Merge "Let launcher control wallpaper zoom"
diff --git a/Android.bp b/Android.bp
index 3fff2d4..b6483a0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -327,7 +327,6 @@
             "rs/java",
             "sax/java",
             "telecomm/java",
-            "wifi/aidl-export",
         ],
     },
 }
@@ -346,6 +345,7 @@
         "android.hardware.cas-V1.1-java",
         "android.hardware.cas-V1.2-java",
         "android.hardware.contexthub-V1.0-java",
+        "android.hardware.contexthub-V1.1-java",
         "android.hardware.gnss-V1.0-java",
         "android.hardware.gnss-V2.1-java",
         "android.hardware.health-V1.0-java-constants",
@@ -392,7 +392,7 @@
 
     exclude_srcs: [
         // See comment on framework-atb-backward-compatibility module below
-        "core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java",
+        "core/java/android/content/pm/AndroidTestBaseUpdater.java",
     ],
 
     sdk_version: "core_platform",
@@ -596,7 +596,7 @@
     installable: true,
     libs: ["app-compat-annotations"],
     srcs: [
-        "core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java",
+        "core/java/android/content/pm/AndroidTestBaseUpdater.java",
     ],
 }
 
@@ -687,6 +687,7 @@
     srcs: [
         "core/java/android/annotation/CallbackExecutor.java",
         "core/java/android/annotation/CheckResult.java",
+        "core/java/android/annotation/CurrentTimeMillisLong.java",
         "core/java/android/annotation/IntDef.java",
         "core/java/android/annotation/IntRange.java",
         "core/java/android/annotation/NonNull.java",
@@ -1028,22 +1029,6 @@
     },
 }
 
-
-subdirs = [
-    "cmds/*",
-    "core/*",
-    "libs/*",
-    "media/*",
-    "proto",
-    "tools/*",
-    "native/android",
-    "native/graphics/jni",
-]
-
-optional_subdirs = [
-    "core/tests/utiltests/jni",
-]
-
 // TODO(b/77285514): remove this once the last few hidl interfaces have been
 // updated to use hwbinder.stubs.
 java_library {
@@ -1103,13 +1088,6 @@
 }
 
 filegroup {
-    name: "framework-annotation-nonnull-srcs",
-    srcs: [
-        "core/java/android/annotation/NonNull.java",
-    ],
-}
-
-filegroup {
     name: "framework-media-annotation-srcs",
     srcs: [
         ":framework-annotations",
@@ -1126,7 +1104,6 @@
     srcs: [
         ":framework-annotations",
         "core/java/android/annotation/BytesLong.java",
-        "core/java/android/annotation/CurrentTimeMillisLong.java",
         "core/java/android/annotation/CurrentTimeSecondsLong.java",
         "core/java/android/annotation/DurationMillisLong.java",
     ],
@@ -1326,7 +1303,6 @@
     libs: [
         "framework-minus-apex",
         "unsupportedappusage",
-        "ike-stubs",
     ],
     static_libs: [
         "libphonenumber-platform",
diff --git a/StubLibraries.bp b/StubLibraries.bp
index 4616ced..7f23df7 100644
--- a/StubLibraries.bp
+++ b/StubLibraries.bp
@@ -49,7 +49,6 @@
         ":opt-net-voip-srcs",
         ":core-current-stubs-source",
         ":core_public_api_files",
-        ":ike-api-srcs",
     ],
     // TODO(b/147699819): remove below aidl includes.
     aidl: {
diff --git a/apex/blobstore/TEST_MAPPING b/apex/blobstore/TEST_MAPPING
index 25a1537..6d3c0d7 100644
--- a/apex/blobstore/TEST_MAPPING
+++ b/apex/blobstore/TEST_MAPPING
@@ -4,6 +4,9 @@
       "name": "CtsBlobStoreTestCases"
     },
     {
+      "name": "CtsBlobStoreHostTestCases"
+    },
+    {
       "name": "FrameworksMockingServicesTests",
       "options": [
         {
@@ -12,4 +15,4 @@
       ]
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
index d4ceabd..18b1108 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreManagerService.java
@@ -96,10 +96,12 @@
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
+import java.util.Random;
 import java.util.Set;
 
 /**
@@ -122,8 +124,15 @@
 
     // Contains all ids that are currently in use.
     @GuardedBy("mBlobsLock")
+    private final ArraySet<Long> mActiveBlobIds = new ArraySet<>();
+    // Contains all ids that are currently in use and those that were in use but got deleted in the
+    // current boot session.
+    @GuardedBy("mBlobsLock")
     private final ArraySet<Long> mKnownBlobIds = new ArraySet<>();
 
+    // Random number generator for new session ids.
+    private final Random mRandom = new SecureRandom();
+
     private final Context mContext;
     private final Handler mHandler;
     private final Injector mInjector;
@@ -181,7 +190,16 @@
 
     @GuardedBy("mBlobsLock")
     private long generateNextSessionIdLocked() {
-        return ++mCurrentMaxSessionId;
+        // Logic borrowed from PackageInstallerService.
+        int n = 0;
+        long sessionId;
+        do {
+            sessionId = Math.abs(mRandom.nextLong());
+            if (mKnownBlobIds.indexOf(sessionId) < 0 && sessionId != 0) {
+                return sessionId;
+            }
+        } while (n++ < 32);
+        throw new IllegalStateException("Failed to allocate session ID");
     }
 
     private void registerReceivers() {
@@ -228,15 +246,22 @@
     }
 
     @VisibleForTesting
-    void addKnownIdsForTest(long... knownIds) {
+    void addActiveIdsForTest(long... activeIds) {
         synchronized (mBlobsLock) {
-            for (long id : knownIds) {
-                mKnownBlobIds.add(id);
+            for (long id : activeIds) {
+                addActiveBlobIdLocked(id);
             }
         }
     }
 
     @VisibleForTesting
+    Set<Long> getActiveIdsForTest() {
+        synchronized (mBlobsLock) {
+            return mActiveBlobIds;
+        }
+    }
+
+    @VisibleForTesting
     Set<Long> getKnownIdsForTest() {
         synchronized (mBlobsLock) {
             return mKnownBlobIds;
@@ -246,7 +271,7 @@
     @GuardedBy("mBlobsLock")
     private void addSessionForUserLocked(BlobStoreSession session, int userId) {
         getUserSessionsLocked(userId).put(session.getSessionId(), session);
-        mKnownBlobIds.add(session.getSessionId());
+        addActiveBlobIdLocked(session.getSessionId());
     }
 
     @GuardedBy("mBlobsLock")
@@ -258,7 +283,13 @@
     private void addBlobForUserLocked(BlobMetadata blobMetadata,
             ArrayMap<BlobHandle, BlobMetadata> userBlobs) {
         userBlobs.put(blobMetadata.getBlobHandle(), blobMetadata);
-        mKnownBlobIds.add(blobMetadata.getBlobId());
+        addActiveBlobIdLocked(blobMetadata.getBlobId());
+    }
+
+    @GuardedBy("mBlobsLock")
+    private void addActiveBlobIdLocked(long id) {
+        mActiveBlobIds.add(id);
+        mKnownBlobIds.add(id);
     }
 
     private long createSessionInternal(BlobHandle blobHandle,
@@ -334,7 +365,8 @@
                 throw new SecurityException("Caller not allowed to access " + blobHandle
                         + "; callingUid=" + callingUid + ", callingPackage=" + callingPackage);
             }
-            if (leaseExpiryTimeMillis != 0 && leaseExpiryTimeMillis > blobHandle.expiryTimeMillis) {
+            if (leaseExpiryTimeMillis != 0 && blobHandle.expiryTimeMillis != 0
+                    && leaseExpiryTimeMillis > blobHandle.expiryTimeMillis) {
                 throw new IllegalArgumentException(
                         "Lease expiry cannot be later than blobs expiry time");
             }
@@ -384,24 +416,27 @@
     }
 
     private void onStateChangedInternal(@NonNull BlobStoreSession session) {
-        synchronized (mBlobsLock) {
-            switch (session.getState()) {
-                case STATE_ABANDONED:
-                case STATE_VERIFIED_INVALID:
-                    session.getSessionFile().delete();
+        switch (session.getState()) {
+            case STATE_ABANDONED:
+            case STATE_VERIFIED_INVALID:
+                session.getSessionFile().delete();
+                synchronized (mBlobsLock) {
                     getUserSessionsLocked(UserHandle.getUserId(session.getOwnerUid()))
                             .remove(session.getSessionId());
-                    mKnownBlobIds.remove(session.getSessionId());
+                    mActiveBlobIds.remove(session.getSessionId());
                     if (LOGV) {
                         Slog.v(TAG, "Session is invalid; deleted " + session);
                     }
-                    break;
-                case STATE_COMMITTED:
-                    session.verifyBlobData();
-                    break;
-                case STATE_VERIFIED_VALID:
+                }
+                break;
+            case STATE_COMMITTED:
+                session.verifyBlobData();
+                break;
+            case STATE_VERIFIED_VALID:
+                synchronized (mBlobsLock) {
                     final int userId = UserHandle.getUserId(session.getOwnerUid());
-                    final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(userId);
+                    final ArrayMap<BlobHandle, BlobMetadata> userBlobs = getUserBlobsLocked(
+                            userId);
                     BlobMetadata blob = userBlobs.get(session.getBlobHandle());
                     if (blob == null) {
                         blob = new BlobMetadata(mContext,
@@ -424,11 +459,13 @@
                     if (LOGV) {
                         Slog.v(TAG, "Successfully committed session " + session);
                     }
-                    break;
-                default:
-                    Slog.wtf(TAG, "Invalid session state: "
-                            + stateToString(session.getState()));
-            }
+                }
+                break;
+            default:
+                Slog.wtf(TAG, "Invalid session state: "
+                        + stateToString(session.getState()));
+        }
+        synchronized (mBlobsLock) {
             try {
                 writeBlobSessionsLocked();
             } catch (Exception e) {
@@ -485,6 +522,9 @@
         if (sessionsIndexFile == null) {
             Slog.wtf(TAG, "Error creating sessions index file");
             return;
+        } else if (!sessionsIndexFile.exists()) {
+            Slog.w(TAG, "Sessions index file not available: " + sessionsIndexFile.getBaseFile());
+            return;
         }
 
         mSessions.clear();
@@ -574,6 +614,9 @@
         if (blobsIndexFile == null) {
             Slog.wtf(TAG, "Error creating blobs index file");
             return;
+        } else if (!blobsIndexFile.exists()) {
+            Slog.w(TAG, "Blobs index file not available: " + blobsIndexFile.getBaseFile());
+            return;
         }
 
         mBlobsMap.clear();
@@ -698,7 +741,7 @@
                 if (session.getOwnerUid() == uid
                         && session.getOwnerPackageName().equals(packageName)) {
                     session.getSessionFile().delete();
-                    mKnownBlobIds.remove(session.getSessionId());
+                    mActiveBlobIds.remove(session.getSessionId());
                     indicesToRemove.add(i);
                 }
             }
@@ -718,7 +761,7 @@
                 // Delete the blob if it doesn't have any active leases.
                 if (!blobMetadata.hasLeases()) {
                     blobMetadata.getBlobFile().delete();
-                    mKnownBlobIds.remove(blobMetadata.getBlobId());
+                    mActiveBlobIds.remove(blobMetadata.getBlobId());
                     indicesToRemove.add(i);
                 }
             }
@@ -741,7 +784,7 @@
                 for (int i = 0, count = userSessions.size(); i < count; ++i) {
                     final BlobStoreSession session = userSessions.valueAt(i);
                     session.getSessionFile().delete();
-                    mKnownBlobIds.remove(session.getSessionId());
+                    mActiveBlobIds.remove(session.getSessionId());
                 }
             }
 
@@ -751,7 +794,7 @@
                 for (int i = 0, count = userBlobs.size(); i < count; ++i) {
                     final BlobMetadata blobMetadata = userBlobs.valueAt(i);
                     blobMetadata.getBlobFile().delete();
-                    mKnownBlobIds.remove(blobMetadata.getBlobId());
+                    mActiveBlobIds.remove(blobMetadata.getBlobId());
                 }
             }
             if (LOGV) {
@@ -771,7 +814,7 @@
             for (File file : blobsDir.listFiles()) {
                 try {
                     final long id = Long.parseLong(file.getName());
-                    if (mKnownBlobIds.indexOf(id) < 0) {
+                    if (mActiveBlobIds.indexOf(id) < 0) {
                         filesToDelete.add(file);
                         deletedBlobIds.add(id);
                     }
@@ -806,7 +849,7 @@
 
                 if (shouldRemove) {
                     blobMetadata.getBlobFile().delete();
-                    mKnownBlobIds.remove(blobMetadata.getBlobId());
+                    mActiveBlobIds.remove(blobMetadata.getBlobId());
                     deletedBlobIds.add(blobMetadata.getBlobId());
                 }
                 return shouldRemove;
@@ -815,12 +858,9 @@
         writeBlobsInfoAsync();
 
         // Cleanup any stale sessions.
-        final ArrayList<Integer> indicesToRemove = new ArrayList<>();
         for (int i = 0, userCount = mSessions.size(); i < userCount; ++i) {
             final LongSparseArray<BlobStoreSession> userSessions = mSessions.valueAt(i);
-            indicesToRemove.clear();
-            for (int j = 0, sessionsCount = userSessions.size(); j < sessionsCount; ++j) {
-                final BlobStoreSession blobStoreSession = userSessions.valueAt(j);
+            userSessions.removeIf((sessionId, blobStoreSession) -> {
                 boolean shouldRemove = false;
 
                 // Cleanup sessions which haven't been modified in a while.
@@ -836,14 +876,11 @@
 
                 if (shouldRemove) {
                     blobStoreSession.getSessionFile().delete();
-                    mKnownBlobIds.remove(blobStoreSession.getSessionId());
-                    indicesToRemove.add(j);
+                    mActiveBlobIds.remove(blobStoreSession.getSessionId());
                     deletedBlobIds.add(blobStoreSession.getSessionId());
                 }
-            }
-            for (int j = 0; j < indicesToRemove.size(); ++j) {
-                userSessions.removeAt(indicesToRemove.get(j));
-            }
+                return shouldRemove;
+            });
         }
         if (LOGV) {
             Slog.v(TAG, "Completed idle maintenance; deleted "
@@ -883,7 +920,7 @@
             }
             blobMetadata.getBlobFile().delete();
             userBlobs.remove(blobHandle);
-            mKnownBlobIds.remove(blobMetadata.getBlobId());
+            mActiveBlobIds.remove(blobMetadata.getBlobId());
             writeBlobsInfoAsync();
         }
     }
diff --git a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
index 80b4235..d33a09f 100644
--- a/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
+++ b/apex/blobstore/service/java/com/android/server/blob/BlobStoreSession.java
@@ -514,7 +514,7 @@
     static BlobStoreSession createFromXml(@NonNull XmlPullParser in, int version,
             @NonNull Context context, @NonNull SessionStateChangeListener stateChangeListener)
             throws IOException, XmlPullParserException {
-        final int sessionId = XmlUtils.readIntAttribute(in, ATTR_ID);
+        final long sessionId = XmlUtils.readLongAttribute(in, ATTR_ID);
         final String ownerPackageName = XmlUtils.readStringAttribute(in, ATTR_PACKAGE);
         final int ownerUid = XmlUtils.readIntAttribute(in, ATTR_UID);
 
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index b96161a..4c98b5f 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -77,11 +77,11 @@
 
     /**
      * @hide
-     * @deprecated use {@link #getReasonCodeDescription(int)}
      */
-    @Deprecated
-    public static String getReasonName(int reason) {
-        switch (reason) {
+    // TODO(142420609): make it @SystemApi for mainline
+    @NonNull
+    public static String getReasonCodeDescription(int reasonCode) {
+        switch (reasonCode) {
             case REASON_CANCELED: return "canceled";
             case REASON_CONSTRAINTS_NOT_SATISFIED: return "constraints";
             case REASON_PREEMPT: return "preempt";
@@ -89,7 +89,7 @@
             case REASON_DEVICE_IDLE: return "device_idle";
             case REASON_DEVICE_THERMAL: return "thermal";
             case REASON_RESTRAINED: return "restrained";
-            default: return "unknown:" + reason;
+            default: return "unknown:" + reasonCode;
         }
     }
 
@@ -100,13 +100,6 @@
         return JOB_STOP_REASON_CODES;
     }
 
-    /** @hide */
-    // @SystemApi TODO make it a system api for mainline
-    @NonNull
-    public static String getReasonCodeDescription(int reasonCode) {
-        return getReasonName(reasonCode);
-    }
-
     @UnsupportedAppUsage
     private final int jobId;
     private final PersistableBundle extras;
diff --git a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
index dc72d6d..f8b598a 100644
--- a/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
+++ b/apex/jobscheduler/framework/java/com/android/server/usage/AppStandbyInternal.java
@@ -147,7 +147,7 @@
 
     void postReportExemptedSyncStart(String packageName, int userId);
 
-    void dumpUser(IndentingPrintWriter idpw, int userId, String pkg);
+    void dumpUser(IndentingPrintWriter idpw, int userId, List<String> pkgs);
 
     void dumpState(String[] args, PrintWriter pw);
 
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
index e28e5bd..d050347 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobPackageTracker.java
@@ -359,7 +359,8 @@
                             }
                             pw.print(pe.stopReasons.valueAt(k));
                             pw.print("x ");
-                            pw.print(JobParameters.getReasonName(pe.stopReasons.keyAt(k)));
+                            pw.print(JobParameters
+                                    .getReasonCodeDescription(pe.stopReasons.keyAt(k)));
                         }
                         pw.println();
                     }
@@ -606,8 +607,9 @@
                 if (reason != null) {
                     pw.print(mEventReasons[index]);
                 } else {
-                    pw.print(JobParameters.getReasonName((mEventCmds[index] & EVENT_STOP_REASON_MASK)
-                            >> EVENT_STOP_REASON_SHIFT));
+                    pw.print(JobParameters.getReasonCodeDescription(
+                            (mEventCmds[index] & EVENT_STOP_REASON_MASK)
+                                    >> EVENT_STOP_REASON_SHIFT));
                 }
             }
             pw.println();
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
index ff7944d..c1e529f 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1963,7 +1963,7 @@
                 if (restriction != null) {
                     final int reason = restriction.getReason();
                     serviceContext.cancelExecutingJobLocked(reason,
-                            "restricted due to " + JobParameters.getReasonName(reason));
+                            "restricted due to " + JobParameters.getReasonCodeDescription(reason));
                 }
             }
         }
@@ -3110,7 +3110,7 @@
                             final JobRestriction restriction = mJobRestrictions.get(i);
                             if (restriction.isJobRestricted(job)) {
                                 final int reason = restriction.getReason();
-                                pw.write(" " + JobParameters.getReasonName(reason) + "[" + reason + "]");
+                                pw.print(" " + JobParameters.getReasonCodeDescription(reason));
                             }
                         }
                     } else {
diff --git a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
index 789f20b..b63cc19 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java
@@ -39,6 +39,7 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.FrameworkStatsLog;
 import com.android.server.LocalServices;
 import com.android.server.job.GrantedUriPermissions;
@@ -97,6 +98,15 @@
                     | CONSTRAINT_IDLE;
 
     /**
+     * Standard media URIs that contain the media files that might be important to the user.
+     * @see #mHasMediaBackupExemption
+     */
+    private static final Uri[] MEDIA_URIS_FOR_STANDBY_EXEMPTION = {
+            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+            MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+    };
+
+    /**
      * The constraints that we want to log to statsd.
      *
      * Constraints that can be inferred from other atoms have been excluded to avoid logging too
@@ -441,13 +451,13 @@
         if (latestRunTimeElapsedMillis != NO_LATEST_RUNTIME) {
             requiredConstraints |= CONSTRAINT_DEADLINE;
         }
-        boolean mediaOnly = false;
+        boolean exemptedMediaUrisOnly = false;
         if (job.getTriggerContentUris() != null) {
             requiredConstraints |= CONSTRAINT_CONTENT_TRIGGER;
-            mediaOnly = true;
+            exemptedMediaUrisOnly = true;
             for (JobInfo.TriggerContentUri uri : job.getTriggerContentUris()) {
-                if (!MediaStore.AUTHORITY.equals(uri.getUri().getAuthority())) {
-                    mediaOnly = false;
+                if (!ArrayUtils.contains(MEDIA_URIS_FOR_STANDBY_EXEMPTION, uri.getUri())) {
+                    exemptedMediaUrisOnly = false;
                     break;
                 }
             }
@@ -475,8 +485,8 @@
             job.getRequiredNetwork().networkCapabilities.setSingleUid(this.sourceUid);
         }
         final JobSchedulerInternal jsi = LocalServices.getService(JobSchedulerInternal.class);
-        mHasMediaBackupExemption = !job.hasLateConstraint() && mediaOnly && requiresNetwork
-                && this.sourcePackageName.equals(jsi.getMediaBackupPackage());
+        mHasMediaBackupExemption = !job.hasLateConstraint() && exemptedMediaUrisOnly
+                && requiresNetwork && this.sourcePackageName.equals(jsi.getMediaBackupPackage());
     }
 
     /** Copy constructor: used specifically when cloning JobStatus objects for persistence,
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
index 9d6e012..932c25d 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppIdleHistory.java
@@ -41,6 +41,7 @@
 import android.util.Xml;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.IndentingPrintWriter;
 
@@ -58,6 +59,7 @@
 import java.io.IOException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Keeps track of recent active state changes in apps.
@@ -721,7 +723,7 @@
         }
     }
 
-    public void dump(IndentingPrintWriter idpw, int userId, String pkg) {
+    public void dump(IndentingPrintWriter idpw, int userId, List<String> pkgs) {
         idpw.println("App Standby States:");
         idpw.increaseIndent();
         ArrayMap<String, AppUsageHistory> userHistory = mIdleHistory.get(userId);
@@ -733,7 +735,7 @@
         for (int p = 0; p < P; p++) {
             final String packageName = userHistory.keyAt(p);
             final AppUsageHistory appUsageHistory = userHistory.valueAt(p);
-            if (pkg != null && !pkg.equals(packageName)) {
+            if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(packageName)) {
                 continue;
             }
             idpw.print("package=" + packageName);
diff --git a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
index e343478..a4ab31d 100644
--- a/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
+++ b/apex/jobscheduler/service/java/com/android/server/usage/AppStandbyController.java
@@ -65,6 +65,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.CrossProfileAppsInternal;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
@@ -283,6 +284,12 @@
      * start is the first usage of the app
      */
     long mInitialForegroundServiceStartTimeoutMillis;
+    /**
+     * User usage that would elevate an app's standby bucket will also elevate the standby bucket of
+     * cross profile connected apps. Explicit standby bucket setting via
+     * {@link #setAppStandbyBucket(String, int, int, int, int)} will not be propagated.
+     */
+    boolean mLinkCrossProfileApps;
 
     private volatile boolean mAppIdleEnabled;
     private boolean mIsCharging;
@@ -445,10 +452,12 @@
                     continue;
                 }
                 if (!packageName.equals(providerPkgName)) {
+                    final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName,
+                            userId);
                     synchronized (mAppIdleLock) {
-                        reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE,
-                                REASON_SUB_USAGE_SYNC_ADAPTER, elapsedRealtime,
-                                mSyncAdapterTimeoutMillis);
+                        reportNoninteractiveUsageCrossUserLocked(packageName, userId,
+                                STANDBY_BUCKET_ACTIVE, REASON_SUB_USAGE_SYNC_ADAPTER,
+                                elapsedRealtime, mSyncAdapterTimeoutMillis, linkedProfiles);
                     }
                 }
             } catch (PackageManager.NameNotFoundException e) {
@@ -477,10 +486,10 @@
         }
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
-
+        final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId);
         synchronized (mAppIdleLock) {
-            reportNoninteractiveUsageLocked(packageName, userId, bucketToPromote,
-                    usageReason, elapsedRealtime, durationMillis);
+            reportNoninteractiveUsageCrossUserLocked(packageName, userId, bucketToPromote,
+                    usageReason, elapsedRealtime, durationMillis, linkedProfiles);
         }
     }
 
@@ -492,10 +501,11 @@
             final int currentBucket =
                     mAppIdleHistory.getAppStandbyBucket(packageName, userId, elapsedRealtime);
             if (currentBucket == STANDBY_BUCKET_NEVER) {
+                final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId);
                 // Bring the app out of the never bucket
-                reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_WORKING_SET,
-                        REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED, elapsedRealtime,
-                        mUnexemptedSyncScheduledTimeoutMillis);
+                reportNoninteractiveUsageCrossUserLocked(packageName, userId,
+                        STANDBY_BUCKET_WORKING_SET, REASON_SUB_USAGE_UNEXEMPTED_SYNC_SCHEDULED,
+                        elapsedRealtime, mUnexemptedSyncScheduledTimeoutMillis, linkedProfiles);
             }
         }
     }
@@ -504,14 +514,39 @@
         if (!mAppIdleEnabled) return;
 
         final long elapsedRealtime = mInjector.elapsedRealtime();
-
+        final List<UserHandle> linkedProfiles = getCrossProfileTargets(packageName, userId);
         synchronized (mAppIdleLock) {
-            reportNoninteractiveUsageLocked(packageName, userId, STANDBY_BUCKET_ACTIVE,
+            reportNoninteractiveUsageCrossUserLocked(packageName, userId, STANDBY_BUCKET_ACTIVE,
                     REASON_SUB_USAGE_EXEMPTED_SYNC_START, elapsedRealtime,
-                    mExemptedSyncStartTimeoutMillis);
+                    mExemptedSyncStartTimeoutMillis, linkedProfiles);
         }
     }
 
+    /**
+     * Helper method to report indirect user usage of an app and handle reporting the usage
+     * against cross profile connected apps. <br>
+     * Use {@link #reportNoninteractiveUsageLocked(String, int, int, int, long, long)} if
+     * cross profile connected apps do not need to be handled.
+     */
+    private void reportNoninteractiveUsageCrossUserLocked(String packageName, int userId,
+            int bucket, int subReason, long elapsedRealtime, long nextCheckDelay,
+            List<UserHandle> otherProfiles) {
+        reportNoninteractiveUsageLocked(packageName, userId, bucket, subReason, elapsedRealtime,
+                nextCheckDelay);
+        final int size = otherProfiles.size();
+        for (int profileIndex = 0; profileIndex < size; profileIndex++) {
+            final int otherUserId = otherProfiles.get(profileIndex).getIdentifier();
+            reportNoninteractiveUsageLocked(packageName, otherUserId, bucket, subReason,
+                    elapsedRealtime, nextCheckDelay);
+        }
+    }
+
+    /**
+     * Helper method to report indirect user usage of an app. <br>
+     * Use
+     * {@link #reportNoninteractiveUsageCrossUserLocked(String, int, int, int, long, long, List)}
+     * if cross profile connected apps need to be handled.
+     */
     private void reportNoninteractiveUsageLocked(String packageName, int userId, int bucket,
             int subReason, long elapsedRealtime, long nextCheckDelay) {
         final AppUsageHistory appUsage = mAppIdleHistory.reportUsage(packageName, userId, bucket,
@@ -766,8 +801,16 @@
                 || eventType == UsageEvents.Event.SLICE_PINNED
                 || eventType == UsageEvents.Event.SLICE_PINNED_PRIV
                 || eventType == UsageEvents.Event.FOREGROUND_SERVICE_START)) {
+            final String pkg = event.getPackageName();
+            final List<UserHandle> linkedProfiles = getCrossProfileTargets(pkg, userId);
             synchronized (mAppIdleLock) {
-                reportEventLocked(event.getPackageName(), eventType, elapsedRealtime, userId);
+                reportEventLocked(pkg, eventType, elapsedRealtime, userId);
+
+                final int size = linkedProfiles.size();
+                for (int profileIndex = 0; profileIndex < size; profileIndex++) {
+                    final int linkedUserId = linkedProfiles.get(profileIndex).getIdentifier();
+                    reportEventLocked(pkg, eventType, elapsedRealtime, linkedUserId);
+                }
             }
         }
     }
@@ -826,6 +869,16 @@
         }
     }
 
+    /**
+     * Note: don't call this with the lock held since it makes calls to other system services.
+     */
+    private @NonNull List<UserHandle> getCrossProfileTargets(String pkg, int userId) {
+        synchronized (mAppIdleLock) {
+            if (!mLinkCrossProfileApps) return Collections.emptyList();
+        }
+        return mInjector.getValidCrossProfileTargets(pkg, userId);
+    }
+
     private int usageEventToSubReason(int eventType) {
         switch (eventType) {
             case UsageEvents.Event.ACTIVITY_RESUMED: return REASON_SUB_USAGE_MOVE_TO_FOREGROUND;
@@ -1505,9 +1558,9 @@
     }
 
     @Override
-    public void dumpUser(IndentingPrintWriter idpw, int userId, String pkg) {
+    public void dumpUser(IndentingPrintWriter idpw, int userId, List<String> pkgs) {
         synchronized (mAppIdleLock) {
-            mAppIdleHistory.dump(idpw, userId, pkg);
+            mAppIdleHistory.dump(idpw, userId, pkgs);
         }
     }
 
@@ -1589,6 +1642,7 @@
         private PackageManagerInternal mPackageManagerInternal;
         private DisplayManager mDisplayManager;
         private PowerManager mPowerManager;
+        private CrossProfileAppsInternal mCrossProfileAppsInternal;
         int mBootPhase;
         /**
          * The minimum amount of time required since the last user interaction before an app can be
@@ -1620,6 +1674,8 @@
                         Context.DISPLAY_SERVICE);
                 mPowerManager = mContext.getSystemService(PowerManager.class);
                 mBatteryManager = mContext.getSystemService(BatteryManager.class);
+                mCrossProfileAppsInternal = LocalServices.getService(
+                        CrossProfileAppsInternal.class);
 
                 final ActivityManager activityManager =
                         (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
@@ -1727,6 +1783,17 @@
         public boolean isDeviceIdleMode() {
             return mPowerManager.isDeviceIdleMode();
         }
+
+        public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) {
+            final int uid = mPackageManagerInternal.getPackageUidInternal(pkg, 0, userId);
+            if (uid < 0
+                    || !mPackageManagerInternal.getPackage(uid).isCrossProfile()
+                    || !mCrossProfileAppsInternal
+                            .verifyUidHasInteractAcrossProfilePermission(pkg, uid)) {
+                return Collections.emptyList();
+            }
+            return mCrossProfileAppsInternal.getTargetUserProfiles(pkg, userId);
+        }
     }
 
     class AppStandbyHandler extends Handler {
@@ -1857,6 +1924,8 @@
                 "initial_foreground_service_start_duration";
         private static final String KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS =
                 "auto_restricted_bucket_delay_ms";
+        private static final String KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS =
+                "cross_profile_apps_share_standby_buckets";
         public static final long DEFAULT_STRONG_USAGE_TIMEOUT = 1 * ONE_HOUR;
         public static final long DEFAULT_NOTIFICATION_TIMEOUT = 12 * ONE_HOUR;
         public static final long DEFAULT_SYSTEM_UPDATE_TIMEOUT = 2 * ONE_HOUR;
@@ -1868,6 +1937,7 @@
         public static final long DEFAULT_UNEXEMPTED_SYNC_SCHEDULED_TIMEOUT = 10 * ONE_MINUTE;
         public static final long DEFAULT_INITIAL_FOREGROUND_SERVICE_START_TIMEOUT = 30 * ONE_MINUTE;
         public static final long DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS = ONE_DAY;
+        public static final boolean DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS = true;
 
         private final KeyValueListParser mParser = new KeyValueListParser(',');
 
@@ -1973,6 +2043,10 @@
                         mParser.getDurationMillis(KEY_AUTO_RESTRICTED_BUCKET_DELAY_MS,
                                 COMPRESS_TIME
                                         ? ONE_MINUTE : DEFAULT_AUTO_RESTRICTED_BUCKET_DELAY_MS));
+
+                mLinkCrossProfileApps = mParser.getBoolean(
+                        KEY_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS,
+                        DEFAULT_CROSS_PROFILE_APPS_SHARE_STANDBY_BUCKETS);
             }
 
             // Check if app_idle_enabled has changed. Do this after getting the rest of the settings
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 7d18578..11d3a68 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -56,6 +56,7 @@
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
@@ -375,13 +376,13 @@
     }
 
     /**
-     * Thrown if all extractors implementations provided to {@link #create} failed to sniff the
-     * input content.
+     * Thrown if all parser implementations provided to {@link #create} failed to sniff the input
+     * content.
      */
     public static final class UnrecognizedInputFormatException extends IOException {
 
         /**
-         * Creates a new instance which signals that the extractors with the given names failed to
+         * Creates a new instance which signals that the parsers with the given names failed to
          * parse the input.
          */
         @NonNull
@@ -389,7 +390,7 @@
         private static UnrecognizedInputFormatException createForExtractors(
                 @NonNull String... extractorNames) {
             StringBuilder builder = new StringBuilder();
-            builder.append("None of the available extractors ( ");
+            builder.append("None of the available parsers ( ");
             builder.append(extractorNames[0]);
             for (int i = 1; i < extractorNames.length; i++) {
                 builder.append(", ");
@@ -404,17 +405,149 @@
         }
     }
 
+    // Public constants.
+
+    /**
+     * Sets whether constant bitrate seeking should be enabled for exo.AdtsParser. {@code boolean}
+     * expected. Default value is {@code false}.
+     */
+    public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING =
+            "exo.AdtsParser.enableCbrSeeking";
+    /**
+     * Sets whether constant bitrate seeking should be enabled for exo.AmrParser. {@code boolean}
+     * expected. Default value is {@code false}.
+     */
+    public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "exo.AmrParser.enableCbrSeeking";
+    /**
+     * Sets whether the ID3 track should be disabled for exo.FlacParser. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_FLAC_DISABLE_ID3 = "exo.FlacParser.disableId3";
+    /**
+     * Sets whether exo.FragmentedMp4Parser should ignore edit lists. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_FMP4_IGNORE_EDIT_LISTS =
+            "exo.FragmentedMp4Parser.ignoreEditLists";
+    /**
+     * Sets whether exo.FragmentedMp4Parser should ignore the tfdt box. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_FMP4_IGNORE_TFDT_BOX =
+            "exo.FragmentedMp4Parser.ignoreTfdtBox";
+    /**
+     * Sets whether exo.FragmentedMp4Parser should treat all video frames as key frames. {@code
+     * boolean} expected. Default value is {@code false}.
+     */
+    public static final String PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES =
+            "exo.FragmentedMp4Parser.treatVideoFramesAsKeyframes";
+    /**
+     * Sets whether exo.MatroskaParser should avoid seeking to the cues element. {@code boolean}
+     * expected. Default value is {@code false}.
+     *
+     * <p>If this flag is enabled and the cues element occurs after the first cluster, then the
+     * media is treated as unseekable.
+     */
+    public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING =
+            "exo.MatroskaParser.disableCuesSeeking";
+    /**
+     * Sets whether the ID3 track should be disabled for exo.Mp3Parser. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_MP3_DISABLE_ID3 = "exo.Mp3Parser.disableId3";
+    /**
+     * Sets whether constant bitrate seeking should be enabled for exo.Mp3Parser. {@code boolean}
+     * expected. Default value is {@code false}.
+     */
+    public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "exo.Mp3Parser.enableCbrSeeking";
+    /**
+     * Sets whether exo.Mp3Parser should generate a time-to-byte mapping. {@code boolean} expected.
+     * Default value is {@code false}.
+     *
+     * <p>Enabling this flag may require to scan a significant portion of the file to compute a seek
+     * point. Therefore, it should only be used if:
+     *
+     * <ul>
+     *   <li>the file is small, or
+     *   <li>the bitrate is variable (or the type of bitrate is unknown) and the seeking metadata
+     *       provided in the file is not precise enough (or is not present).
+     * </ul>
+     */
+    public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING =
+            "exo.Mp3Parser.enableIndexSeeking";
+    /**
+     * Sets whether exo.Mp4Parser should ignore edit lists. {@code boolean} expected. Default value
+     * is {@code false}.
+     */
+    public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "exo.Mp4Parser.ignoreEditLists";
+    /**
+     * Sets the operation mode for exo.TsParser. {@code String} expected. Valid values are {@code
+     * "single_pmt"}, {@code "multi_pmt"}, and {@code "hls"}. Default value is {@code "single_pmt"}.
+     *
+     * <p>The operation modes alter the way exo.TsParser behaves so that it can handle certain kinds
+     * of commonly-occurring malformed media.
+     *
+     * <ul>
+     *   <li>{@code "single_pmt"}: Only the first found PMT is parsed. Others are ignored, even if
+     *       more PMTs are declared in the PAT.
+     *   <li>{@code "multi_pmt"}: Behave as described in ISO/IEC 13818-1.
+     *   <li>{@code "hls"}: Enable {@code "single_pmt"} mode, and ignore continuity counters.
+     * </ul>
+     */
+    public static final String PARAMETER_TS_MODE = "exo.TsParser.mode";
+    /**
+     * Sets whether exo.TsParser should treat samples consisting of non-IDR I slices as
+     * synchronization samples (key-frames). {@code boolean} expected. Default value is {@code
+     * false}.
+     */
+    public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES =
+            "exo.TsParser.allowNonIdrAvcKeyframes";
+    /**
+     * Sets whether exo.TsParser should ignore AAC elementary streams. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "exo.TsParser.ignoreAacStream";
+    /**
+     * Sets whether exo.TsParser should ignore AVC elementary streams. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "exo.TsParser.ignoreAvcStream";
+    /**
+     * Sets whether exo.TsParser should ignore splice information streams. {@code boolean} expected.
+     * Default value is {@code false}.
+     */
+    public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM =
+            "exo.TsParser.ignoreSpliceInfoStream";
+    /**
+     * Sets whether exo.TsParser should split AVC stream into access units based on slice headers.
+     * {@code boolean} expected. Default value is {@code false}.
+     *
+     * <p>This flag should be left disabled if the stream contains access units delimiters in order
+     * to avoid unnecessary computational costs.
+     */
+    public static final String PARAMETER_TS_DETECT_ACCESS_UNITS =
+            "exo.TsParser.ignoreDetectAccessUnits";
+    /**
+     * Sets whether exo.TsParser should handle HDMV DTS audio streams. {@code boolean} expected.
+     * Default value is {@code false}.
+     *
+     * <p>Enabling this flag will disable the detection of SCTE subtitles.
+     */
+    public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS =
+            "exo.TsParser.enableHdmvDtsAudioStreams";
+
     // Private constants.
 
     private static final Map<String, ExtractorFactory> EXTRACTOR_FACTORIES_BY_NAME;
+    private static final Map<String, Class> EXPECTED_TYPE_BY_PARAMETER_NAME;
 
     // Instance creation methods.
 
     /**
-     * Creates an instance backed by the extractor with the given {@code name}. The returned
-     * instance will attempt extraction without sniffing the content.
+     * Creates an instance backed by the parser with the given {@code name}. The returned instance
+     * will attempt parsing without sniffing the content.
      *
-     * @param name The name of the extractor that will be associated with the created instance.
+     * @param name The name of the parser that will be associated with the created instance.
      * @param outputConsumer The {@link OutputConsumer} to which track data and samples are pushed.
      * @return A new instance.
      * @throws IllegalArgumentException If an invalid name is provided.
@@ -428,42 +561,43 @@
     }
 
     /**
-     * Creates an instance whose backing extractor will be selected by sniffing the content during
-     * the first {@link #advance} call. Extractor implementations will sniff the content in order of
-     * appearance in {@code extractorNames}.
+     * Creates an instance whose backing parser will be selected by sniffing the content during the
+     * first {@link #advance} call. Parser implementations will sniff the content in order of
+     * appearance in {@code parserNames}.
      *
      * @param outputConsumer The {@link OutputConsumer} to which extracted data is output.
-     * @param extractorNames The names of the extractors to sniff the content with. If empty, a
-     *     default array of names is used.
+     * @param parserNames The names of the parsers to sniff the content with. If empty, a default
+     *     array of names is used.
      * @return A new instance.
      */
     @NonNull
     public static MediaParser create(
-            @NonNull OutputConsumer outputConsumer, @NonNull String... extractorNames) {
-        assertValidNames(extractorNames);
-        if (extractorNames.length == 0) {
-            extractorNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
+            @NonNull OutputConsumer outputConsumer, @NonNull String... parserNames) {
+        assertValidNames(parserNames);
+        if (parserNames.length == 0) {
+            parserNames = EXTRACTOR_FACTORIES_BY_NAME.keySet().toArray(new String[0]);
         }
-        return new MediaParser(outputConsumer, /* sniff= */ true, extractorNames);
+        return new MediaParser(outputConsumer, /* sniff= */ true, parserNames);
     }
 
     // Misc static methods.
 
     /**
-     * Returns an immutable list with the names of the extractors that are suitable for container
+     * Returns an immutable list with the names of the parsers that are suitable for container
      * formats with the given {@link MediaFormat}.
      *
      * <p>TODO: List which properties are taken into account. E.g. MimeType.
      */
     @NonNull
-    public static List<String> getExtractorNames(@NonNull MediaFormat mediaFormat) {
+    public static List<String> getParserNames(@NonNull MediaFormat mediaFormat) {
         throw new UnsupportedOperationException();
     }
 
     // Private fields.
 
+    private final Map<String, Object> mParserParameters;
     private final OutputConsumer mOutputConsumer;
-    private final String[] mExtractorNamesPool;
+    private final String[] mParserNamesPool;
     private final PositionHolder mPositionHolder;
     private final InputReadingDataSource mDataSource;
     private final ExtractorInputAdapter mScratchExtractorInputAdapter;
@@ -477,18 +611,63 @@
     // Public methods.
 
     /**
-     * Returns the name of the backing extractor implementation.
+     * Sets parser-specific parameters which allow customizing behavior.
+     *
+     * <p>Must be called before the first call to {@link #advance}.
+     *
+     * @param parameterName The name of the parameter to set. See {@code PARAMETER_*} constants for
+     *     documentation on possible values.
+     * @param value The value to set for the given {@code parameterName}. See {@code PARAMETER_*}
+     *     constants for documentation on the expected types.
+     * @return This instance, for convenience.
+     * @throws IllegalStateException If called after calling {@link #advance} on the same instance.
+     */
+    @NonNull
+    public MediaParser setParameter(@NonNull String parameterName, @NonNull Object value) {
+        if (mExtractor != null) {
+            throw new IllegalStateException(
+                    "setParameters() must be called before the first advance() call.");
+        }
+        Class expectedType = EXPECTED_TYPE_BY_PARAMETER_NAME.get(parameterName);
+        // Ignore parameter names that are not contained in the map, in case the client is passing
+        // a parameter that is being added in a future version of this library.
+        if (expectedType != null && !expectedType.isInstance(value)) {
+            throw new IllegalArgumentException(
+                    parameterName
+                            + " expects a "
+                            + expectedType.getSimpleName()
+                            + " but a "
+                            + value.getClass().getSimpleName()
+                            + " was passed.");
+        }
+        mParserParameters.put(parameterName, value);
+        return this;
+    }
+
+    /**
+     * Returns whether the given {@code parameterName} is supported by this parser.
+     *
+     * @param parameterName The parameter name to check support for. One of the {@code PARAMETER_*}
+     *     constants.
+     * @return Whether the given {@code parameterName} is supported.
+     */
+    public boolean supportsParameter(@NonNull String parameterName) {
+        return EXPECTED_TYPE_BY_PARAMETER_NAME.containsKey(parameterName);
+    }
+
+    /**
+     * Returns the name of the backing parser implementation.
      *
      * <p>If this instance was creating using {@link #createByName}, the provided name is returned.
      * If this instance was created using {@link #create}, this method will return null until the
-     * first call to {@link #advance}, after which the name of the backing extractor implementation
-     * is returned.
+     * first call to {@link #advance}, after which the name of the backing parser implementation is
+     * returned.
      *
-     * @return The name of the backing extractor implementation, or null if the backing extractor
+     * @return The name of the backing parser implementation, or null if the backing parser
      *     implementation has not yet been selected.
      */
     @Nullable
-    public String getExtractorName() {
+    public String getParserName() {
         return mExtractorName;
     }
 
@@ -499,7 +678,7 @@
      * <p>This method will block until some progress has been made.
      *
      * <p>If this instance was created using {@link #create}. the first call to this method will
-     * sniff the content with the extractors with the provided names.
+     * sniff the content with the parsers with the provided names.
      *
      * @param seekableInputReader The {@link SeekableInputReader} from which to obtain the media
      *     container data.
@@ -520,13 +699,15 @@
         }
         mDataSource.mInputReader = seekableInputReader;
 
-        if (mExtractor == null) {
-            for (String extractorName : mExtractorNamesPool) {
-                Extractor extractor =
-                        EXTRACTOR_FACTORIES_BY_NAME.get(extractorName).createInstance();
+        // TODO: Apply parameters when creating extractor instances.
+        if (mExtractorName != null) {
+            mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
+        } else if (mExtractor == null) {
+            for (String parserName : mParserNamesPool) {
+                Extractor extractor = EXTRACTOR_FACTORIES_BY_NAME.get(parserName).createInstance();
                 try {
                     if (extractor.sniff(mExtractorInput)) {
-                        mExtractorName = extractorName;
+                        mExtractorName = parserName;
                         mExtractor = extractor;
                         mExtractor.init(new ExtractorOutputAdapter());
                         break;
@@ -540,7 +721,7 @@
                 }
             }
             if (mExtractor == null) {
-                throw UnrecognizedInputFormatException.createForExtractors(mExtractorNamesPool);
+                throw UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
             }
             return true;
         }
@@ -586,22 +767,22 @@
      * Releases any acquired resources.
      *
      * <p>After calling this method, this instance becomes unusable and no other methods should be
-     * invoked. DESIGN NOTE: Should be removed. There shouldn't be any resource for releasing.
+     * invoked.
      */
     public void release() {
+        // TODO: Dump media metrics here.
         mExtractorInput = null;
         mExtractor = null;
     }
 
     // Private methods.
 
-    private MediaParser(
-            OutputConsumer outputConsumer, boolean sniff, String... extractorNamesPool) {
+    private MediaParser(OutputConsumer outputConsumer, boolean sniff, String... parserNamesPool) {
+        mParserParameters = new HashMap<>();
         mOutputConsumer = outputConsumer;
-        mExtractorNamesPool = extractorNamesPool;
+        mParserNamesPool = parserNamesPool;
         if (!sniff) {
-            mExtractorName = extractorNamesPool[0];
-            mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
+            mExtractorName = parserNamesPool[0];
         }
         mPositionHolder = new PositionHolder();
         mDataSource = new InputReadingDataSource();
@@ -921,7 +1102,7 @@
                 throw new IllegalArgumentException(
                         "Invalid extractor name: "
                                 + name
-                                + ". Supported extractors are: "
+                                + ". Supported parsers are: "
                                 + TextUtils.join(", ", EXTRACTOR_FACTORIES_BY_NAME.keySet())
                                 + ".");
             }
@@ -933,20 +1114,42 @@
     static {
         // Using a LinkedHashMap to keep the insertion order when iterating over the keys.
         LinkedHashMap<String, ExtractorFactory> extractorFactoriesByName = new LinkedHashMap<>();
-        extractorFactoriesByName.put("exo.Ac3Extractor", Ac3Extractor::new);
-        extractorFactoriesByName.put("exo.Ac4Extractor", Ac4Extractor::new);
-        extractorFactoriesByName.put("exo.AdtsExtractor", AdtsExtractor::new);
-        extractorFactoriesByName.put("exo.AmrExtractor", AmrExtractor::new);
-        extractorFactoriesByName.put("exo.FlacExtractor", FlacExtractor::new);
-        extractorFactoriesByName.put("exo.FlvExtractor", FlvExtractor::new);
-        extractorFactoriesByName.put("exo.FragmentedMp4Extractor", FragmentedMp4Extractor::new);
-        extractorFactoriesByName.put("exo.MatroskaExtractor", MatroskaExtractor::new);
-        extractorFactoriesByName.put("exo.Mp3Extractor", Mp3Extractor::new);
-        extractorFactoriesByName.put("exo.Mp4Extractor", Mp4Extractor::new);
-        extractorFactoriesByName.put("exo.OggExtractor", OggExtractor::new);
-        extractorFactoriesByName.put("exo.PsExtractor", PsExtractor::new);
-        extractorFactoriesByName.put("exo.TsExtractor", TsExtractor::new);
-        extractorFactoriesByName.put("exo.WavExtractor", WavExtractor::new);
+        extractorFactoriesByName.put("exo.Ac3Parser", Ac3Extractor::new);
+        extractorFactoriesByName.put("exo.Ac4Parser", Ac4Extractor::new);
+        extractorFactoriesByName.put("exo.AdtsParser", AdtsExtractor::new);
+        extractorFactoriesByName.put("exo.AmrParser", AmrExtractor::new);
+        extractorFactoriesByName.put("exo.FlacParser", FlacExtractor::new);
+        extractorFactoriesByName.put("exo.FlvParser", FlvExtractor::new);
+        extractorFactoriesByName.put("exo.FragmentedMp4Parser", FragmentedMp4Extractor::new);
+        extractorFactoriesByName.put("exo.MatroskaParser", MatroskaExtractor::new);
+        extractorFactoriesByName.put("exo.Mp3Parser", Mp3Extractor::new);
+        extractorFactoriesByName.put("exo.Mp4Parser", Mp4Extractor::new);
+        extractorFactoriesByName.put("exo.OggParser", OggExtractor::new);
+        extractorFactoriesByName.put("exo.PsParser", PsExtractor::new);
+        extractorFactoriesByName.put("exo.TsParser", TsExtractor::new);
+        extractorFactoriesByName.put("exo.WavParser", WavExtractor::new);
         EXTRACTOR_FACTORIES_BY_NAME = Collections.unmodifiableMap(extractorFactoriesByName);
+
+        HashMap<String, Class> expectedTypeByParameterName = new HashMap<>();
+        expectedTypeByParameterName.put(PARAMETER_ADTS_ENABLE_CBR_SEEKING, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_AMR_ENABLE_CBR_SEEKING, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_FLAC_DISABLE_ID3, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_FMP4_IGNORE_EDIT_LISTS, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_FMP4_IGNORE_TFDT_BOX, Boolean.class);
+        expectedTypeByParameterName.put(
+                PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_MATROSKA_DISABLE_CUES_SEEKING, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_MP3_DISABLE_ID3, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_CBR_SEEKING, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_MP3_ENABLE_INDEX_SEEKING, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_MP4_IGNORE_EDIT_LISTS, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_MODE, String.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AAC_STREAM, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_AVC_STREAM, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_DETECT_ACCESS_UNITS, Boolean.class);
+        expectedTypeByParameterName.put(PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS, Boolean.class);
+        EXPECTED_TYPE_BY_PARAMETER_NAME = Collections.unmodifiableMap(expectedTypeByParameterName);
     }
 }
diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java
index 6c7f82a..0d163cf 100644
--- a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java
+++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistence.java
@@ -40,7 +40,7 @@
      * @return the runtime permissions read
      */
     @Nullable
-    RuntimePermissionsState read(@NonNull UserHandle user);
+    RuntimePermissionsState readAsUser(@NonNull UserHandle user);
 
     /**
      * Write the runtime permissions to persistence.
@@ -50,7 +50,7 @@
      * @param runtimePermissions the runtime permissions to write
      * @param user the user to write for
      */
-    void write(@NonNull RuntimePermissionsState runtimePermissions, @NonNull UserHandle user);
+    void writeAsUser(@NonNull RuntimePermissionsState runtimePermissions, @NonNull UserHandle user);
 
     /**
      * Delete the runtime permissions from persistence.
@@ -59,7 +59,7 @@
      *
      * @param user the user to delete for
      */
-    void delete(@NonNull UserHandle user);
+    void deleteAsUser(@NonNull UserHandle user);
 
     /**
      * Create a new instance of {@link RuntimePermissionsPersistence} implementation.
diff --git a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
index 90b1c4b..205ffc2 100644
--- a/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/permission/persistence/RuntimePermissionsPersistenceImpl.java
@@ -67,7 +67,7 @@
 
     @Nullable
     @Override
-    public RuntimePermissionsState read(@NonNull UserHandle user) {
+    public RuntimePermissionsState readAsUser(@NonNull UserHandle user) {
         File file = getFile(user);
         try (FileInputStream inputStream = new AtomicFile(file).openRead()) {
             XmlPullParser parser = Xml.newPullParser();
@@ -172,7 +172,7 @@
     }
 
     @Override
-    public void write(@NonNull RuntimePermissionsState runtimePermissions,
+    public void writeAsUser(@NonNull RuntimePermissionsState runtimePermissions,
             @NonNull UserHandle user) {
         File file = getFile(user);
         AtomicFile atomicFile = new AtomicFile(file);
@@ -252,7 +252,7 @@
     }
 
     @Override
-    public void delete(@NonNull UserHandle user) {
+    public void deleteAsUser(@NonNull UserHandle user) {
         getFile(user).delete();
     }
 
diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java
index 2908a38..64d6545 100644
--- a/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java
+++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistence.java
@@ -40,7 +40,7 @@
      * @return the roles read
      */
     @Nullable
-    RolesState read(@NonNull UserHandle user);
+    RolesState readAsUser(@NonNull UserHandle user);
 
     /**
      * Write the roles to persistence.
@@ -50,7 +50,7 @@
      * @param roles the roles to write
      * @param user the user to write for
      */
-    void write(@NonNull RolesState roles, @NonNull UserHandle user);
+    void writeAsUser(@NonNull RolesState roles, @NonNull UserHandle user);
 
     /**
      * Delete the roles from persistence.
@@ -59,7 +59,7 @@
      *
      * @param user the user to delete for
      */
-    void delete(@NonNull UserHandle user);
+    void deleteAsUser(@NonNull UserHandle user);
 
     /**
      * Create a new instance of {@link RolesPersistence} implementation.
diff --git a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
index 06fad77..3031c82 100644
--- a/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
+++ b/apex/permission/service/java/com/android/role/persistence/RolesPersistenceImpl.java
@@ -65,7 +65,7 @@
 
     @Nullable
     @Override
-    public RolesState read(@NonNull UserHandle user) {
+    public RolesState readAsUser(@NonNull UserHandle user) {
         File file = getFile(user);
         try (FileInputStream inputStream = new AtomicFile(file).openRead()) {
             XmlPullParser parser = Xml.newPullParser();
@@ -146,8 +146,7 @@
     }
 
     @Override
-    public void write(@NonNull RolesState roles,
-            @NonNull UserHandle user) {
+    public void writeAsUser(@NonNull RolesState roles, @NonNull UserHandle user) {
         File file = getFile(user);
         AtomicFile atomicFile = new AtomicFile(file);
         FileOutputStream outputStream = null;
@@ -206,7 +205,7 @@
     }
 
     @Override
-    public void delete(@NonNull UserHandle user) {
+    public void deleteAsUser(@NonNull UserHandle user) {
         getFile(user).delete();
     }
 
diff --git a/apex/sdkextensions/Android.bp b/apex/sdkextensions/Android.bp
index 4c5c2b2..25765af 100644
--- a/apex/sdkextensions/Android.bp
+++ b/apex/sdkextensions/Android.bp
@@ -28,7 +28,6 @@
     name: "com.android.sdkext-defaults",
     java_libs: [ "framework-sdkextensions" ],
     prebuilts: [
-        "com.android.sdkext.ldconfig",
         "derive_sdk.rc",
     ],
     key: "com.android.sdkext.key",
@@ -51,13 +50,6 @@
     certificate: "com.android.sdkext",
 }
 
-prebuilt_etc {
-    name: "com.android.sdkext.ldconfig",
-    src: "ld.config.txt",
-    filename: "ld.config.txt",
-    installable: false,
-}
-
 python_binary_host {
     name: "gen_sdkinfo",
     srcs: [
diff --git a/apex/sdkextensions/ld.config.txt b/apex/sdkextensions/ld.config.txt
deleted file mode 100644
index dcc69b8..0000000
--- a/apex/sdkextensions/ld.config.txt
+++ /dev/null
@@ -1,31 +0,0 @@
-# Copyright (C) 2019 The Android Open Source Project
-#
-# Bionic loader config file for the sdkextensions apex.
-
-dir.sdkextensions = /apex/com.android.sdkext/bin/
-
-[sdkextensions]
-additional.namespaces = platform
-
-namespace.default.isolated = true
-namespace.default.links = platform
-namespace.default.link.platform.allow_all_shared_libs = true
-
-###############################################################################
-# "platform" namespace: used for NDK libraries
-###############################################################################
-namespace.platform.isolated = true
-namespace.platform.search.paths = /system/${LIB}
-namespace.platform.asan.search.paths = /data/asan/system/${LIB}
-
-# /system/lib/libc.so, etc are symlinks to /apex/com.android.lib/lib/bionic/libc.so, etc.
-# Add /apex/... path to the permitted paths because linker uses realpath(3)
-# to check the accessibility of the lib. We could add this to search.paths
-# instead but that makes the resolution of bionic libs be dependent on
-# the order of /system/lib and /apex/... in search.paths. If /apex/...
-# is after /system/lib, then /apex/... is never tried because libc.so
-# is always found in /system/lib but fails to pass the accessibility test
-# because of its realpath.  It's better to not depend on the ordering if
-# possible.
-namespace.platform.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
-namespace.platform.asan.permitted.paths = /apex/com.android.runtime/${LIB}/bionic
diff --git a/apex/statsd/Android.bp b/apex/statsd/Android.bp
index c8aa526..2f3e2ac 100644
--- a/apex/statsd/Android.bp
+++ b/apex/statsd/Android.bp
@@ -21,13 +21,16 @@
 apex_defaults {
     native_shared_libs: [
         "libstats_jni",
+        "libstatspull",
+        "libstatssocket",
     ],
-    // binaries: ["vold"],
+    binaries: ["statsd"],
     java_libs: [
         "framework-statsd",
         "service-statsd",
     ],
-    // prebuilts: ["my_prebuilt"],
+    compile_multilib: "both",
+    prebuilts: ["com.android.os.statsd.init.rc"],
     name: "com.android.os.statsd-defaults",
     key: "com.android.os.statsd.key",
     certificate: ":com.android.os.statsd.certificate",
@@ -46,6 +49,12 @@
     certificate: "com.android.os.statsd",
 }
 
+prebuilt_etc {
+    name: "com.android.os.statsd.init.rc",
+    src: "statsd.rc",
+    filename: "init.rc",
+    installable: false,
+}
 
 // JNI library for StatsLog.write
 cc_library_shared {
@@ -72,4 +81,4 @@
         "com.android.os.statsd",
         "test_com.android.os.statsd",
     ],
-}
\ No newline at end of file
+}
diff --git a/apex/statsd/aidl/Android.bp b/apex/statsd/aidl/Android.bp
index 7c93bc7..487c8e1 100644
--- a/apex/statsd/aidl/Android.bp
+++ b/apex/statsd/aidl/Android.bp
@@ -34,10 +34,17 @@
             enabled: false, // the platform uses statsd_java_aidl
         },
         cpp: {
-            enabled: true,
+            enabled: false,
         },
         ndk: {
             enabled: true,
-        }
+            apex_available: [
+                // TODO(b/145923087): Remove this once statsd binary is in apex
+                "//apex_available:platform",
+
+                "com.android.os.statsd",
+                "test_com.android.os.statsd",
+            ],
+        },
     }
 }
diff --git a/apex/statsd/framework/Android.bp b/apex/statsd/framework/Android.bp
index ab669d4..5533ed8 100644
--- a/apex/statsd/framework/Android.bp
+++ b/apex/statsd/framework/Android.bp
@@ -48,17 +48,8 @@
 
 java_defaults {
     name: "framework-statsd-defaults",
-
-    // TODO(b/146757305): Use "module_current" once it's ready.
-    sdk_version: "core_current",
-
-    libs: [
-        "framework-annotations-lib",
-
-        // TODO(b/146757305): should be unnecessary once
-        // sdk_version="module_lib_current" or "module_current"
-        "android_module_lib_stubs_current",
-    ],
+    sdk_version: "module_current",
+    libs: [ "framework-annotations-lib" ],
 }
 
 java_library {
@@ -72,16 +63,6 @@
         ":framework-statsd-sources",
     ],
 
-    aidl: {
-        // TODO(b/146757305): should be unnecessary once
-        // sdk_version="module_lib_current" or "module_current"
-        include_dirs: [
-            // To refer:
-            // android.app.PendintIntent
-            "frameworks/base/core/java",
-        ],
-    },
-
     permitted_packages: [
         "android.app",
         "android.os",
diff --git a/apex/statsd/framework/java/android/app/StatsManager.java b/apex/statsd/framework/java/android/app/StatsManager.java
index 526d17f..e637187 100644
--- a/apex/statsd/framework/java/android/app/StatsManager.java
+++ b/apex/statsd/framework/java/android/app/StatsManager.java
@@ -159,6 +159,9 @@
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to addConfig in statsmanager");
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -195,6 +198,9 @@
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to removeConfig in statsmanager");
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -391,6 +397,9 @@
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to getReports in statsmanager");
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -428,6 +437,9 @@
                 throw new StatsUnavailableException("could not connect", e);
             } catch (SecurityException e) {
                 throw new StatsUnavailableException(e.getMessage(), e);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to getStatsMetadata in statsmanager");
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
@@ -469,6 +481,9 @@
                                     + "registered experiment IDs");
                 }
                 throw new StatsUnavailableException("could not connect", e);
+            } catch (IllegalStateException e) {
+                Log.e(TAG, "Failed to getRegisteredExperimentIds in statsmanager");
+                throw new StatsUnavailableException(e.getMessage(), e);
             }
         }
     }
diff --git a/cmds/statsd/statsd.rc b/apex/statsd/statsd.rc
similarity index 67%
rename from cmds/statsd/statsd.rc
rename to apex/statsd/statsd.rc
index a98ecd5..605da2a 100644
--- a/cmds/statsd/statsd.rc
+++ b/apex/statsd/statsd.rc
@@ -12,19 +12,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-service statsd /system/bin/statsd
+service statsd /apex/com.android.os.statsd/bin/statsd
     class main
     socket statsdw dgram+passcred 0222 statsd statsd
     user statsd
     group statsd log
     writepid /dev/cpuset/system-background/tasks
-
-on property:ro.statsd.enable=false
-    stop statsd
-
-on post-fs-data
-    # Create directory for statsd
-    mkdir /data/misc/stats-data/ 0770 statsd system
-    mkdir /data/misc/stats-service/ 0770 statsd system
-    mkdir /data/misc/stats-active-metric/ 0770 statsd system
-    mkdir /data/misc/train-info/ 0770 statsd system
diff --git a/api/current.txt b/api/current.txt
index 7c80f5e..0a7bac5 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9,6 +9,7 @@
     ctor public Manifest.permission();
     field public static final String ACCEPT_HANDOVER = "android.permission.ACCEPT_HANDOVER";
     field public static final String ACCESS_BACKGROUND_LOCATION = "android.permission.ACCESS_BACKGROUND_LOCATION";
+    field public static final String ACCESS_CALL_AUDIO = "android.permission.ACCESS_CALL_AUDIO";
     field public static final String ACCESS_CHECKIN_PROPERTIES = "android.permission.ACCESS_CHECKIN_PROPERTIES";
     field public static final String ACCESS_COARSE_LOCATION = "android.permission.ACCESS_COARSE_LOCATION";
     field public static final String ACCESS_FINE_LOCATION = "android.permission.ACCESS_FINE_LOCATION";
@@ -31,6 +32,7 @@
     field public static final String BIND_CARRIER_SERVICES = "android.permission.BIND_CARRIER_SERVICES";
     field @Deprecated public static final String BIND_CHOOSER_TARGET_SERVICE = "android.permission.BIND_CHOOSER_TARGET_SERVICE";
     field public static final String BIND_CONDITION_PROVIDER_SERVICE = "android.permission.BIND_CONDITION_PROVIDER_SERVICE";
+    field public static final String BIND_CONTROLS = "android.permission.BIND_CONTROLS";
     field public static final String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
     field public static final String BIND_DREAM_SERVICE = "android.permission.BIND_DREAM_SERVICE";
     field public static final String BIND_INCALL_SERVICE = "android.permission.BIND_INCALL_SERVICE";
@@ -951,6 +953,7 @@
     field public static final int mediaRouteButtonStyle = 16843693; // 0x10103ad
     field public static final int mediaRouteTypes = 16843694; // 0x10103ae
     field public static final int menuCategory = 16843230; // 0x10101de
+    field public static final int mimeGroup = 16844309; // 0x1010615
     field public static final int mimeType = 16842790; // 0x1010026
     field public static final int min = 16844089; // 0x1010539
     field public static final int minAspectRatio = 16844187; // 0x101059b
@@ -2871,7 +2874,9 @@
     method protected void onServiceConnected();
     method public void onSystemActionsChanged();
     method public final boolean performGlobalAction(int);
+    method public void setGestureDetectionPassthroughRegion(int, @NonNull android.graphics.Region);
     method public final void setServiceInfo(android.accessibilityservice.AccessibilityServiceInfo);
+    method public void setTouchExplorationPassthroughRegion(int, @NonNull android.graphics.Region);
     method public boolean takeScreenshot(int, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.accessibilityservice.AccessibilityService.ScreenshotResult>);
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP = 20; // 0x14
     field public static final int GESTURE_2_FINGER_DOUBLE_TAP_AND_HOLD = 40; // 0x28
@@ -2979,7 +2984,6 @@
     method public int describeContents();
     method public static String feedbackTypeToString(int);
     method public static String flagToString(int);
-    method public int getAnimatedImageRes();
     method @Deprecated public boolean getCanRetrieveWindowContent();
     method public int getCapabilities();
     method @Deprecated public String getDescription();
@@ -2988,6 +2992,7 @@
     method public int getNonInteractiveUiTimeoutMillis();
     method public android.content.pm.ResolveInfo getResolveInfo();
     method public String getSettingsActivityName();
+    method @Nullable public android.graphics.drawable.Drawable loadAnimatedImage(@NonNull android.content.Context);
     method public String loadDescription(android.content.pm.PackageManager);
     method @Nullable public String loadHtmlDescription(@NonNull android.content.pm.PackageManager);
     method public CharSequence loadSummary(android.content.pm.PackageManager);
@@ -4351,7 +4356,7 @@
   public class AppOpsManager {
     method @Deprecated public int checkOp(@NonNull String, int, @NonNull String);
     method @Deprecated public int checkOpNoThrow(@NonNull String, int, @NonNull String);
-    method public void checkPackage(int, @NonNull String);
+    method @Deprecated public void checkPackage(int, @NonNull String);
     method @Deprecated public void finishOp(@NonNull String, int, @NonNull String);
     method public void finishOp(@NonNull String, int, @NonNull String, @Nullable String);
     method public boolean isOpActive(@NonNull String, int, @NonNull String);
@@ -4364,7 +4369,7 @@
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @NonNull String);
     method @Deprecated public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int);
     method public int noteProxyOpNoThrow(@NonNull String, @Nullable String, int, @Nullable String, @Nullable String);
-    method public static String permissionToOp(String);
+    method @Nullable public static String permissionToOp(@NonNull String);
     method public void setNotedAppOpsCollector(@Nullable android.app.AppOpsManager.AppOpsCollector);
     method @Deprecated public int startOp(@NonNull String, int, @NonNull String);
     method public int startOp(@NonNull String, int, @Nullable String, @Nullable String, @Nullable String);
@@ -6965,7 +6970,6 @@
     method public boolean removeOverrideApn(@NonNull android.content.ComponentName, int);
     method public boolean removeUser(@NonNull android.content.ComponentName, @NonNull android.os.UserHandle);
     method public boolean requestBugreport(@NonNull android.content.ComponentName);
-    method public void requestSetLocationProviderAllowed(@NonNull android.content.ComponentName, @NonNull String, boolean);
     method @Deprecated public boolean resetPassword(String, int);
     method public boolean resetPasswordWithToken(@NonNull android.content.ComponentName, String, byte[], int);
     method @Nullable public java.util.List<android.app.admin.NetworkEvent> retrieveNetworkLogs(@Nullable android.content.ComponentName, long);
@@ -10827,6 +10831,8 @@
     field public static final int FLAG_ACTIVITY_NO_USER_ACTION = 262144; // 0x40000
     field public static final int FLAG_ACTIVITY_PREVIOUS_IS_TOP = 16777216; // 0x1000000
     field public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 131072; // 0x20000
+    field public static final int FLAG_ACTIVITY_REQUIRE_DEFAULT = 512; // 0x200
+    field public static final int FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 1024; // 0x400
     field public static final int FLAG_ACTIVITY_RESET_TASK_IF_NEEDED = 2097152; // 0x200000
     field public static final int FLAG_ACTIVITY_RETAIN_IN_RECENTS = 8192; // 0x2000
     field public static final int FLAG_ACTIVITY_SINGLE_TOP = 536870912; // 0x20000000
@@ -11937,6 +11943,7 @@
     method @CheckResult public abstract int checkSignatures(@NonNull String, @NonNull String);
     method @CheckResult public abstract int checkSignatures(int, int);
     method public abstract void clearInstantAppCookie();
+    method public void clearMimeGroup(@NonNull String);
     method @Deprecated public abstract void clearPackagePreferredActivities(@NonNull String);
     method public abstract String[] currentToCanonicalPackageNames(@NonNull String[]);
     method public abstract void extendVerificationTimeout(int, int, long);
@@ -11972,6 +11979,7 @@
     method @NonNull public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(@NonNull android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract android.content.Intent getLaunchIntentForPackage(@NonNull String);
     method @Nullable public abstract android.content.Intent getLeanbackLaunchIntentForPackage(@NonNull String);
+    method @Nullable public java.util.Set<java.lang.String> getMimeGroup(@NonNull String);
     method @NonNull public android.content.pm.ModuleInfo getModuleInfo(@NonNull String, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method @Nullable public abstract String getNameForUid(int);
     method @Nullable public android.content.pm.PackageInfo getPackageArchiveInfo(@NonNull String, int);
@@ -12034,6 +12042,7 @@
     method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setApplicationEnabledSetting(@NonNull String, int, int);
     method @RequiresPermission(value=android.Manifest.permission.CHANGE_COMPONENT_ENABLED_STATE, conditional=true) public abstract void setComponentEnabledSetting(@NonNull android.content.ComponentName, int, int);
     method public abstract void setInstallerPackageName(@NonNull String, @Nullable String);
+    method public void setMimeGroup(@NonNull String, @NonNull java.util.Set<java.lang.String>);
     method public abstract void updateInstantAppCookie(@Nullable byte[]);
     method public abstract void verifyPendingInstall(int, int);
     field public static final int CERT_INPUT_RAW_X509 = 0; // 0x0
@@ -12319,6 +12328,7 @@
     method public int describeContents();
     method public void dump(android.util.Printer, String);
     method public final int getIconResource();
+    method public boolean isCrossProfileIntentForwarderActivity();
     method public android.graphics.drawable.Drawable loadIcon(android.content.pm.PackageManager);
     method public CharSequence loadLabel(android.content.pm.PackageManager);
     method public void writeToParcel(android.os.Parcel, int);
@@ -12457,6 +12467,7 @@
     method @NonNull public java.util.List<android.content.pm.ShortcutInfo> getShortcuts(int);
     method public boolean isRateLimitingActive();
     method public boolean isRequestPinShortcutSupported();
+    method public void pushDynamicShortcut(@NonNull android.content.pm.ShortcutInfo);
     method public void removeAllDynamicShortcuts();
     method public void removeDynamicShortcuts(@NonNull java.util.List<java.lang.String>);
     method public void removeLongLivedShortcuts(@NonNull java.util.List<java.lang.String>);
@@ -23166,7 +23177,7 @@
     method public void onConfigureWindow(android.view.Window, boolean, boolean);
     method public android.view.View onCreateCandidatesView();
     method public android.view.View onCreateExtractTextView();
-    method @Nullable public android.view.inputmethod.InlineSuggestionsRequest onCreateInlineSuggestionsRequest();
+    method @Nullable public android.view.inputmethod.InlineSuggestionsRequest onCreateInlineSuggestionsRequest(@NonNull android.os.Bundle);
     method public android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodImpl onCreateInputMethodInterface();
     method public android.inputmethodservice.AbstractInputMethodService.AbstractInputMethodSessionImpl onCreateInputMethodSessionInterface();
     method public android.view.View onCreateInputView();
@@ -23481,66 +23492,54 @@
   }
 
   public final class GnssAntennaInfo implements android.os.Parcelable {
-    ctor public GnssAntennaInfo(double, @NonNull android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates, @Nullable android.location.GnssAntennaInfo.PhaseCenterVariationCorrections, @Nullable android.location.GnssAntennaInfo.SignalGainCorrections);
     method public int describeContents();
-    method public double getCarrierFrequencyMHz();
-    method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates();
-    method @Nullable public android.location.GnssAntennaInfo.PhaseCenterVariationCorrections getPhaseCenterVariationCorrections();
-    method @Nullable public android.location.GnssAntennaInfo.SignalGainCorrections getSignalGainCorrections();
+    method @FloatRange(from=0.0f) public double getCarrierFrequencyMHz();
+    method @NonNull public android.location.GnssAntennaInfo.PhaseCenterOffset getPhaseCenterOffset();
+    method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getPhaseCenterVariationCorrections();
+    method @Nullable public android.location.GnssAntennaInfo.SphericalCorrections getSignalGainCorrections();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo> CREATOR;
   }
 
-  public abstract static class GnssAntennaInfo.Callback {
-    ctor public GnssAntennaInfo.Callback();
+  public static class GnssAntennaInfo.Builder {
+    ctor public GnssAntennaInfo.Builder();
+    method @NonNull public android.location.GnssAntennaInfo build();
+    method @NonNull public android.location.GnssAntennaInfo.Builder setCarrierFrequencyMHz(@FloatRange(from=0.0f) double);
+    method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterOffset(@NonNull android.location.GnssAntennaInfo.PhaseCenterOffset);
+    method @NonNull public android.location.GnssAntennaInfo.Builder setPhaseCenterVariationCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+    method @NonNull public android.location.GnssAntennaInfo.Builder setSignalGainCorrections(@Nullable android.location.GnssAntennaInfo.SphericalCorrections);
+  }
+
+  public static interface GnssAntennaInfo.Listener {
     method public void onGnssAntennaInfoReceived(@NonNull java.util.List<android.location.GnssAntennaInfo>);
-    method public void onStatusChanged(int);
-    field public static final int STATUS_LOCATION_DISABLED = 2; // 0x2
-    field public static final int STATUS_NOT_SUPPORTED = 0; // 0x0
-    field public static final int STATUS_READY = 1; // 0x1
   }
 
-  public static final class GnssAntennaInfo.PhaseCenterOffsetCoordinates implements android.os.Parcelable {
-    ctor public GnssAntennaInfo.PhaseCenterOffsetCoordinates(double, double, double, double, double, double);
+  public static final class GnssAntennaInfo.PhaseCenterOffset implements android.os.Parcelable {
+    ctor public GnssAntennaInfo.PhaseCenterOffset(double, double, double, double, double, double);
     method public int describeContents();
-    method public double getXCoordMillimeters();
-    method public double getXCoordUncertaintyMillimeters();
-    method public double getYCoordMillimeters();
-    method public double getYCoordUncertaintyMillimeters();
-    method public double getZCoordMillimeters();
-    method public double getZCoordUncertaintyMillimeters();
+    method @FloatRange public double getXOffsetMm();
+    method @FloatRange public double getXOffsetUncertaintyMm();
+    method @FloatRange public double getYOffsetMm();
+    method @FloatRange public double getYOffsetUncertaintyMm();
+    method @FloatRange public double getZOffsetMm();
+    method @FloatRange public double getZOffsetUncertaintyMm();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffsetCoordinates> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterOffset> CREATOR;
   }
 
-  public static final class GnssAntennaInfo.PhaseCenterVariationCorrections implements android.os.Parcelable {
-    ctor public GnssAntennaInfo.PhaseCenterVariationCorrections(@NonNull double[][], @NonNull double[][]);
+  public static final class GnssAntennaInfo.SphericalCorrections implements android.os.Parcelable {
+    ctor public GnssAntennaInfo.SphericalCorrections(@NonNull double[][], @NonNull double[][]);
     method public int describeContents();
-    method public double getDeltaPhi();
-    method public double getDeltaTheta();
-    method public int getNumColumns();
-    method public int getNumRows();
-    method public double getPhaseCenterVariationCorrectionMillimetersAt(int, int);
-    method public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(int, int);
-    method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
-    method @NonNull public double[][] getRawCorrectionsArray();
+    method @NonNull public double[][] getCorrectionUncertaintiesArray();
+    method @NonNull public double[][] getCorrectionsArray();
+    method @FloatRange(from=0.0f, to=180.0f) public double getDeltaPhi();
+    method @FloatRange(from=0.0f, to=360.0f) public double getDeltaTheta();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.PhaseCenterVariationCorrections> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SphericalCorrections> CREATOR;
   }
 
-  public static final class GnssAntennaInfo.SignalGainCorrections implements android.os.Parcelable {
-    ctor public GnssAntennaInfo.SignalGainCorrections(@NonNull double[][], @NonNull double[][]);
-    method public int describeContents();
-    method public double getDeltaPhi();
-    method public double getDeltaTheta();
-    method public int getNumColumns();
-    method public int getNumRows();
-    method @NonNull public double[][] getRawCorrectionUncertaintiesArray();
-    method @NonNull public double[][] getRawCorrectionsArray();
-    method public double getSignalGainCorrectionDbiAt(int, int);
-    method public double getSignalGainCorrectionUncertaintyDbiAt(int, int);
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.location.GnssAntennaInfo.SignalGainCorrections> CREATOR;
+  public final class GnssCapabilities {
+    method public boolean hasGnssAntennaInfo();
   }
 
   public final class GnssClock implements android.os.Parcelable {
@@ -23851,6 +23850,7 @@
     method @NonNull public java.util.List<java.lang.String> getAllProviders();
     method @Nullable public String getBestProvider(@NonNull android.location.Criteria, boolean);
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull String, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
+    method @NonNull public android.location.GnssCapabilities getGnssCapabilities();
     method @Nullable public String getGnssHardwareModelName();
     method public int getGnssYearOfHardware();
     method @Deprecated @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GpsStatus getGpsStatus(@Nullable android.location.GpsStatus);
@@ -23860,7 +23860,7 @@
     method @NonNull public java.util.List<java.lang.String> getProviders(@NonNull android.location.Criteria, boolean);
     method public boolean isLocationEnabled();
     method public boolean isProviderEnabled(@NonNull String);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerAntennaInfoCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Callback);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerAntennaInfoListener(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssAntennaInfo.Listener);
     method @Deprecated @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback, @Nullable android.os.Handler);
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public boolean registerGnssMeasurementsCallback(@NonNull java.util.concurrent.Executor, @NonNull android.location.GnssMeasurementsEvent.Callback);
@@ -23892,7 +23892,7 @@
     method public void setTestProviderEnabled(@NonNull String, boolean);
     method public void setTestProviderLocation(@NonNull String, @NonNull android.location.Location);
     method @Deprecated public void setTestProviderStatus(@NonNull String, int, @Nullable android.os.Bundle, long);
-    method public void unregisterAntennaInfoCallback(@NonNull android.location.GnssAntennaInfo.Callback);
+    method public void unregisterAntennaInfoListener(@NonNull android.location.GnssAntennaInfo.Listener);
     method public void unregisterGnssMeasurementsCallback(@NonNull android.location.GnssMeasurementsEvent.Callback);
     method public void unregisterGnssNavigationMessageCallback(@NonNull android.location.GnssNavigationMessage.Callback);
     method public void unregisterGnssStatusCallback(@NonNull android.location.GnssStatus.Callback);
@@ -24788,7 +24788,7 @@
   }
 
   public abstract class DrmInitData {
-    method public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
+    method @Deprecated public abstract android.media.DrmInitData.SchemeInitData get(java.util.UUID);
     method @NonNull public android.media.DrmInitData.SchemeInitData getSchemeInitDataAt(int);
     method public int getSchemeInitDataCount();
   }
@@ -25092,7 +25092,7 @@
 
   public final class MediaCas implements java.lang.AutoCloseable {
     ctor public MediaCas(int) throws android.media.MediaCasException.UnsupportedCasException;
-    ctor public MediaCas(int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException;
+    ctor public MediaCas(@NonNull android.content.Context, int, @Nullable String, int) throws android.media.MediaCasException.UnsupportedCasException;
     method public void close();
     method public static android.media.MediaCas.PluginDescriptor[] enumeratePlugins();
     method protected void finalize();
@@ -25307,6 +25307,10 @@
     method public void recycle();
   }
 
+  public class MediaCodec.IncompatibleWithBlockModelException extends java.lang.RuntimeException {
+    ctor public MediaCodec.IncompatibleWithBlockModelException();
+  }
+
   public static final class MediaCodec.LinearBlock {
     method protected void finalize();
     method public static boolean isCodecCopyFreeCompatible(@NonNull String[]);
@@ -25334,23 +25338,24 @@
   }
 
   public static final class MediaCodec.OutputFrame {
-    method public void getChangedKeys(@NonNull java.util.Set<java.lang.String>);
     method public int getFlags();
     method @NonNull public android.media.MediaFormat getFormat();
     method @Nullable public android.media.MediaCodec.GraphicBlock getGraphicBlock();
     method @Nullable public android.media.MediaCodec.LinearBlock getLinearBlock();
     method public long getPresentationTimeUs();
+    method public void retrieveChangedKeys(@NonNull java.util.Set<java.lang.String>);
   }
 
   public final class MediaCodec.QueueRequest {
     method public void queue();
     method @NonNull public android.media.MediaCodec.QueueRequest setByteBufferParameter(@NonNull String, @NonNull java.nio.ByteBuffer);
-    method @NonNull public android.media.MediaCodec.QueueRequest setEncryptedLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, @NonNull android.media.MediaCodec.CryptoInfo, long, int);
+    method @NonNull public android.media.MediaCodec.QueueRequest setFlags(int);
     method @NonNull public android.media.MediaCodec.QueueRequest setFloatParameter(@NonNull String, float);
-    method @NonNull public android.media.MediaCodec.QueueRequest setGraphicBlock(@NonNull android.media.MediaCodec.GraphicBlock, long, int);
+    method @NonNull public android.media.MediaCodec.QueueRequest setGraphicBlock(@NonNull android.media.MediaCodec.GraphicBlock);
     method @NonNull public android.media.MediaCodec.QueueRequest setIntegerParameter(@NonNull String, int);
-    method @NonNull public android.media.MediaCodec.QueueRequest setLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int, long, int);
+    method @NonNull public android.media.MediaCodec.QueueRequest setLinearBlock(@NonNull android.media.MediaCodec.LinearBlock, int, int, @Nullable android.media.MediaCodec.CryptoInfo);
     method @NonNull public android.media.MediaCodec.QueueRequest setLongParameter(@NonNull String, long);
+    method @NonNull public android.media.MediaCodec.QueueRequest setPresentationTimeUs(long);
     method @NonNull public android.media.MediaCodec.QueueRequest setStringParameter(@NonNull String, @NonNull String);
   }
 
@@ -26404,10 +26409,30 @@
     method public boolean advance(@NonNull android.media.MediaParser.SeekableInputReader) throws java.io.IOException, java.lang.InterruptedException;
     method @NonNull public static android.media.MediaParser create(@NonNull android.media.MediaParser.OutputConsumer, @NonNull java.lang.String...);
     method @NonNull public static android.media.MediaParser createByName(@NonNull String, @NonNull android.media.MediaParser.OutputConsumer);
-    method @Nullable public String getExtractorName();
-    method @NonNull public static java.util.List<java.lang.String> getExtractorNames(@NonNull android.media.MediaFormat);
+    method @Nullable public String getParserName();
+    method @NonNull public static java.util.List<java.lang.String> getParserNames(@NonNull android.media.MediaFormat);
     method public void release();
     method public void seek(@NonNull android.media.MediaParser.SeekPoint);
+    method @NonNull public android.media.MediaParser setParameter(@NonNull String, @NonNull Object);
+    method public boolean supportsParameter(@NonNull String);
+    field public static final String PARAMETER_ADTS_ENABLE_CBR_SEEKING = "exo.AdtsParser.enableCbrSeeking";
+    field public static final String PARAMETER_AMR_ENABLE_CBR_SEEKING = "exo.AmrParser.enableCbrSeeking";
+    field public static final String PARAMETER_FLAC_DISABLE_ID3 = "exo.FlacParser.disableId3";
+    field public static final String PARAMETER_FMP4_IGNORE_EDIT_LISTS = "exo.FragmentedMp4Parser.ignoreEditLists";
+    field public static final String PARAMETER_FMP4_IGNORE_TFDT_BOX = "exo.FragmentedMp4Parser.ignoreTfdtBox";
+    field public static final String PARAMETER_FMP4_TREAT_VIDEO_FRAMES_AS_KEYFRAMES = "exo.FragmentedMp4Parser.treatVideoFramesAsKeyframes";
+    field public static final String PARAMETER_MATROSKA_DISABLE_CUES_SEEKING = "exo.MatroskaParser.disableCuesSeeking";
+    field public static final String PARAMETER_MP3_DISABLE_ID3 = "exo.Mp3Parser.disableId3";
+    field public static final String PARAMETER_MP3_ENABLE_CBR_SEEKING = "exo.Mp3Parser.enableCbrSeeking";
+    field public static final String PARAMETER_MP3_ENABLE_INDEX_SEEKING = "exo.Mp3Parser.enableIndexSeeking";
+    field public static final String PARAMETER_MP4_IGNORE_EDIT_LISTS = "exo.Mp4Parser.ignoreEditLists";
+    field public static final String PARAMETER_TS_ALLOW_NON_IDR_AVC_KEYFRAMES = "exo.TsParser.allowNonIdrAvcKeyframes";
+    field public static final String PARAMETER_TS_DETECT_ACCESS_UNITS = "exo.TsParser.ignoreDetectAccessUnits";
+    field public static final String PARAMETER_TS_ENABLE_HDMV_DTS_AUDIO_STREAMS = "exo.TsParser.enableHdmvDtsAudioStreams";
+    field public static final String PARAMETER_TS_IGNORE_AAC_STREAM = "exo.TsParser.ignoreAacStream";
+    field public static final String PARAMETER_TS_IGNORE_AVC_STREAM = "exo.TsParser.ignoreAvcStream";
+    field public static final String PARAMETER_TS_IGNORE_SPLICE_INFO_STREAM = "exo.TsParser.ignoreSpliceInfoStream";
+    field public static final String PARAMETER_TS_MODE = "exo.TsParser.mode";
   }
 
   public static interface MediaParser.InputReader {
@@ -26874,21 +26899,27 @@
     ctor public MediaRoute2ProviderService();
     method @NonNull public final java.util.List<android.media.RoutingSessionInfo> getAllSessionInfo();
     method @Nullable public final android.media.RoutingSessionInfo getSessionInfo(@NonNull String);
+    method public final void notifyRequestFailed(long, int);
     method public final void notifyRoutes(@NonNull java.util.Collection<android.media.MediaRoute2Info>);
     method public final void notifySessionCreated(@NonNull android.media.RoutingSessionInfo, long);
     method public final void notifySessionCreationFailed(long);
     method public final void notifySessionReleased(@NonNull String);
     method public final void notifySessionUpdated(@NonNull android.media.RoutingSessionInfo);
     method @CallSuper @Nullable public android.os.IBinder onBind(@NonNull android.content.Intent);
-    method public abstract void onCreateSession(@NonNull String, @NonNull String, long, @Nullable android.os.Bundle);
-    method public abstract void onDeselectRoute(@NonNull String, @NonNull String);
+    method public abstract void onCreateSession(long, @NonNull String, @NonNull String, @Nullable android.os.Bundle);
+    method public abstract void onDeselectRoute(long, @NonNull String, @NonNull String);
     method public void onDiscoveryPreferenceChanged(@NonNull android.media.RouteDiscoveryPreference);
-    method public abstract void onReleaseSession(@NonNull String);
-    method public abstract void onSelectRoute(@NonNull String, @NonNull String);
-    method public abstract void onSetRouteVolume(@NonNull String, int);
-    method public abstract void onSetSessionVolume(@NonNull String, int);
-    method public abstract void onTransferToRoute(@NonNull String, @NonNull String);
-    field public static final long REQUEST_ID_UNKNOWN = 0L; // 0x0L
+    method public abstract void onReleaseSession(long, @NonNull String);
+    method public abstract void onSelectRoute(long, @NonNull String, @NonNull String);
+    method public abstract void onSetRouteVolume(long, @NonNull String, int);
+    method public abstract void onSetSessionVolume(long, @NonNull String, int);
+    method public abstract void onTransferToRoute(long, @NonNull String, @NonNull String);
+    field public static final int REASON_INVALID_COMMAND = 4; // 0x4
+    field public static final int REASON_NETWORK_ERROR = 2; // 0x2
+    field public static final int REASON_REJECTED = 1; // 0x1
+    field public static final int REASON_ROUTE_NOT_AVAILABLE = 3; // 0x3
+    field public static final int REASON_UNKNOWN_ERROR = 0; // 0x0
+    field public static final long REQUEST_ID_NONE = 0L; // 0x0L
     field public static final String SERVICE_INTERFACE = "android.media.MediaRoute2ProviderService";
   }
 
@@ -31736,7 +31767,7 @@
     method public android.net.wifi.hotspot2.pps.Credential getCredential();
     method public android.net.wifi.hotspot2.pps.HomeSp getHomeSp();
     method public long getSubscriptionExpirationTimeMillis();
-    method @NonNull public String getUniqueId() throws java.lang.IllegalStateException;
+    method @NonNull public String getUniqueId();
     method public boolean isOsuProvisioned();
     method public void setCredential(android.net.wifi.hotspot2.pps.Credential);
     method public void setHomeSp(android.net.wifi.hotspot2.pps.HomeSp);
@@ -36625,6 +36656,7 @@
     method public void addThermalStatusListener(@NonNull java.util.concurrent.Executor, @NonNull android.os.PowerManager.OnThermalStatusChangedListener);
     method public int getCurrentThermalStatus();
     method public int getLocationPowerSaveMode();
+    method public float getThermalHeadroom(@IntRange(from=0, to=60) int);
     method public boolean isDeviceIdleMode();
     method public boolean isIgnoringBatteryOptimizations(String);
     method public boolean isInteractive();
@@ -40577,13 +40609,13 @@
     field public static final String WIFI_MAX_DHCP_RETRY_COUNT = "wifi_max_dhcp_retry_count";
     field public static final String WIFI_MOBILE_DATA_TRANSITION_WAKELOCK_TIMEOUT_MS = "wifi_mobile_data_transition_wakelock_timeout_ms";
     field @Deprecated public static final String WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON = "wifi_networks_available_notification_on";
-    field public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
-    field public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
+    field @Deprecated public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY = "wifi_networks_available_repeat_delay";
+    field @Deprecated public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
     field public static final String WIFI_ON = "wifi_on";
-    field public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
-    field public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
-    field public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
-    field public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
+    field @Deprecated public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
+    field @Deprecated public static final int WIFI_SLEEP_POLICY_DEFAULT = 0; // 0x0
+    field @Deprecated public static final int WIFI_SLEEP_POLICY_NEVER = 2; // 0x2
+    field @Deprecated public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1; // 0x1
     field public static final String WIFI_WATCHDOG_ON = "wifi_watchdog_on";
     field public static final String WINDOW_ANIMATION_SCALE = "window_animation_scale";
   }
@@ -43394,11 +43426,13 @@
 
   public abstract class ControlsProviderService extends android.app.Service {
     ctor public ControlsProviderService();
-    method public abstract void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
-    method public void loadSuggestedControls(int, @NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
+    method @Deprecated public void loadAvailableControls(@NonNull java.util.function.Consumer<java.util.List<android.service.controls.Control>>);
     method @NonNull public final android.os.IBinder onBind(@NonNull android.content.Intent);
     method public abstract void performControlAction(@NonNull String, @NonNull android.service.controls.actions.ControlAction, @NonNull java.util.function.Consumer<java.lang.Integer>);
     method @NonNull public abstract java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherFor(@NonNull java.util.List<java.lang.String>);
+    method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForAllAvailable();
+    method @Nullable public java.util.concurrent.Flow.Publisher<android.service.controls.Control> publisherForSuggested();
+    method public static void requestAddControl(@NonNull android.content.Context, @NonNull android.content.ComponentName, @NonNull android.service.controls.Control);
     field public static final String SERVICE_CONTROLS = "android.service.controls.ControlsProviderService";
     field @NonNull public static final String TAG = "ControlsProviderService";
   }
@@ -45645,7 +45679,7 @@
     method public final android.telecom.CallAudioState getCallAudioState();
     method public final String getCallerDisplayName();
     method public final int getCallerDisplayNamePresentation();
-    method public int getCallerNumberVerificationStatus();
+    method public final int getCallerNumberVerificationStatus();
     method public final android.telecom.Conference getConference();
     method public final java.util.List<android.telecom.Conferenceable> getConferenceables();
     method public final int getConnectionCapabilities();
@@ -45698,7 +45732,7 @@
     method public final void setAudioModeIsVoip(boolean);
     method public final void setAudioRoute(int);
     method public final void setCallerDisplayName(String, int);
-    method public void setCallerNumberVerificationStatus(int);
+    method public final void setCallerNumberVerificationStatus(int);
     method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
     method public final void setConferenceables(java.util.List<android.telecom.Conferenceable>);
     method public final void setConnectionCapabilities(int);
@@ -46550,8 +46584,8 @@
     field public static final String KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL = "allow_add_call_during_video_call";
     field public static final String KEY_ALLOW_EMERGENCY_NUMBERS_IN_CALL_LOG_BOOL = "allow_emergency_numbers_in_call_log_bool";
     field public static final String KEY_ALLOW_EMERGENCY_VIDEO_CALLS_BOOL = "allow_emergency_video_calls_bool";
-    field public static final String KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL = "allow_holding_video_call";
     field public static final String KEY_ALLOW_HOLD_CALL_DURING_EMERGENCY_BOOL = "allow_hold_call_during_emergency_bool";
+    field public static final String KEY_ALLOW_HOLD_VIDEO_CALL_BOOL = "allow_hold_video_call_bool";
     field public static final String KEY_ALLOW_LOCAL_DTMF_TONES_BOOL = "allow_local_dtmf_tones_bool";
     field public static final String KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL = "allow_merge_wifi_calls_when_vowifi_off_bool";
     field public static final String KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL = "allow_non_emergency_calls_in_ecm_bool";
@@ -46804,59 +46838,6 @@
     field public static final String KEY_WIFI_OFF_DEFERRING_TIME_INT = "ims.wifi_off_deferring_time_int";
   }
 
-  public static final class CarrierConfigManager.Iwlan {
-    field public static final int AUTHENTICATION_METHOD_CERT = 1; // 0x1
-    field public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0; // 0x0
-    field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
-    field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
-    field public static final int DH_GROUP_NONE = 0; // 0x0
-    field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
-    field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
-    field public static final int EPDG_ADDRESS_PCO = 2; // 0x2
-    field public static final int EPDG_ADDRESS_PLMN = 1; // 0x1
-    field public static final int EPDG_ADDRESS_STATIC = 0; // 0x0
-    field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
-    field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
-    field public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT = "iwlan.child_sa_rekey_hard_timer_sec_int";
-    field public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT = "iwlan.child_sa_rekey_soft_timer_sec_int";
-    field public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.child_session_aes_cbc_key_size_int_array";
-    field public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.child_encryption_aes_ctr_key_size_int_array";
-    field public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY = "iwlan.diffie_hellman_groups_int_array";
-    field public static final String KEY_DPD_TIMER_SEC_INT = "iwlan.dpd_timer_sec_int";
-    field public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY = "iwlan.epdg_address_priority_int_array";
-    field public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT = "iwlan.epdg_authentication_method_int";
-    field public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING = "iwlan.epdg_static_address_roaming_string";
-    field public static final String KEY_EPDG_STATIC_ADDRESS_STRING = "iwlan.epdg_static_address_string";
-    field public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL = "iwlan.ike_fragmentation_enabled_bool";
-    field public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT = "iwlan.ike_rekey_hard_timer_in_sec";
-    field public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT = "iwlan.ike_rekey_soft_timer_sec_int";
-    field public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_encryption_aes_cbc_key_size_int_array";
-    field public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY = "iwlan.ike_session_aes_ctr_key_size_int_array";
-    field public static final int KEY_LEN_AES_128 = 128; // 0x80
-    field public static final int KEY_LEN_AES_192 = 192; // 0xc0
-    field public static final int KEY_LEN_AES_256 = 256; // 0x100
-    field public static final int KEY_LEN_UNUSED = 0; // 0x0
-    field public static final String KEY_MAX_RETRIES_INT = "iwlan.max_retries_int";
-    field public static final String KEY_MCC_MNCS_STRING_ARRAY = "iwlan.mcc_mncs_string_array";
-    field public static final String KEY_NATT_ENABLED_BOOL = "iwlan.natt_enabled_bool";
-    field public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT = "iwlan.natt_keep_alive_timer_sec_int";
-    field public static final String KEY_PREFIX = "iwlan.";
-    field public static final String KEY_RETRANSMIT_TIMER_SEC_INT = "iwlan.retransmit_timer_sec_int";
-    field public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_child_session_encryption_algorithms_int_array";
-    field public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY = "iwlan.supported_ike_session_encryption_algorithms_int_array";
-    field public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY = "iwlan.supported_integrity_algorithms_int_array";
-    field public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = "iwlan.supported_prf_algorithms_int_array";
-    field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
-    field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
-  }
-
   public abstract class CellIdentity implements android.os.Parcelable {
     method public int describeContents();
     method @Nullable public CharSequence getOperatorAlphaLong();
@@ -47118,6 +47099,350 @@
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ClosedSubscriberGroupInfo> CREATOR;
   }
 
+  public final class DataFailCause {
+    field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
+    field public static final int ACCESS_BLOCK = 2087; // 0x827
+    field public static final int ACCESS_BLOCK_ALL = 2088; // 0x828
+    field public static final int ACCESS_CLASS_DSAC_REJECTION = 2108; // 0x83c
+    field public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128; // 0x850
+    field public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 48; // 0x30
+    field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
+    field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
+    field public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 65; // 0x41
+    field public static final int APN_DISABLED = 2045; // 0x7fd
+    field public static final int APN_DISALLOWED_ON_ROAMING = 2059; // 0x80b
+    field public static final int APN_MISMATCH = 2054; // 0x806
+    field public static final int APN_PARAMETERS_CHANGED = 2060; // 0x80c
+    field public static final int APN_PENDING_HANDOVER = 2041; // 0x7f9
+    field public static final int APN_TYPE_CONFLICT = 112; // 0x70
+    field public static final int AUTH_FAILURE_ON_EMERGENCY_CALL = 122; // 0x7a
+    field public static final int BEARER_HANDLING_NOT_SUPPORTED = 60; // 0x3c
+    field public static final int CALL_DISALLOWED_IN_ROAMING = 2068; // 0x814
+    field public static final int CALL_PREEMPT_BY_EMERGENCY_APN = 127; // 0x7f
+    field public static final int CANNOT_ENCODE_OTA_MESSAGE = 2159; // 0x86f
+    field public static final int CDMA_ALERT_STOP = 2077; // 0x81d
+    field public static final int CDMA_INCOMING_CALL = 2076; // 0x81c
+    field public static final int CDMA_INTERCEPT = 2073; // 0x819
+    field public static final int CDMA_LOCK = 2072; // 0x818
+    field public static final int CDMA_RELEASE_DUE_TO_SO_REJECTION = 2075; // 0x81b
+    field public static final int CDMA_REORDER = 2074; // 0x81a
+    field public static final int CDMA_RETRY_ORDER = 2086; // 0x826
+    field public static final int CHANNEL_ACQUISITION_FAILURE = 2078; // 0x81e
+    field public static final int CLOSE_IN_PROGRESS = 2030; // 0x7ee
+    field public static final int COLLISION_WITH_NETWORK_INITIATED_REQUEST = 56; // 0x38
+    field public static final int COMPANION_IFACE_IN_USE = 118; // 0x76
+    field public static final int CONCURRENT_SERVICES_INCOMPATIBLE = 2083; // 0x823
+    field public static final int CONCURRENT_SERVICES_NOT_ALLOWED = 2091; // 0x82b
+    field public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 2080; // 0x820
+    field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
+    field public static final int CONGESTION = 2106; // 0x83a
+    field public static final int CONNECTION_RELEASED = 2113; // 0x841
+    field public static final int CS_DOMAIN_NOT_AVAILABLE = 2181; // 0x885
+    field public static final int CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 2188; // 0x88c
+    field public static final int DATA_PLAN_EXPIRED = 2198; // 0x896
+    field public static final int DATA_ROAMING_SETTINGS_DISABLED = 2064; // 0x810
+    field public static final int DATA_SETTINGS_DISABLED = 2063; // 0x80f
+    field public static final int DBM_OR_SMS_IN_PROGRESS = 2211; // 0x8a3
+    field public static final int DDS_SWITCHED = 2065; // 0x811
+    field public static final int DDS_SWITCH_IN_PROGRESS = 2067; // 0x813
+    field public static final int DRB_RELEASED_BY_RRC = 2112; // 0x840
+    field public static final int DS_EXPLICIT_DEACTIVATION = 2125; // 0x84d
+    field public static final int DUAL_SWITCH = 2227; // 0x8b3
+    field public static final int DUN_CALL_DISALLOWED = 2056; // 0x808
+    field public static final int DUPLICATE_BEARER_ID = 2118; // 0x846
+    field public static final int EHRPD_TO_HRPD_FALLBACK = 2049; // 0x801
+    field public static final int EMBMS_NOT_ENABLED = 2193; // 0x891
+    field public static final int EMBMS_REGULAR_DEACTIVATION = 2195; // 0x893
+    field public static final int EMERGENCY_IFACE_ONLY = 116; // 0x74
+    field public static final int EMERGENCY_MODE = 2221; // 0x8ad
+    field public static final int EMM_ACCESS_BARRED = 115; // 0x73
+    field public static final int EMM_ACCESS_BARRED_INFINITE_RETRY = 121; // 0x79
+    field public static final int EMM_ATTACH_FAILED = 2115; // 0x843
+    field public static final int EMM_ATTACH_STARTED = 2116; // 0x844
+    field public static final int EMM_DETACHED = 2114; // 0x842
+    field public static final int EMM_T3417_EXPIRED = 2130; // 0x852
+    field public static final int EMM_T3417_EXT_EXPIRED = 2131; // 0x853
+    field public static final int EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 2178; // 0x882
+    field public static final int EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 2179; // 0x883
+    field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
+    field public static final int ESM_BAD_OTA_MESSAGE = 2122; // 0x84a
+    field public static final int ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 2120; // 0x848
+    field public static final int ESM_COLLISION_SCENARIOS = 2119; // 0x847
+    field public static final int ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 2124; // 0x84c
+    field public static final int ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 2123; // 0x84b
+    field public static final int ESM_FAILURE = 2182; // 0x886
+    field public static final int ESM_INFO_NOT_RECEIVED = 53; // 0x35
+    field public static final int ESM_LOCAL_CAUSE_NONE = 2126; // 0x84e
+    field public static final int ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 2121; // 0x849
+    field public static final int ESM_PROCEDURE_TIME_OUT = 2155; // 0x86b
+    field public static final int ESM_UNKNOWN_EPS_BEARER_CONTEXT = 2111; // 0x83f
+    field public static final int EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 2201; // 0x899
+    field public static final int EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 2200; // 0x898
+    field public static final int EVDO_HDR_CHANGED = 2202; // 0x89a
+    field public static final int EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 2206; // 0x89e
+    field public static final int EVDO_HDR_EXITED = 2203; // 0x89b
+    field public static final int EVDO_HDR_NO_SESSION = 2204; // 0x89c
+    field public static final int EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 2205; // 0x89d
+    field public static final int FADE = 2217; // 0x8a9
+    field public static final int FAILED_TO_ACQUIRE_COLOCATED_HDR = 2207; // 0x89f
+    field public static final int FEATURE_NOT_SUPP = 40; // 0x28
+    field public static final int FILTER_SEMANTIC_ERROR = 44; // 0x2c
+    field public static final int FILTER_SYTAX_ERROR = 45; // 0x2d
+    field public static final int FORBIDDEN_APN_NAME = 2066; // 0x812
+    field public static final int GPRS_REGISTRATION_FAIL = -2; // 0xfffffffe
+    field public static final int GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 2097; // 0x831
+    field public static final int GPRS_SERVICES_NOT_ALLOWED = 2098; // 0x832
+    field public static final int GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 2103; // 0x837
+    field public static final int HANDOFF_PREFERENCE_CHANGED = 2251; // 0x8cb
+    field public static final int HDR_ACCESS_FAILURE = 2213; // 0x8a5
+    field public static final int HDR_FADE = 2212; // 0x8a4
+    field public static final int HDR_NO_LOCK_GRANTED = 2210; // 0x8a2
+    field public static final int IFACE_AND_POL_FAMILY_MISMATCH = 120; // 0x78
+    field public static final int IFACE_MISMATCH = 117; // 0x75
+    field public static final int ILLEGAL_ME = 2096; // 0x830
+    field public static final int ILLEGAL_MS = 2095; // 0x82f
+    field public static final int IMEI_NOT_ACCEPTED = 2177; // 0x881
+    field public static final int IMPLICITLY_DETACHED = 2100; // 0x834
+    field public static final int IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 2176; // 0x880
+    field public static final int INCOMING_CALL_REJECTED = 2092; // 0x82c
+    field public static final int INSUFFICIENT_RESOURCES = 26; // 0x1a
+    field public static final int INTERFACE_IN_USE = 2058; // 0x80a
+    field public static final int INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 114; // 0x72
+    field public static final int INTERNAL_EPC_NONEPC_TRANSITION = 2057; // 0x809
+    field public static final int INVALID_CONNECTION_ID = 2156; // 0x86c
+    field public static final int INVALID_DNS_ADDR = 123; // 0x7b
+    field public static final int INVALID_EMM_STATE = 2190; // 0x88e
+    field public static final int INVALID_MANDATORY_INFO = 96; // 0x60
+    field public static final int INVALID_MODE = 2223; // 0x8af
+    field public static final int INVALID_PCSCF_ADDR = 113; // 0x71
+    field public static final int INVALID_PCSCF_OR_DNS_ADDRESS = 124; // 0x7c
+    field public static final int INVALID_PRIMARY_NSAPI = 2158; // 0x86e
+    field public static final int INVALID_SIM_STATE = 2224; // 0x8b0
+    field public static final int INVALID_TRANSACTION_ID = 81; // 0x51
+    field public static final int IPV6_ADDRESS_TRANSFER_FAILED = 2047; // 0x7ff
+    field public static final int IPV6_PREFIX_UNAVAILABLE = 2250; // 0x8ca
+    field public static final int IP_ADDRESS_MISMATCH = 119; // 0x77
+    field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
+    field public static final int IRAT_HANDOVER_FAILED = 2194; // 0x892
+    field public static final int IS707B_MAX_ACCESS_PROBES = 2089; // 0x829
+    field public static final int LIMITED_TO_IPV4 = 2234; // 0x8ba
+    field public static final int LIMITED_TO_IPV6 = 2235; // 0x8bb
+    field public static final int LLC_SNDCP = 25; // 0x19
+    field public static final int LOCAL_END = 2215; // 0x8a7
+    field public static final int LOCATION_AREA_NOT_ALLOWED = 2102; // 0x836
+    field public static final int LOST_CONNECTION = 65540; // 0x10004
+    field public static final int LOWER_LAYER_REGISTRATION_FAILURE = 2197; // 0x895
+    field public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 2044; // 0x7fc
+    field public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 2117; // 0x845
+    field public static final int LTE_THROTTLING_NOT_REQUIRED = 2127; // 0x84f
+    field public static final int MAC_FAILURE = 2183; // 0x887
+    field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
+    field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
+    field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
+    field public static final int MAX_IPV4_CONNECTIONS = 2052; // 0x804
+    field public static final int MAX_IPV6_CONNECTIONS = 2053; // 0x805
+    field public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
+    field public static final int MESSAGE_INCORRECT_SEMANTIC = 95; // 0x5f
+    field public static final int MESSAGE_TYPE_UNSUPPORTED = 97; // 0x61
+    field public static final int MIP_CONFIG_FAILURE = 2050; // 0x802
+    field public static final int MIP_FA_ADMIN_PROHIBITED = 2001; // 0x7d1
+    field public static final int MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 2012; // 0x7dc
+    field public static final int MIP_FA_ENCAPSULATION_UNAVAILABLE = 2008; // 0x7d8
+    field public static final int MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 2004; // 0x7d4
+    field public static final int MIP_FA_INSUFFICIENT_RESOURCES = 2002; // 0x7d2
+    field public static final int MIP_FA_MALFORMED_REPLY = 2007; // 0x7d7
+    field public static final int MIP_FA_MALFORMED_REQUEST = 2006; // 0x7d6
+    field public static final int MIP_FA_MISSING_CHALLENGE = 2017; // 0x7e1
+    field public static final int MIP_FA_MISSING_HOME_ADDRESS = 2015; // 0x7df
+    field public static final int MIP_FA_MISSING_HOME_AGENT = 2014; // 0x7de
+    field public static final int MIP_FA_MISSING_NAI = 2013; // 0x7dd
+    field public static final int MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2003; // 0x7d3
+    field public static final int MIP_FA_REASON_UNSPECIFIED = 2000; // 0x7d0
+    field public static final int MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 2005; // 0x7d5
+    field public static final int MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 2011; // 0x7db
+    field public static final int MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 2010; // 0x7da
+    field public static final int MIP_FA_STALE_CHALLENGE = 2018; // 0x7e2
+    field public static final int MIP_FA_UNKNOWN_CHALLENGE = 2016; // 0x7e0
+    field public static final int MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 2009; // 0x7d9
+    field public static final int MIP_HA_ADMIN_PROHIBITED = 2020; // 0x7e4
+    field public static final int MIP_HA_ENCAPSULATION_UNAVAILABLE = 2029; // 0x7ed
+    field public static final int MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 2023; // 0x7e7
+    field public static final int MIP_HA_INSUFFICIENT_RESOURCES = 2021; // 0x7e5
+    field public static final int MIP_HA_MALFORMED_REQUEST = 2025; // 0x7e9
+    field public static final int MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2022; // 0x7e6
+    field public static final int MIP_HA_REASON_UNSPECIFIED = 2019; // 0x7e3
+    field public static final int MIP_HA_REGISTRATION_ID_MISMATCH = 2024; // 0x7e8
+    field public static final int MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 2028; // 0x7ec
+    field public static final int MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 2027; // 0x7eb
+    field public static final int MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 2026; // 0x7ea
+    field public static final int MISSING_UNKNOWN_APN = 27; // 0x1b
+    field public static final int MODEM_APP_PREEMPTED = 2032; // 0x7f0
+    field public static final int MODEM_RESTART = 2037; // 0x7f5
+    field public static final int MSC_TEMPORARILY_NOT_REACHABLE = 2180; // 0x884
+    field public static final int MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101; // 0x65
+    field public static final int MSG_TYPE_NONCOMPATIBLE_STATE = 98; // 0x62
+    field public static final int MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 2099; // 0x833
+    field public static final int MULTIPLE_PDP_CALL_NOT_ALLOWED = 2192; // 0x890
+    field public static final int MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 55; // 0x37
+    field public static final int NAS_LAYER_FAILURE = 2191; // 0x88f
+    field public static final int NAS_REQUEST_REJECTED_BY_NETWORK = 2167; // 0x877
+    field public static final int NAS_SIGNALLING = 14; // 0xe
+    field public static final int NETWORK_FAILURE = 38; // 0x26
+    field public static final int NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 2154; // 0x86a
+    field public static final int NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 2153; // 0x869
+    field public static final int NETWORK_INITIATED_TERMINATION = 2031; // 0x7ef
+    field public static final int NONE = 0; // 0x0
+    field public static final int NON_IP_NOT_SUPPORTED = 2069; // 0x815
+    field public static final int NORMAL_RELEASE = 2218; // 0x8aa
+    field public static final int NO_CDMA_SERVICE = 2084; // 0x824
+    field public static final int NO_COLLOCATED_HDR = 2225; // 0x8b1
+    field public static final int NO_EPS_BEARER_CONTEXT_ACTIVATED = 2189; // 0x88d
+    field public static final int NO_GPRS_CONTEXT = 2094; // 0x82e
+    field public static final int NO_HYBRID_HDR_SERVICE = 2209; // 0x8a1
+    field public static final int NO_PDP_CONTEXT_ACTIVATED = 2107; // 0x83b
+    field public static final int NO_RESPONSE_FROM_BASE_STATION = 2081; // 0x821
+    field public static final int NO_SERVICE = 2216; // 0x8a8
+    field public static final int NO_SERVICE_ON_GATEWAY = 2093; // 0x82d
+    field public static final int NSAPI_IN_USE = 35; // 0x23
+    field public static final int NULL_APN_DISALLOWED = 2061; // 0x80d
+    field public static final int OEM_DCFAILCAUSE_1 = 4097; // 0x1001
+    field public static final int OEM_DCFAILCAUSE_10 = 4106; // 0x100a
+    field public static final int OEM_DCFAILCAUSE_11 = 4107; // 0x100b
+    field public static final int OEM_DCFAILCAUSE_12 = 4108; // 0x100c
+    field public static final int OEM_DCFAILCAUSE_13 = 4109; // 0x100d
+    field public static final int OEM_DCFAILCAUSE_14 = 4110; // 0x100e
+    field public static final int OEM_DCFAILCAUSE_15 = 4111; // 0x100f
+    field public static final int OEM_DCFAILCAUSE_2 = 4098; // 0x1002
+    field public static final int OEM_DCFAILCAUSE_3 = 4099; // 0x1003
+    field public static final int OEM_DCFAILCAUSE_4 = 4100; // 0x1004
+    field public static final int OEM_DCFAILCAUSE_5 = 4101; // 0x1005
+    field public static final int OEM_DCFAILCAUSE_6 = 4102; // 0x1006
+    field public static final int OEM_DCFAILCAUSE_7 = 4103; // 0x1007
+    field public static final int OEM_DCFAILCAUSE_8 = 4104; // 0x1008
+    field public static final int OEM_DCFAILCAUSE_9 = 4105; // 0x1009
+    field public static final int ONLY_IPV4V6_ALLOWED = 57; // 0x39
+    field public static final int ONLY_IPV4_ALLOWED = 50; // 0x32
+    field public static final int ONLY_IPV6_ALLOWED = 51; // 0x33
+    field public static final int ONLY_NON_IP_ALLOWED = 58; // 0x3a
+    field public static final int ONLY_SINGLE_BEARER_ALLOWED = 52; // 0x34
+    field public static final int OPERATOR_BARRED = 8; // 0x8
+    field public static final int OTASP_COMMIT_IN_PROGRESS = 2208; // 0x8a0
+    field public static final int PDN_CONN_DOES_NOT_EXIST = 54; // 0x36
+    field public static final int PDN_INACTIVITY_TIMER_EXPIRED = 2051; // 0x803
+    field public static final int PDN_IPV4_CALL_DISALLOWED = 2033; // 0x7f1
+    field public static final int PDN_IPV4_CALL_THROTTLED = 2034; // 0x7f2
+    field public static final int PDN_IPV6_CALL_DISALLOWED = 2035; // 0x7f3
+    field public static final int PDN_IPV6_CALL_THROTTLED = 2036; // 0x7f4
+    field public static final int PDN_NON_IP_CALL_DISALLOWED = 2071; // 0x817
+    field public static final int PDN_NON_IP_CALL_THROTTLED = 2070; // 0x816
+    field public static final int PDP_ACTIVATE_MAX_RETRY_FAILED = 2109; // 0x83d
+    field public static final int PDP_DUPLICATE = 2104; // 0x838
+    field public static final int PDP_ESTABLISH_TIMEOUT_EXPIRED = 2161; // 0x871
+    field public static final int PDP_INACTIVE_TIMEOUT_EXPIRED = 2163; // 0x873
+    field public static final int PDP_LOWERLAYER_ERROR = 2164; // 0x874
+    field public static final int PDP_MODIFY_COLLISION = 2165; // 0x875
+    field public static final int PDP_MODIFY_TIMEOUT_EXPIRED = 2162; // 0x872
+    field public static final int PDP_PPP_NOT_SUPPORTED = 2038; // 0x7f6
+    field public static final int PDP_WITHOUT_ACTIVE_TFT = 46; // 0x2e
+    field public static final int PHONE_IN_USE = 2222; // 0x8ae
+    field public static final int PHYSICAL_LINK_CLOSE_IN_PROGRESS = 2040; // 0x7f8
+    field public static final int PLMN_NOT_ALLOWED = 2101; // 0x835
+    field public static final int PPP_AUTH_FAILURE = 2229; // 0x8b5
+    field public static final int PPP_CHAP_FAILURE = 2232; // 0x8b8
+    field public static final int PPP_CLOSE_IN_PROGRESS = 2233; // 0x8b9
+    field public static final int PPP_OPTION_MISMATCH = 2230; // 0x8b6
+    field public static final int PPP_PAP_FAILURE = 2231; // 0x8b7
+    field public static final int PPP_TIMEOUT = 2228; // 0x8b4
+    field public static final int PREF_RADIO_TECH_CHANGED = -4; // 0xfffffffc
+    field public static final int PROFILE_BEARER_INCOMPATIBLE = 2042; // 0x7fa
+    field public static final int PROTOCOL_ERRORS = 111; // 0x6f
+    field public static final int QOS_NOT_ACCEPTED = 37; // 0x25
+    field public static final int RADIO_ACCESS_BEARER_FAILURE = 2110; // 0x83e
+    field public static final int RADIO_ACCESS_BEARER_SETUP_FAILURE = 2160; // 0x870
+    field public static final int RADIO_NOT_AVAILABLE = 65537; // 0x10001
+    field public static final int RADIO_POWER_OFF = -5; // 0xfffffffb
+    field public static final int REDIRECTION_OR_HANDOFF_IN_PROGRESS = 2220; // 0x8ac
+    field public static final int REGISTRATION_FAIL = -1; // 0xffffffff
+    field public static final int REGULAR_DEACTIVATION = 36; // 0x24
+    field public static final int REJECTED_BY_BASE_STATION = 2082; // 0x822
+    field public static final int RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 2173; // 0x87d
+    field public static final int RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 2174; // 0x87e
+    field public static final int RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 2171; // 0x87b
+    field public static final int RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 2175; // 0x87f
+    field public static final int RRC_CONNECTION_ABORT_REQUEST = 2151; // 0x867
+    field public static final int RRC_CONNECTION_ACCESS_BARRED = 2139; // 0x85b
+    field public static final int RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 2137; // 0x859
+    field public static final int RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 2138; // 0x85a
+    field public static final int RRC_CONNECTION_CELL_NOT_CAMPED = 2144; // 0x860
+    field public static final int RRC_CONNECTION_CELL_RESELECTION = 2140; // 0x85c
+    field public static final int RRC_CONNECTION_CONFIG_FAILURE = 2141; // 0x85d
+    field public static final int RRC_CONNECTION_INVALID_REQUEST = 2168; // 0x878
+    field public static final int RRC_CONNECTION_LINK_FAILURE = 2143; // 0x85f
+    field public static final int RRC_CONNECTION_NORMAL_RELEASE = 2147; // 0x863
+    field public static final int RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 2150; // 0x866
+    field public static final int RRC_CONNECTION_RADIO_LINK_FAILURE = 2148; // 0x864
+    field public static final int RRC_CONNECTION_REESTABLISHMENT_FAILURE = 2149; // 0x865
+    field public static final int RRC_CONNECTION_REJECT_BY_NETWORK = 2146; // 0x862
+    field public static final int RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 2172; // 0x87c
+    field public static final int RRC_CONNECTION_RF_UNAVAILABLE = 2170; // 0x87a
+    field public static final int RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 2152; // 0x868
+    field public static final int RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 2145; // 0x861
+    field public static final int RRC_CONNECTION_TIMER_EXPIRED = 2142; // 0x85e
+    field public static final int RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 2169; // 0x879
+    field public static final int RRC_UPLINK_CONNECTION_RELEASE = 2134; // 0x856
+    field public static final int RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 2132; // 0x854
+    field public static final int RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 2133; // 0x855
+    field public static final int RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 2136; // 0x858
+    field public static final int RRC_UPLINK_RADIO_LINK_FAILURE = 2135; // 0x857
+    field public static final int RUIM_NOT_PRESENT = 2085; // 0x825
+    field public static final int SECURITY_MODE_REJECTED = 2186; // 0x88a
+    field public static final int SERVICE_NOT_ALLOWED_ON_PLMN = 2129; // 0x851
+    field public static final int SERVICE_OPTION_NOT_SUBSCRIBED = 33; // 0x21
+    field public static final int SERVICE_OPTION_NOT_SUPPORTED = 32; // 0x20
+    field public static final int SERVICE_OPTION_OUT_OF_ORDER = 34; // 0x22
+    field public static final int SIGNAL_LOST = -3; // 0xfffffffd
+    field public static final int SIM_CARD_CHANGED = 2043; // 0x7fb
+    field public static final int SYNCHRONIZATION_FAILURE = 2184; // 0x888
+    field public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196; // 0x894
+    field public static final int TETHERED_CALL_ACTIVE = -6; // 0xfffffffa
+    field public static final int TFT_SEMANTIC_ERROR = 41; // 0x29
+    field public static final int TFT_SYTAX_ERROR = 42; // 0x2a
+    field public static final int THERMAL_EMERGENCY = 2090; // 0x82a
+    field public static final int THERMAL_MITIGATION = 2062; // 0x80e
+    field public static final int TRAT_SWAP_FAILED = 2048; // 0x800
+    field public static final int UE_INITIATED_DETACH_OR_DISCONNECT = 128; // 0x80
+    field public static final int UE_IS_ENTERING_POWERSAVE_MODE = 2226; // 0x8b2
+    field public static final int UE_RAT_CHANGE = 2105; // 0x839
+    field public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 2185; // 0x889
+    field public static final int UMTS_HANDOVER_TO_IWLAN = 2199; // 0x897
+    field public static final int UMTS_REACTIVATION_REQ = 39; // 0x27
+    field public static final int UNACCEPTABLE_NETWORK_PARAMETER = 65538; // 0x10002
+    field public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187; // 0x88b
+    field public static final int UNKNOWN = 65536; // 0x10000
+    field public static final int UNKNOWN_INFO_ELEMENT = 99; // 0x63
+    field public static final int UNKNOWN_PDP_ADDRESS_TYPE = 28; // 0x1c
+    field public static final int UNKNOWN_PDP_CONTEXT = 43; // 0x2b
+    field public static final int UNPREFERRED_RAT = 2039; // 0x7f7
+    field public static final int UNSUPPORTED_1X_PREV = 2214; // 0x8a6
+    field public static final int UNSUPPORTED_APN_IN_CURRENT_PLMN = 66; // 0x42
+    field public static final int UNSUPPORTED_QCI_VALUE = 59; // 0x3b
+    field public static final int USER_AUTHENTICATION = 29; // 0x1d
+    field public static final int VSNCP_ADMINISTRATIVELY_PROHIBITED = 2245; // 0x8c5
+    field public static final int VSNCP_APN_UNAUTHORIZED = 2238; // 0x8be
+    field public static final int VSNCP_GEN_ERROR = 2237; // 0x8bd
+    field public static final int VSNCP_INSUFFICIENT_PARAMETERS = 2243; // 0x8c3
+    field public static final int VSNCP_NO_PDN_GATEWAY_ADDRESS = 2240; // 0x8c0
+    field public static final int VSNCP_PDN_EXISTS_FOR_THIS_APN = 2248; // 0x8c8
+    field public static final int VSNCP_PDN_GATEWAY_REJECT = 2242; // 0x8c2
+    field public static final int VSNCP_PDN_GATEWAY_UNREACHABLE = 2241; // 0x8c1
+    field public static final int VSNCP_PDN_ID_IN_USE = 2246; // 0x8c6
+    field public static final int VSNCP_PDN_LIMIT_EXCEEDED = 2239; // 0x8bf
+    field public static final int VSNCP_RECONNECT_NOT_ALLOWED = 2249; // 0x8c9
+    field public static final int VSNCP_RESOURCE_UNAVAILABLE = 2244; // 0x8c4
+    field public static final int VSNCP_SUBSCRIBER_LIMITATION = 2247; // 0x8c7
+    field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc
+  }
+
   public final class DisplayInfo implements android.os.Parcelable {
     method public int describeContents();
     method public int getNetworkType();
@@ -47280,32 +47605,8 @@
 
   public final class PhoneCapability implements android.os.Parcelable {
     method public int describeContents();
-    method @NonNull public java.util.List<java.lang.Integer> getBands(int);
-    method @NonNull public java.util.List<java.util.List<java.lang.Long>> getConcurrentFeaturesSupport();
-    method @NonNull public java.util.List<java.lang.String> getLogicalModemUuids();
-    method public int getMaxActiveDedicatedBearers();
-    method public int getMaxActiveInternetData();
-    method public int getMaxActivePsVoice();
-    method public long getPsDataConnectionLingerTimeMillis();
-    method @NonNull public java.util.List<android.telephony.SimSlotCapability> getSimSlotCapabilities();
-    method public long getSupportedRats();
-    method public int getUeCategory(boolean, int);
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.telephony.PhoneCapability> CREATOR;
-    field public static final long MODEM_FEATURE_3GPP2_REG = 1L; // 0x1L
-    field public static final long MODEM_FEATURE_3GPP_REG = 2L; // 0x2L
-    field public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 4L; // 0x4L
-    field public static final long MODEM_FEATURE_CSIM = 8192L; // 0x2000L
-    field public static final long MODEM_FEATURE_CS_VOICE_SESSION = 512L; // 0x200L
-    field public static final long MODEM_FEATURE_DEDICATED_BEARER = 2048L; // 0x800L
-    field public static final long MODEM_FEATURE_EUTRAN_REG = 32L; // 0x20L
-    field public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 128L; // 0x80L
-    field public static final long MODEM_FEATURE_GERAN_REG = 8L; // 0x8L
-    field public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1024L; // 0x400L
-    field public static final long MODEM_FEATURE_NETWORK_SCAN = 4096L; // 0x1000L
-    field public static final long MODEM_FEATURE_NGRAN_REG = 64L; // 0x40L
-    field public static final long MODEM_FEATURE_PS_VOICE_REG = 256L; // 0x100L
-    field public static final long MODEM_FEATURE_UTRAN_REG = 16L; // 0x10L
   }
 
   public class PhoneNumberFormattingTextWatcher implements android.text.TextWatcher {
@@ -47495,18 +47796,6 @@
     field public static final int INVALID = 2147483647; // 0x7fffffff
   }
 
-  public final class SimSlotCapability implements android.os.Parcelable {
-    method public int describeContents();
-    method public int getPhysicalSlotIndex();
-    method public int getSlotType();
-    method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.telephony.SimSlotCapability> CREATOR;
-    field public static final int SLOT_TYPE_EUICC = 3; // 0x3
-    field public static final int SLOT_TYPE_IUICC = 2; // 0x2
-    field public static final int SLOT_TYPE_SOFT_SIM = 4; // 0x4
-    field public static final int SLOT_TYPE_UICC = 1; // 0x1
-  }
-
   public final class SmsManager {
     method public String createAppSpecificSmsToken(android.app.PendingIntent);
     method @Nullable public String createAppSpecificSmsTokenWithPackageInfo(@Nullable String, @NonNull android.app.PendingIntent);
@@ -47863,7 +48152,6 @@
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PRECISE_PHONE_STATE}) public int getNetworkSelectionMode();
     method public String getNetworkSpecifier();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public int getNetworkType();
-    method @Nullable @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public android.telephony.PhoneCapability getPhoneCapability();
     method @Deprecated public int getPhoneCount();
     method public int getPhoneType();
     method @RequiresPermission(anyOf={"android.permission.READ_PRIVILEGED_PHONE_STATE", android.Manifest.permission.READ_PHONE_STATE}) public int getPreferredOpportunisticDataSubscription();
@@ -53231,11 +53519,13 @@
     method public android.graphics.Canvas lockHardwareCanvas();
     method public void readFromParcel(android.os.Parcel);
     method public void release();
-    method public void setFrameRate(@FloatRange(from=0.0) float);
+    method public void setFrameRate(@FloatRange(from=0.0) float, int);
     method @Deprecated public void unlockCanvas(android.graphics.Canvas);
     method public void unlockCanvasAndPost(android.graphics.Canvas);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.Surface> CREATOR;
+    field public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0; // 0x0
+    field public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1; // 0x1
     field public static final int ROTATION_0 = 0; // 0x0
     field public static final int ROTATION_180 = 2; // 0x2
     field public static final int ROTATION_270 = 3; // 0x3
@@ -53275,7 +53565,7 @@
     method @NonNull public android.view.SurfaceControl.Transaction reparent(@NonNull android.view.SurfaceControl, @Nullable android.view.SurfaceControl);
     method @NonNull public android.view.SurfaceControl.Transaction setAlpha(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0, to=1.0) float);
     method @NonNull public android.view.SurfaceControl.Transaction setBufferSize(@NonNull android.view.SurfaceControl, @IntRange(from=0) int, @IntRange(from=0) int);
-    method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float);
+    method @NonNull public android.view.SurfaceControl.Transaction setFrameRate(@NonNull android.view.SurfaceControl, @FloatRange(from=0.0) float, int);
     method @NonNull public android.view.SurfaceControl.Transaction setGeometry(@NonNull android.view.SurfaceControl, @Nullable android.graphics.Rect, @Nullable android.graphics.Rect, int);
     method @NonNull public android.view.SurfaceControl.Transaction setLayer(@NonNull android.view.SurfaceControl, @IntRange(from=java.lang.Integer.MIN_VALUE, to=java.lang.Integer.MAX_VALUE) int);
     method @NonNull public android.view.SurfaceControl.Transaction setVisibility(@NonNull android.view.SurfaceControl, boolean);
@@ -53883,6 +54173,7 @@
     method public boolean requestRectangleOnScreen(android.graphics.Rect);
     method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
     method public final void requestUnbufferedDispatch(android.view.MotionEvent);
+    method public final void requestUnbufferedDispatch(int);
     method @NonNull public final <T extends android.view.View> T requireViewById(@IdRes int);
     method public void resetPivot();
     method public static int resolveSize(int, int);
@@ -55596,6 +55887,7 @@
     method public CharSequence getContentDescription();
     method public int getDrawingOrder();
     method public CharSequence getError();
+    method @Nullable public android.view.accessibility.AccessibilityNodeInfo.ExtraRenderingInfo getExtraRenderingInfo();
     method public android.os.Bundle getExtras();
     method public CharSequence getHintText();
     method public int getInputType();
@@ -55748,6 +56040,7 @@
     field public static final int ACTION_SET_SELECTION = 131072; // 0x20000
     field public static final int ACTION_SET_TEXT = 2097152; // 0x200000
     field @NonNull public static final android.os.Parcelable.Creator<android.view.accessibility.AccessibilityNodeInfo> CREATOR;
+    field public static final String EXTRA_DATA_RENDERING_INFO_KEY = "android.view.accessibility.extra.DATA_RENDERING_INFO_KEY";
     field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
     field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX";
     field public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY = "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_KEY";
@@ -55835,6 +56128,12 @@
     method public static android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo obtain(int, int, int, int, boolean, boolean);
   }
 
+  public static final class AccessibilityNodeInfo.ExtraRenderingInfo {
+    method @Nullable public android.util.Size getLayoutParams();
+    method public float getTextSizeInPx();
+    method public int getTextSizeUnit();
+  }
+
   public static final class AccessibilityNodeInfo.RangeInfo {
     ctor public AccessibilityNodeInfo.RangeInfo(int, float, float, float);
     method public float getCurrent();
@@ -56461,7 +56760,7 @@
     method public int describeContents();
     method @NonNull public android.util.Size getMaxSize();
     method @NonNull public android.util.Size getMinSize();
-    method @Nullable public String getStyle();
+    method @Nullable public android.os.Bundle getStyle();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.view.inline.InlinePresentationSpec> CREATOR;
   }
@@ -56469,7 +56768,7 @@
   public static final class InlinePresentationSpec.Builder {
     ctor public InlinePresentationSpec.Builder(@NonNull android.util.Size, @NonNull android.util.Size);
     method @NonNull public android.view.inline.InlinePresentationSpec build();
-    method @NonNull public android.view.inline.InlinePresentationSpec.Builder setStyle(@Nullable String);
+    method @NonNull public android.view.inline.InlinePresentationSpec.Builder setStyle(@Nullable android.os.Bundle);
   }
 
 }
@@ -60817,6 +61116,7 @@
     method @Nullable public android.graphics.drawable.Drawable getTextSelectHandleLeft();
     method @Nullable public android.graphics.drawable.Drawable getTextSelectHandleRight();
     method @android.view.ViewDebug.ExportedProperty(category="text") public float getTextSize();
+    method public int getTextSizeUnit();
     method public int getTotalPaddingBottom();
     method public int getTotalPaddingEnd();
     method public int getTotalPaddingLeft();
diff --git a/api/module-lib-current.txt b/api/module-lib-current.txt
index 7b66f73..6863221 100644
--- a/api/module-lib-current.txt
+++ b/api/module-lib-current.txt
@@ -30,7 +30,6 @@
   }
 
   public class TetheringConstants {
-    ctor public TetheringConstants();
     field public static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
     field public static final String EXTRA_PROVISION_CALLBACK = "extraProvisionCallback";
     field public static final String EXTRA_REM_TETHER_TYPE = "extraRemTetherType";
diff --git a/api/module-lib-lint-baseline.txt b/api/module-lib-lint-baseline.txt
index 6e59596..56f7a02 100644
--- a/api/module-lib-lint-baseline.txt
+++ b/api/module-lib-lint-baseline.txt
@@ -27,7 +27,3 @@
     Public class android.location.GnssAntennaInfo.PhaseCenterVariationCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections
 PrivateSuperclass: android.location.GnssAntennaInfo.SignalGainCorrections:
     Public class android.location.GnssAntennaInfo.SignalGainCorrections extends private class android.location.GnssAntennaInfo.SphericalCorrections
-
-
-StaticUtils: android.net.TetheringConstants:
-    Fully-static utility classes must not have constructor
diff --git a/api/system-current.txt b/api/system-current.txt
index a8c2453..f4a1d84 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -118,6 +118,7 @@
     field public static final String MANAGE_CONTENT_CAPTURE = "android.permission.MANAGE_CONTENT_CAPTURE";
     field public static final String MANAGE_CONTENT_SUGGESTIONS = "android.permission.MANAGE_CONTENT_SUGGESTIONS";
     field public static final String MANAGE_DEBUGGING = "android.permission.MANAGE_DEBUGGING";
+    field public static final String MANAGE_FACTORY_RESET_PROTECTION = "android.permission.MANAGE_FACTORY_RESET_PROTECTION";
     field public static final String MANAGE_IPSEC_TUNNELS = "android.permission.MANAGE_IPSEC_TUNNELS";
     field public static final String MANAGE_ONE_TIME_PERMISSION_SESSIONS = "android.permission.MANAGE_ONE_TIME_PERMISSION_SESSIONS";
     field public static final String MANAGE_ROLE_HOLDERS = "android.permission.MANAGE_ROLE_HOLDERS";
@@ -136,7 +137,6 @@
     field public static final String MODIFY_PARENTAL_CONTROLS = "android.permission.MODIFY_PARENTAL_CONTROLS";
     field public static final String MODIFY_QUIET_MODE = "android.permission.MODIFY_QUIET_MODE";
     field public static final String MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE = "android.permission.MODIFY_SETTINGS_OVERRIDEABLE_BY_RESTORE";
-    field public static final String MONITOR_DEVICE_CONFIG_ACCESS = "android.permission.MONITOR_DEVICE_CONFIG_ACCESS";
     field public static final String MOVE_PACKAGE = "android.permission.MOVE_PACKAGE";
     field public static final String NETWORK_AIRPLANE_MODE = "android.permission.NETWORK_AIRPLANE_MODE";
     field public static final String NETWORK_CARRIER_PROVISIONING = "android.permission.NETWORK_CARRIER_PROVISIONING";
@@ -371,10 +371,11 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.app.AppOpsManager.PackageOps> getPackagesForOps(@Nullable String[]);
     method public static int opToDefaultMode(@NonNull String);
     method @Nullable public static String opToPermission(@NonNull String);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
+    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
+    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
     field public static final String OPSTR_ACCEPT_HANDOVER = "android:accept_handover";
     field public static final String OPSTR_ACCESS_ACCESSIBILITY = "android:access_accessibility";
+    field public static final String OPSTR_ACCESS_CALL_AUDIO = "android:access_call_audio";
     field public static final String OPSTR_ACCESS_NOTIFICATIONS = "android:access_notifications";
     field public static final String OPSTR_ACTIVATE_VPN = "android:activate_vpn";
     field public static final String OPSTR_ASSIST_SCREENSHOT = "android:assist_screenshot";
@@ -887,7 +888,7 @@
     field public static final String ACTION_PROVISION_FINALIZATION = "android.app.action.PROVISION_FINALIZATION";
     field public static final String ACTION_PROVISION_FINANCED_DEVICE = "android.app.action.PROVISION_FINANCED_DEVICE";
     field public static final String ACTION_PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE = "android.app.action.PROVISION_MANAGED_DEVICE_FROM_TRUSTED_SOURCE";
-    field public static final String ACTION_RESET_PROTECTION_POLICY_CHANGED = "android.app.action.RESET_PROTECTION_POLICY_CHANGED";
+    field @RequiresPermission(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION) public static final String ACTION_RESET_PROTECTION_POLICY_CHANGED = "android.app.action.RESET_PROTECTION_POLICY_CHANGED";
     field public static final String ACTION_SET_PROFILE_OWNER = "android.app.action.SET_PROFILE_OWNER";
     field public static final String ACTION_STATE_USER_SETUP_COMPLETE = "android.app.action.STATE_USER_SETUP_COMPLETE";
     field public static final String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
@@ -1957,6 +1958,11 @@
     method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
   }
 
+  public static final class IntegrityFormula.SourceStamp {
+    method @NonNull public static android.content.integrity.IntegrityFormula notTrusted();
+    method @NonNull public static android.content.integrity.IntegrityFormula stampCertificateHashEquals(@NonNull String);
+  }
+
   public final class Rule implements android.os.Parcelable {
     ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
     method public int describeContents();
@@ -3774,8 +3780,14 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USB) public void setCurrentFunctions(long);
     field @RequiresPermission(android.Manifest.permission.MANAGE_USB) public static final String ACTION_USB_PORT_CHANGED = "android.hardware.usb.action.USB_PORT_CHANGED";
     field public static final String ACTION_USB_STATE = "android.hardware.usb.action.USB_STATE";
+    field public static final long FUNCTION_ACCESSORY = 2L; // 0x2L
+    field public static final long FUNCTION_ADB = 1L; // 0x1L
+    field public static final long FUNCTION_AUDIO_SOURCE = 64L; // 0x40L
+    field public static final long FUNCTION_MIDI = 8L; // 0x8L
+    field public static final long FUNCTION_MTP = 4L; // 0x4L
     field public static final long FUNCTION_NCM = 1024L; // 0x400L
     field public static final long FUNCTION_NONE = 0L; // 0x0L
+    field public static final long FUNCTION_PTP = 16L; // 0x10L
     field public static final long FUNCTION_RNDIS = 32L; // 0x20L
     field public static final String USB_CONFIGURED = "configured";
     field public static final String USB_CONNECTED = "connected";
@@ -3822,7 +3834,6 @@
 
   public final class GnssCapabilities {
     method public boolean hasGeofencing();
-    method public boolean hasGnssAntennaInfo();
     method public boolean hasLowPowerMode();
     method public boolean hasMeasurementCorrections();
     method public boolean hasMeasurementCorrectionsExcessPathLength();
@@ -4162,7 +4173,6 @@
     method @RequiresPermission(anyOf={android.Manifest.permission.ACCESS_COARSE_LOCATION, android.Manifest.permission.ACCESS_FINE_LOCATION}) public void getCurrentLocation(@NonNull android.location.LocationRequest, @Nullable android.os.CancellationSignal, @NonNull java.util.concurrent.Executor, @NonNull java.util.function.Consumer<android.location.Location>);
     method @Nullable public String getExtraLocationControllerPackage();
     method @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE) public int getGnssBatchSize();
-    method @NonNull @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public android.location.GnssCapabilities getGnssCapabilities();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public void injectGnssMeasurementCorrections(@NonNull android.location.GnssMeasurementCorrections);
     method public boolean isExtraLocationControllerPackageEnabled();
     method public boolean isLocationEnabledForUser(@NonNull android.os.UserHandle);
@@ -4247,15 +4257,15 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioAttributes.Builder setSystemUsage(int);
   }
 
-  public final class AudioDevice implements android.os.Parcelable {
-    ctor public AudioDevice(@NonNull android.media.AudioDeviceInfo);
-    ctor public AudioDevice(int, int, @NonNull String);
+  public final class AudioDeviceAttributes implements android.os.Parcelable {
+    ctor public AudioDeviceAttributes(@NonNull android.media.AudioDeviceInfo);
+    ctor public AudioDeviceAttributes(int, int, @NonNull String);
     method public int describeContents();
     method @NonNull public String getAddress();
     method public int getRole();
     method public int getType();
     method public void writeToParcel(@NonNull android.os.Parcel, int);
-    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDevice> CREATOR;
+    field @NonNull public static final android.os.Parcelable.Creator<android.media.AudioDeviceAttributes> CREATOR;
     field public static final int ROLE_INPUT = 1; // 0x1
     field public static final int ROLE_OUTPUT = 2; // 0x2
   }
@@ -4293,11 +4303,11 @@
     method @IntRange(from=0) public int getAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioProductStrategy> getAudioProductStrategies();
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public static java.util.List<android.media.audiopolicy.AudioVolumeGroup> getAudioVolumeGroups();
-    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDevice> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
+    method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public java.util.List<android.media.AudioDeviceAttributes> getDevicesForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) public int getMaxAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMaxVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getMinVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
-    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDevice getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
+    method @Nullable @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public android.media.AudioDeviceAttributes getPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy);
     method @NonNull @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int[] getSupportedSystemUsages();
     method @IntRange(from=0) @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public int getVolumeIndexForAttributes(@NonNull android.media.AudioAttributes);
     method public boolean isAudioServerRunning();
@@ -4312,7 +4322,7 @@
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setAdditionalOutputDeviceDelay(@NonNull android.media.AudioDeviceInfo, @IntRange(from=0) int);
     method public void setAudioServerStateCallback(@NonNull java.util.concurrent.Executor, @NonNull android.media.AudioManager.AudioServerStateCallback);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setFocusRequestResult(@NonNull android.media.AudioFocusInfo, int, @NonNull android.media.audiopolicy.AudioPolicy);
-    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDevice);
+    method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public boolean setPreferredDeviceForStrategy(@NonNull android.media.audiopolicy.AudioProductStrategy, @NonNull android.media.AudioDeviceAttributes);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setSupportedSystemUsages(@NonNull int[]);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void setVolumeIndexForAttributes(@NonNull android.media.AudioAttributes, int, int);
     method @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING) public void unregisterAudioPolicy(@NonNull android.media.audiopolicy.AudioPolicy);
@@ -4332,7 +4342,7 @@
   }
 
   public static interface AudioManager.OnPreferredDeviceForStrategyChangedListener {
-    method public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDevice);
+    method public void onPreferredDeviceForStrategyChanged(@NonNull android.media.audiopolicy.AudioProductStrategy, @Nullable android.media.AudioDeviceAttributes);
   }
 
   public abstract static class AudioManager.VolumeGroupCallback {
@@ -4412,7 +4422,7 @@
 package android.media.audiofx {
 
   public class AudioEffect {
-    ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDevice);
+    ctor @RequiresPermission("android.permission.MODIFY_DEFAULT_AUDIO_EFFECTS") public AudioEffect(@NonNull java.util.UUID, @NonNull android.media.AudioDeviceAttributes);
   }
 
 }
@@ -4826,7 +4836,7 @@
     method public int getAudioFilterCount();
     method public int getDemuxCount();
     method public int getFilterCapabilities();
-    method @Nullable @Size(5) public int[] getLinkCapabilities();
+    method @NonNull @Size(5) public int[] getLinkCapabilities();
     method public int getPcrFilterCount();
     method public int getPesFilterCount();
     method public int getPlaybackCount();
@@ -4842,7 +4852,7 @@
     method public int addPid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
     method public void close();
     method public int removePid(int, int, @Nullable android.media.tv.tuner.filter.Filter);
-    method public int setKeyToken(@Nullable byte[]);
+    method public int setKeyToken(@NonNull byte[]);
     field public static final int PID_TYPE_MMTP = 2; // 0x2
     field public static final int PID_TYPE_T = 1; // 0x1
   }
@@ -4879,10 +4889,11 @@
   }
 
   public class Tuner implements java.lang.AutoCloseable {
-    ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @NonNull String, int, @Nullable android.media.tv.tuner.Tuner.OnResourceLostListener);
+    ctor @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public Tuner(@NonNull android.content.Context, @Nullable String, int);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelScanning();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int cancelTuning();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearOnTuneEventListener();
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void clearResourceLostListener();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void close();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int connectCiCam(int);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int disconnectCiCam();
@@ -4892,15 +4903,16 @@
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.frontend.FrontendInfo getFrontendInfo();
     method @Nullable public android.media.tv.tuner.frontend.FrontendStatus getFrontendStatus(@NonNull int[]);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_DESCRAMBLER) public android.media.tv.tuner.Descrambler openDescrambler();
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrPlayback openDvrPlayback(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnPlaybackStatusChangedListener);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.dvr.DvrRecorder openDvrRecorder(long, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.dvr.OnRecordStatusChangedListener);
     method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.filter.Filter openFilter(int, int, long, @Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.filter.FilterCallback);
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@Nullable java.util.concurrent.Executor, @Nullable android.media.tv.tuner.LnbCallback);
-    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@Nullable String, @Nullable java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnb(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
+    method @Nullable @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public android.media.tv.tuner.Lnb openLnbByName(@NonNull String, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.LnbCallback);
     method @Nullable public android.media.tv.tuner.filter.TimeFilter openTimeFilter();
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int scan(@NonNull android.media.tv.tuner.frontend.FrontendSettings, int, @NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.ScanCallback);
-    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLna(boolean);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int setLnaEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setOnTuneEventListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.frontend.OnTuneEventListener);
+    method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void setResourceLostListener(@NonNull java.util.concurrent.Executor, @NonNull android.media.tv.tuner.Tuner.OnResourceLostListener);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void shareFrontendFromTuner(@NonNull android.media.tv.tuner.Tuner);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public int tune(@NonNull android.media.tv.tuner.frontend.FrontendSettings);
     method @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER) public void updateResourcePriority(int, int);
@@ -6735,337 +6747,6 @@
 
 }
 
-package android.net.eap {
-
-  public final class EapSessionConfig {
-  }
-
-  public static final class EapSessionConfig.Builder {
-    ctor public EapSessionConfig.Builder();
-    method @NonNull public android.net.eap.EapSessionConfig build();
-    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaConfig(int, int);
-    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapAkaPrimeConfig(int, int, @NonNull String, boolean);
-    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapIdentity(@NonNull byte[]);
-    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapMsChapV2Config(@NonNull String, @NonNull String);
-    method @NonNull public android.net.eap.EapSessionConfig.Builder setEapSimConfig(int, int);
-  }
-
-  public static class EapSessionConfig.EapAkaConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
-  }
-
-  public static class EapSessionConfig.EapAkaPrimeConfig extends android.net.eap.EapSessionConfig.EapAkaConfig {
-    method public boolean allowsMismatchedNetworkNames();
-    method @NonNull public String getNetworkName();
-  }
-
-  public abstract static class EapSessionConfig.EapMethodConfig {
-    method public int getMethodType();
-  }
-
-  public static class EapSessionConfig.EapMsChapV2Config extends android.net.eap.EapSessionConfig.EapMethodConfig {
-    method @NonNull public String getPassword();
-    method @NonNull public String getUsername();
-  }
-
-  public static class EapSessionConfig.EapSimConfig extends android.net.eap.EapSessionConfig.EapUiccConfig {
-  }
-
-  public abstract static class EapSessionConfig.EapUiccConfig extends android.net.eap.EapSessionConfig.EapMethodConfig {
-    method public int getAppType();
-    method public int getSubId();
-  }
-
-}
-
-package android.net.ipsec.ike {
-
-  public final class ChildSaProposal extends android.net.ipsec.ike.SaProposal {
-  }
-
-  public static final class ChildSaProposal.Builder {
-    ctor public ChildSaProposal.Builder();
-    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addDhGroup(int);
-    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addEncryptionAlgorithm(int, int);
-    method @NonNull public android.net.ipsec.ike.ChildSaProposal.Builder addIntegrityAlgorithm(int);
-    method @NonNull public android.net.ipsec.ike.ChildSaProposal build();
-  }
-
-  public interface ChildSessionCallback {
-    method public void onClosed();
-    method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
-    method public void onIpSecTransformCreated(@NonNull android.net.IpSecTransform, int);
-    method public void onIpSecTransformDeleted(@NonNull android.net.IpSecTransform, int);
-    method public void onOpened(@NonNull android.net.ipsec.ike.ChildSessionConfiguration);
-  }
-
-  public final class ChildSessionConfiguration {
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getInboundTrafficSelectors();
-    method @NonNull public java.util.List<android.net.LinkAddress> getInternalAddresses();
-    method @NonNull public java.util.List<java.net.InetAddress> getInternalDhcpServers();
-    method @NonNull public java.util.List<java.net.InetAddress> getInternalDnsServers();
-    method @NonNull public java.util.List<android.net.IpPrefix> getInternalSubnets();
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getOutboundTrafficSelectors();
-  }
-
-  public abstract class ChildSessionParams {
-    method public long getHardLifetime();
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getLocalTrafficSelectors();
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeTrafficSelector> getRemoteTrafficSelectors();
-    method @NonNull public java.util.List<android.net.ipsec.ike.ChildSaProposal> getSaProposals();
-    method public long getSoftLifetime();
-  }
-
-  public class IkeFqdnIdentification extends android.net.ipsec.ike.IkeIdentification {
-    ctor public IkeFqdnIdentification(@NonNull String);
-    field @NonNull public final String fqdn;
-  }
-
-  public abstract class IkeIdentification {
-  }
-
-  public final class IkeIpv4AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
-    ctor public IkeIpv4AddrIdentification(@NonNull java.net.Inet4Address);
-    field @NonNull public final java.net.Inet4Address ipv4Address;
-  }
-
-  public class IkeIpv6AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
-    ctor public IkeIpv6AddrIdentification(@NonNull java.net.Inet6Address);
-    field @NonNull public final java.net.Inet6Address ipv6Address;
-  }
-
-  public final class IkeKeyIdIdentification extends android.net.ipsec.ike.IkeIdentification {
-    ctor public IkeKeyIdIdentification(@NonNull byte[]);
-    field @NonNull public final byte[] keyId;
-  }
-
-  public final class IkeRfc822AddrIdentification extends android.net.ipsec.ike.IkeIdentification {
-    ctor public IkeRfc822AddrIdentification(@NonNull String);
-    field @NonNull public final String rfc822Name;
-  }
-
-  public final class IkeSaProposal extends android.net.ipsec.ike.SaProposal {
-    method @NonNull public java.util.List<java.lang.Integer> getPseudorandomFunctions();
-  }
-
-  public static final class IkeSaProposal.Builder {
-    ctor public IkeSaProposal.Builder();
-    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addDhGroup(int);
-    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addEncryptionAlgorithm(int, int);
-    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addIntegrityAlgorithm(int);
-    method @NonNull public android.net.ipsec.ike.IkeSaProposal.Builder addPseudorandomFunction(int);
-    method @NonNull public android.net.ipsec.ike.IkeSaProposal build();
-  }
-
-  public final class IkeSession implements java.lang.AutoCloseable {
-    ctor public IkeSession(@NonNull android.content.Context, @NonNull android.net.ipsec.ike.IkeSessionParams, @NonNull android.net.ipsec.ike.ChildSessionParams, @NonNull java.util.concurrent.Executor, @NonNull android.net.ipsec.ike.IkeSessionCallback, @NonNull android.net.ipsec.ike.ChildSessionCallback);
-    method public void close();
-    method public void closeChildSession(@NonNull android.net.ipsec.ike.ChildSessionCallback);
-    method public void kill();
-    method public void openChildSession(@NonNull android.net.ipsec.ike.ChildSessionParams, @NonNull android.net.ipsec.ike.ChildSessionCallback);
-  }
-
-  public interface IkeSessionCallback {
-    method public void onClosed();
-    method public void onClosedExceptionally(@NonNull android.net.ipsec.ike.exceptions.IkeException);
-    method public void onError(@NonNull android.net.ipsec.ike.exceptions.IkeProtocolException);
-    method public void onOpened(@NonNull android.net.ipsec.ike.IkeSessionConfiguration);
-  }
-
-  public final class IkeSessionConfiguration {
-    method @NonNull public java.util.List<java.net.InetAddress> getPcscfServers();
-    method @NonNull public String getRemoteApplicationVersion();
-    method @NonNull public java.util.List<byte[]> getRemoteVendorIDs();
-    method public boolean isIkeExtensionEnabled(int);
-    field public static final int EXTENSION_TYPE_FRAGMENTATION = 1; // 0x1
-    field public static final int EXTENSION_TYPE_MOBIKE = 2; // 0x2
-  }
-
-  public final class IkeSessionParams {
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest> getConfigurationRequests();
-    method public long getHardLifetime();
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getLocalAuthConfig();
-    method @NonNull public android.net.ipsec.ike.IkeIdentification getLocalIdentification();
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig getRemoteAuthConfig();
-    method @NonNull public android.net.ipsec.ike.IkeIdentification getRemoteIdentification();
-    method @NonNull public java.util.List<android.net.ipsec.ike.IkeSaProposal> getSaProposals();
-    method @NonNull public java.net.InetAddress getServerAddress();
-    method public long getSoftLifetime();
-    method @NonNull public android.net.IpSecManager.UdpEncapsulationSocket getUdpEncapsulationSocket();
-  }
-
-  public static final class IkeSessionParams.Builder {
-    ctor public IkeSessionParams.Builder();
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(@NonNull java.net.InetAddress);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addPcscfServerRequest(int);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.IkeSaProposal);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams build();
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.security.PrivateKey);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthDigitalSignature(@Nullable java.security.cert.X509Certificate, @NonNull java.security.cert.X509Certificate, @NonNull java.util.List<java.security.cert.X509Certificate>, @NonNull java.security.PrivateKey);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthEap(@Nullable java.security.cert.X509Certificate, @NonNull android.net.eap.EapSessionConfig);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setAuthPsk(@NonNull byte[]);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLifetime(long, long);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setLocalIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setRemoteIdentification(@NonNull android.net.ipsec.ike.IkeIdentification);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setServerAddress(@NonNull java.net.InetAddress);
-    method @NonNull public android.net.ipsec.ike.IkeSessionParams.Builder setUdpEncapsulationSocket(@NonNull android.net.IpSecManager.UdpEncapsulationSocket);
-  }
-
-  public static interface IkeSessionParams.ConfigRequestIpv4PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest {
-    method @Nullable public java.net.Inet4Address getAddress();
-  }
-
-  public static interface IkeSessionParams.ConfigRequestIpv6PcscfServer extends android.net.ipsec.ike.IkeSessionParams.IkeConfigRequest {
-    method @Nullable public java.net.Inet6Address getAddress();
-  }
-
-  public abstract static class IkeSessionParams.IkeAuthConfig {
-  }
-
-  public static class IkeSessionParams.IkeAuthDigitalSignLocalConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
-    method @NonNull public java.security.cert.X509Certificate getClientEndCertificate();
-    method @NonNull public java.util.List<java.security.cert.X509Certificate> getIntermediateCertificates();
-    method @NonNull public java.security.PrivateKey getPrivateKey();
-  }
-
-  public static class IkeSessionParams.IkeAuthDigitalSignRemoteConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
-    method @Nullable public java.security.cert.X509Certificate getRemoteCaCert();
-  }
-
-  public static class IkeSessionParams.IkeAuthEapConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
-    method @NonNull public android.net.eap.EapSessionConfig getEapConfig();
-  }
-
-  public static class IkeSessionParams.IkeAuthPskConfig extends android.net.ipsec.ike.IkeSessionParams.IkeAuthConfig {
-    method @NonNull public byte[] getPsk();
-  }
-
-  public static interface IkeSessionParams.IkeConfigRequest {
-  }
-
-  public final class IkeTrafficSelector {
-    ctor public IkeTrafficSelector(int, int, @NonNull java.net.InetAddress, @NonNull java.net.InetAddress);
-    field public final int endPort;
-    field @NonNull public final java.net.InetAddress endingAddress;
-    field public final int startPort;
-    field @NonNull public final java.net.InetAddress startingAddress;
-  }
-
-  public abstract class SaProposal {
-    method @NonNull public java.util.List<java.lang.Integer> getDhGroups();
-    method @NonNull public java.util.List<android.util.Pair<java.lang.Integer,java.lang.Integer>> getEncryptionAlgorithms();
-    method @NonNull public java.util.List<java.lang.Integer> getIntegrityAlgorithms();
-    field public static final int DH_GROUP_1024_BIT_MODP = 2; // 0x2
-    field public static final int DH_GROUP_2048_BIT_MODP = 14; // 0xe
-    field public static final int DH_GROUP_NONE = 0; // 0x0
-    field public static final int ENCRYPTION_ALGORITHM_3DES = 3; // 0x3
-    field public static final int ENCRYPTION_ALGORITHM_AES_CBC = 12; // 0xc
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 = 19; // 0x13
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 = 20; // 0x14
-    field public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 = 18; // 0x12
-    field public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 = 5; // 0x5
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 = 2; // 0x2
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 = 12; // 0xc
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 = 13; // 0xd
-    field public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 = 14; // 0xe
-    field public static final int INTEGRITY_ALGORITHM_NONE = 0; // 0x0
-    field public static final int KEY_LEN_AES_128 = 128; // 0x80
-    field public static final int KEY_LEN_AES_192 = 192; // 0xc0
-    field public static final int KEY_LEN_AES_256 = 256; // 0x100
-    field public static final int KEY_LEN_UNUSED = 0; // 0x0
-    field public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC = 4; // 0x4
-    field public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 = 2; // 0x2
-  }
-
-  public final class TransportModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
-  }
-
-  public static final class TransportModeChildSessionParams.Builder {
-    ctor public TransportModeChildSessionParams.Builder();
-    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
-    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
-    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
-    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams build();
-    method @NonNull public android.net.ipsec.ike.TransportModeChildSessionParams.Builder setLifetime(long, long);
-  }
-
-  public final class TunnelModeChildSessionParams extends android.net.ipsec.ike.ChildSessionParams {
-    method @NonNull public java.util.List<android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest> getConfigurationRequests();
-  }
-
-  public static final class TunnelModeChildSessionParams.Builder {
-    ctor public TunnelModeChildSessionParams.Builder();
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet4Address);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalAddressRequest(@NonNull java.net.Inet6Address, int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDhcpServerRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addInternalDnsServerRequest(int);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addOutboundTrafficSelectors(@NonNull android.net.ipsec.ike.IkeTrafficSelector);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder addSaProposal(@NonNull android.net.ipsec.ike.ChildSaProposal);
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams build();
-    method @NonNull public android.net.ipsec.ike.TunnelModeChildSessionParams.Builder setLifetime(long, long);
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-    method @Nullable public java.net.Inet4Address getAddress();
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DhcpServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-    method @Nullable public java.net.Inet4Address getAddress();
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-    method @Nullable public java.net.Inet4Address getAddress();
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv4Netmask extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6Address extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-    method @Nullable public java.net.Inet6Address getAddress();
-    method public int getPrefixLength();
-  }
-
-  public static interface TunnelModeChildSessionParams.ConfigRequestIpv6DnsServer extends android.net.ipsec.ike.TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-    method @Nullable public java.net.Inet6Address getAddress();
-  }
-
-  public static interface TunnelModeChildSessionParams.TunnelModeChildConfigRequest {
-  }
-
-}
-
-package android.net.ipsec.ike.exceptions {
-
-  public abstract class IkeException extends java.lang.Exception {
-  }
-
-  public final class IkeInternalException extends android.net.ipsec.ike.exceptions.IkeException {
-  }
-
-  public abstract class IkeProtocolException extends android.net.ipsec.ike.exceptions.IkeException {
-    method @Nullable public byte[] getErrorData();
-    method public int getErrorType();
-    field public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; // 0x18
-    field public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; // 0x2c
-    field public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; // 0x25
-    field public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; // 0x24
-    field public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; // 0x4
-    field public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; // 0x11
-    field public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; // 0x5
-    field public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; // 0x9
-    field public static final int ERROR_TYPE_INVALID_SELECTORS = 39; // 0x27
-    field public static final int ERROR_TYPE_INVALID_SYNTAX = 7; // 0x7
-    field public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; // 0x23
-    field public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; // 0xe
-    field public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; // 0x22
-    field public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; // 0x2b
-    field public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; // 0x26
-    field public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; // 0x1
-  }
-
-}
-
 package android.net.metrics {
 
   public final class ApfProgramEvent implements android.net.metrics.IpConnectivityLog.Event {
@@ -7534,6 +7215,7 @@
     method public int getChannel();
     method public int getMaxNumberOfClients();
     method public int getShutdownTimeoutMillis();
+    method public boolean isAutoShutdownEnabled();
     method public boolean isClientControlByUserEnabled();
     method @Nullable public android.net.wifi.WifiConfiguration toWifiConfiguration();
     field public static final int BAND_2GHZ = 1; // 0x1
@@ -7547,14 +7229,15 @@
     ctor public SoftApConfiguration.Builder(@NonNull android.net.wifi.SoftApConfiguration);
     method @NonNull public android.net.wifi.SoftApConfiguration build();
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder enableClientControlByUser(boolean);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setAutoShutdownEnabled(boolean);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBand(int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setBssid(@Nullable android.net.MacAddress);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setChannel(int, int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setClientList(@NonNull java.util.List<android.net.MacAddress>, @NonNull java.util.List<android.net.MacAddress>);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setHiddenSsid(boolean);
-    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(int);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setMaxNumberOfClients(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setPassphrase(@Nullable String, int);
-    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(int);
+    method @NonNull public android.net.wifi.SoftApConfiguration.Builder setShutdownTimeoutMillis(@IntRange(from=0) int);
     method @NonNull public android.net.wifi.SoftApConfiguration.Builder setSsid(@Nullable String);
   }
 
@@ -7748,6 +7431,7 @@
     method @RequiresPermission(android.Manifest.permission.WIFI_SET_DEVICE_MOBILITY_STATE) public void setDeviceMobilityState(int);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMacRandomizationSettingPasspointEnabled(@NonNull String, boolean);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setMeteredOverridePasspoint(@NonNull String, int);
+    method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanAlwaysAvailable(boolean);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setScanThrottleEnabled(boolean);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public boolean setSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
     method @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS) public void setVerboseLoggingEnabled(boolean);
@@ -7895,6 +7579,7 @@
 
   public final class WifiOemMigrationHook {
     method @Nullable public static android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData loadFromConfigStore();
+    method @NonNull public static android.net.wifi.WifiOemMigrationHook.SettingsMigrationData loadFromSettings(@NonNull android.content.Context);
   }
 
   public static final class WifiOemMigrationHook.ConfigStoreMigrationData implements android.os.Parcelable {
@@ -7912,6 +7597,31 @@
     method @NonNull public android.net.wifi.WifiOemMigrationHook.ConfigStoreMigrationData.Builder setUserSoftApConfiguration(@NonNull android.net.wifi.SoftApConfiguration);
   }
 
+  public static final class WifiOemMigrationHook.SettingsMigrationData implements android.os.Parcelable {
+    method public int describeContents();
+    method @Nullable public String getP2pDeviceName();
+    method public boolean isP2pFactoryResetPending();
+    method public boolean isScanAlwaysAvailable();
+    method public boolean isScanThrottleEnabled();
+    method public boolean isSoftApTimeoutEnabled();
+    method public boolean isVerboseLoggingEnabled();
+    method public boolean isWakeUpEnabled();
+    method public void writeToParcel(@NonNull android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.net.wifi.WifiOemMigrationHook.SettingsMigrationData> CREATOR;
+  }
+
+  public static final class WifiOemMigrationHook.SettingsMigrationData.Builder {
+    ctor public WifiOemMigrationHook.SettingsMigrationData.Builder();
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData build();
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setP2pDeviceName(@Nullable String);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setP2pFactoryResetPending(boolean);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setScanAlwaysAvailable(boolean);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setScanThrottleEnabled(boolean);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setSoftApTimeoutEnabled(boolean);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setVerboseLoggingEnabled(boolean);
+    method @NonNull public android.net.wifi.WifiOemMigrationHook.SettingsMigrationData.Builder setWakeUpEnabled(boolean);
+  }
+
   public class WifiScanner {
     method @Deprecated public void configureWifiChange(int, int, int, int, int, android.net.wifi.WifiScanner.BssidInfo[]);
     method @Deprecated public void configureWifiChange(android.net.wifi.WifiScanner.WifiChangeSettings);
@@ -9047,7 +8757,9 @@
 
   public class UserManager {
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public void clearSeedAccountData();
-    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @Nullable String[]) throws android.os.UserManager.UserOperationException;
+    method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}) public android.os.UserHandle createProfile(@NonNull String, @NonNull String, @NonNull java.util.Set<java.lang.String>) throws android.os.UserManager.UserOperationException;
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getAllProfiles();
+    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getEnabledProfiles();
     method @Nullable @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.UserHandle getProfileParent(@NonNull android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public String getSeedAccountName();
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public android.os.PersistableBundle getSeedAccountOptions();
@@ -9055,7 +8767,6 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public long[] getSerialNumbersOfUsers(boolean);
     method @NonNull @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserHandle> getUserHandles(boolean);
     method @Nullable @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.GET_ACCOUNTS_PRIVILEGED}) public android.graphics.Bitmap getUserIcon();
-    method @NonNull @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.CREATE_USERS}, conditional=true) public java.util.List<android.os.UserHandle> getUserProfiles(boolean);
     method @Deprecated @android.os.UserManager.UserRestrictionSource @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public int getUserRestrictionSource(String, android.os.UserHandle);
     method @RequiresPermission(android.Manifest.permission.MANAGE_USERS) public java.util.List<android.os.UserManager.EnforcingUser> getUserRestrictionSources(String, android.os.UserHandle);
     method @RequiresPermission(allOf={android.Manifest.permission.READ_PHONE_STATE, android.Manifest.permission.MANAGE_USERS, android.Manifest.permission.INTERACT_ACROSS_USERS}, conditional=true) public int getUserSwitchability();
@@ -9718,18 +9429,11 @@
     field public static final String INSTALL_CARRIER_APP_NOTIFICATION_SLEEP_MILLIS = "install_carrier_app_notification_sleep_millis";
     field public static final String OTA_DISABLE_AUTOMATIC_UPDATE = "ota_disable_automatic_update";
     field public static final String REQUIRE_PASSWORD_TO_DECRYPT = "require_password_to_decrypt";
-    field public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
     field public static final String TETHER_OFFLOAD_DISABLED = "tether_offload_disabled";
     field public static final String TETHER_SUPPORTED = "tether_supported";
     field public static final String THEATER_MODE_ON = "theater_mode_on";
     field public static final String WEBVIEW_MULTIPROCESS = "webview_multiprocess";
     field public static final String WIFI_BADGING_THRESHOLDS = "wifi_badging_thresholds";
-    field public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
-    field public static final String WIFI_P2P_PENDING_FACTORY_RESET = "wifi_p2p_pending_factory_reset";
-    field public static final String WIFI_SCAN_ALWAYS_AVAILABLE = "wifi_scan_always_enabled";
-    field public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled";
-    field public static final String WIFI_SCORE_PARAMS = "wifi_score_params";
-    field public static final String WIFI_VERBOSE_LOGGING_ENABLED = "wifi_verbose_logging_enabled";
     field @Deprecated public static final String WIFI_WAKEUP_ENABLED = "wifi_wakeup_enabled";
   }
 
@@ -9744,6 +9448,7 @@
     field public static final String AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE = "autofill_user_data_max_user_data_size";
     field public static final String AUTOFILL_USER_DATA_MAX_VALUE_LENGTH = "autofill_user_data_max_value_length";
     field public static final String AUTOFILL_USER_DATA_MIN_VALUE_LENGTH = "autofill_user_data_min_value_length";
+    field public static final String AUTO_REVOKE_DISABLED = "auto_revoke_disabled";
     field public static final String CARRIER_APPS_HANDLED = "carrier_apps_handled";
     field public static final String COMPLETED_CATEGORY_PREFIX = "suggested.completed_category.";
     field public static final String DOZE_ALWAYS_ON = "doze_always_on";
@@ -10187,6 +9892,7 @@
   public abstract class InlineSuggestionRenderService extends android.app.Service {
     ctor public InlineSuggestionRenderService();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @Nullable public android.os.Bundle onGetInlineSuggestionsRendererInfo();
     method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
     field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
   }
@@ -11364,347 +11070,7 @@
   }
 
   public final class DataFailCause {
-    field public static final int ACCESS_ATTEMPT_ALREADY_IN_PROGRESS = 2219; // 0x8ab
-    field public static final int ACCESS_BLOCK = 2087; // 0x827
-    field public static final int ACCESS_BLOCK_ALL = 2088; // 0x828
-    field public static final int ACCESS_CLASS_DSAC_REJECTION = 2108; // 0x83c
-    field public static final int ACCESS_CONTROL_LIST_CHECK_FAILURE = 2128; // 0x850
-    field public static final int ACTIVATION_REJECTED_BCM_VIOLATION = 48; // 0x30
-    field public static final int ACTIVATION_REJECT_GGSN = 30; // 0x1e
-    field public static final int ACTIVATION_REJECT_UNSPECIFIED = 31; // 0x1f
-    field public static final int ACTIVE_PDP_CONTEXT_MAX_NUMBER_REACHED = 65; // 0x41
-    field public static final int APN_DISABLED = 2045; // 0x7fd
-    field public static final int APN_DISALLOWED_ON_ROAMING = 2059; // 0x80b
-    field public static final int APN_MISMATCH = 2054; // 0x806
-    field public static final int APN_PARAMETERS_CHANGED = 2060; // 0x80c
-    field public static final int APN_PENDING_HANDOVER = 2041; // 0x7f9
-    field public static final int APN_TYPE_CONFLICT = 112; // 0x70
-    field public static final int AUTH_FAILURE_ON_EMERGENCY_CALL = 122; // 0x7a
-    field public static final int BEARER_HANDLING_NOT_SUPPORTED = 60; // 0x3c
-    field public static final int CALL_DISALLOWED_IN_ROAMING = 2068; // 0x814
-    field public static final int CALL_PREEMPT_BY_EMERGENCY_APN = 127; // 0x7f
-    field public static final int CANNOT_ENCODE_OTA_MESSAGE = 2159; // 0x86f
-    field public static final int CDMA_ALERT_STOP = 2077; // 0x81d
-    field public static final int CDMA_INCOMING_CALL = 2076; // 0x81c
-    field public static final int CDMA_INTERCEPT = 2073; // 0x819
-    field public static final int CDMA_LOCK = 2072; // 0x818
-    field public static final int CDMA_RELEASE_DUE_TO_SO_REJECTION = 2075; // 0x81b
-    field public static final int CDMA_REORDER = 2074; // 0x81a
-    field public static final int CDMA_RETRY_ORDER = 2086; // 0x826
-    field public static final int CHANNEL_ACQUISITION_FAILURE = 2078; // 0x81e
-    field public static final int CLOSE_IN_PROGRESS = 2030; // 0x7ee
-    field public static final int COLLISION_WITH_NETWORK_INITIATED_REQUEST = 56; // 0x38
-    field public static final int COMPANION_IFACE_IN_USE = 118; // 0x76
-    field public static final int CONCURRENT_SERVICES_INCOMPATIBLE = 2083; // 0x823
-    field public static final int CONCURRENT_SERVICES_NOT_ALLOWED = 2091; // 0x82b
-    field public static final int CONCURRENT_SERVICE_NOT_SUPPORTED_BY_BASE_STATION = 2080; // 0x820
-    field public static final int CONDITIONAL_IE_ERROR = 100; // 0x64
-    field public static final int CONGESTION = 2106; // 0x83a
-    field public static final int CONNECTION_RELEASED = 2113; // 0x841
-    field public static final int CS_DOMAIN_NOT_AVAILABLE = 2181; // 0x885
-    field public static final int CS_FALLBACK_CALL_ESTABLISHMENT_NOT_ALLOWED = 2188; // 0x88c
-    field public static final int DATA_PLAN_EXPIRED = 2198; // 0x896
-    field public static final int DATA_ROAMING_SETTINGS_DISABLED = 2064; // 0x810
-    field public static final int DATA_SETTINGS_DISABLED = 2063; // 0x80f
-    field public static final int DBM_OR_SMS_IN_PROGRESS = 2211; // 0x8a3
-    field public static final int DDS_SWITCHED = 2065; // 0x811
-    field public static final int DDS_SWITCH_IN_PROGRESS = 2067; // 0x813
-    field public static final int DRB_RELEASED_BY_RRC = 2112; // 0x840
-    field public static final int DS_EXPLICIT_DEACTIVATION = 2125; // 0x84d
-    field public static final int DUAL_SWITCH = 2227; // 0x8b3
-    field public static final int DUN_CALL_DISALLOWED = 2056; // 0x808
-    field public static final int DUPLICATE_BEARER_ID = 2118; // 0x846
-    field public static final int EHRPD_TO_HRPD_FALLBACK = 2049; // 0x801
-    field public static final int EMBMS_NOT_ENABLED = 2193; // 0x891
-    field public static final int EMBMS_REGULAR_DEACTIVATION = 2195; // 0x893
-    field public static final int EMERGENCY_IFACE_ONLY = 116; // 0x74
-    field public static final int EMERGENCY_MODE = 2221; // 0x8ad
-    field public static final int EMM_ACCESS_BARRED = 115; // 0x73
-    field public static final int EMM_ACCESS_BARRED_INFINITE_RETRY = 121; // 0x79
-    field public static final int EMM_ATTACH_FAILED = 2115; // 0x843
-    field public static final int EMM_ATTACH_STARTED = 2116; // 0x844
-    field public static final int EMM_DETACHED = 2114; // 0x842
-    field public static final int EMM_T3417_EXPIRED = 2130; // 0x852
-    field public static final int EMM_T3417_EXT_EXPIRED = 2131; // 0x853
-    field public static final int EPS_SERVICES_AND_NON_EPS_SERVICES_NOT_ALLOWED = 2178; // 0x882
-    field public static final int EPS_SERVICES_NOT_ALLOWED_IN_PLMN = 2179; // 0x883
-    field public static final int ERROR_UNSPECIFIED = 65535; // 0xffff
-    field public static final int ESM_BAD_OTA_MESSAGE = 2122; // 0x84a
-    field public static final int ESM_BEARER_DEACTIVATED_TO_SYNC_WITH_NETWORK = 2120; // 0x848
-    field public static final int ESM_COLLISION_SCENARIOS = 2119; // 0x847
-    field public static final int ESM_CONTEXT_TRANSFERRED_DUE_TO_IRAT = 2124; // 0x84c
-    field public static final int ESM_DOWNLOAD_SERVER_REJECTED_THE_CALL = 2123; // 0x84b
-    field public static final int ESM_FAILURE = 2182; // 0x886
-    field public static final int ESM_INFO_NOT_RECEIVED = 53; // 0x35
-    field public static final int ESM_LOCAL_CAUSE_NONE = 2126; // 0x84e
-    field public static final int ESM_NW_ACTIVATED_DED_BEARER_WITH_ID_OF_DEF_BEARER = 2121; // 0x849
-    field public static final int ESM_PROCEDURE_TIME_OUT = 2155; // 0x86b
-    field public static final int ESM_UNKNOWN_EPS_BEARER_CONTEXT = 2111; // 0x83f
-    field public static final int EVDO_CONNECTION_DENY_BY_BILLING_OR_AUTHENTICATION_FAILURE = 2201; // 0x899
-    field public static final int EVDO_CONNECTION_DENY_BY_GENERAL_OR_NETWORK_BUSY = 2200; // 0x898
-    field public static final int EVDO_HDR_CHANGED = 2202; // 0x89a
-    field public static final int EVDO_HDR_CONNECTION_SETUP_TIMEOUT = 2206; // 0x89e
-    field public static final int EVDO_HDR_EXITED = 2203; // 0x89b
-    field public static final int EVDO_HDR_NO_SESSION = 2204; // 0x89c
-    field public static final int EVDO_USING_GPS_FIX_INSTEAD_OF_HDR_CALL = 2205; // 0x89d
-    field public static final int FADE = 2217; // 0x8a9
-    field public static final int FAILED_TO_ACQUIRE_COLOCATED_HDR = 2207; // 0x89f
-    field public static final int FEATURE_NOT_SUPP = 40; // 0x28
-    field public static final int FILTER_SEMANTIC_ERROR = 44; // 0x2c
-    field public static final int FILTER_SYTAX_ERROR = 45; // 0x2d
-    field public static final int FORBIDDEN_APN_NAME = 2066; // 0x812
-    field public static final int GPRS_REGISTRATION_FAIL = -2; // 0xfffffffe
-    field public static final int GPRS_SERVICES_AND_NON_GPRS_SERVICES_NOT_ALLOWED = 2097; // 0x831
-    field public static final int GPRS_SERVICES_NOT_ALLOWED = 2098; // 0x832
-    field public static final int GPRS_SERVICES_NOT_ALLOWED_IN_THIS_PLMN = 2103; // 0x837
-    field public static final int HANDOFF_PREFERENCE_CHANGED = 2251; // 0x8cb
-    field public static final int HDR_ACCESS_FAILURE = 2213; // 0x8a5
-    field public static final int HDR_FADE = 2212; // 0x8a4
-    field public static final int HDR_NO_LOCK_GRANTED = 2210; // 0x8a2
-    field public static final int IFACE_AND_POL_FAMILY_MISMATCH = 120; // 0x78
-    field public static final int IFACE_MISMATCH = 117; // 0x75
-    field public static final int ILLEGAL_ME = 2096; // 0x830
-    field public static final int ILLEGAL_MS = 2095; // 0x82f
-    field public static final int IMEI_NOT_ACCEPTED = 2177; // 0x881
-    field public static final int IMPLICITLY_DETACHED = 2100; // 0x834
-    field public static final int IMSI_UNKNOWN_IN_HOME_SUBSCRIBER_SERVER = 2176; // 0x880
-    field public static final int INCOMING_CALL_REJECTED = 2092; // 0x82c
-    field public static final int INSUFFICIENT_RESOURCES = 26; // 0x1a
-    field public static final int INTERFACE_IN_USE = 2058; // 0x80a
-    field public static final int INTERNAL_CALL_PREEMPT_BY_HIGH_PRIO_APN = 114; // 0x72
-    field public static final int INTERNAL_EPC_NONEPC_TRANSITION = 2057; // 0x809
-    field public static final int INVALID_CONNECTION_ID = 2156; // 0x86c
-    field public static final int INVALID_DNS_ADDR = 123; // 0x7b
-    field public static final int INVALID_EMM_STATE = 2190; // 0x88e
-    field public static final int INVALID_MANDATORY_INFO = 96; // 0x60
-    field public static final int INVALID_MODE = 2223; // 0x8af
-    field public static final int INVALID_PCSCF_ADDR = 113; // 0x71
-    field public static final int INVALID_PCSCF_OR_DNS_ADDRESS = 124; // 0x7c
-    field public static final int INVALID_PRIMARY_NSAPI = 2158; // 0x86e
-    field public static final int INVALID_SIM_STATE = 2224; // 0x8b0
-    field public static final int INVALID_TRANSACTION_ID = 81; // 0x51
-    field public static final int IPV6_ADDRESS_TRANSFER_FAILED = 2047; // 0x7ff
-    field public static final int IPV6_PREFIX_UNAVAILABLE = 2250; // 0x8ca
-    field public static final int IP_ADDRESS_MISMATCH = 119; // 0x77
-    field public static final int IP_VERSION_MISMATCH = 2055; // 0x807
-    field public static final int IRAT_HANDOVER_FAILED = 2194; // 0x892
-    field public static final int IS707B_MAX_ACCESS_PROBES = 2089; // 0x829
-    field public static final int LIMITED_TO_IPV4 = 2234; // 0x8ba
-    field public static final int LIMITED_TO_IPV6 = 2235; // 0x8bb
-    field public static final int LLC_SNDCP = 25; // 0x19
-    field public static final int LOCAL_END = 2215; // 0x8a7
-    field public static final int LOCATION_AREA_NOT_ALLOWED = 2102; // 0x836
-    field public static final int LOST_CONNECTION = 65540; // 0x10004
-    field public static final int LOWER_LAYER_REGISTRATION_FAILURE = 2197; // 0x895
-    field public static final int LOW_POWER_MODE_OR_POWERING_DOWN = 2044; // 0x7fc
-    field public static final int LTE_NAS_SERVICE_REQUEST_FAILED = 2117; // 0x845
-    field public static final int LTE_THROTTLING_NOT_REQUIRED = 2127; // 0x84f
-    field public static final int MAC_FAILURE = 2183; // 0x887
-    field public static final int MAXIMIUM_NSAPIS_EXCEEDED = 2157; // 0x86d
-    field public static final int MAXINUM_SIZE_OF_L2_MESSAGE_EXCEEDED = 2166; // 0x876
-    field public static final int MAX_ACCESS_PROBE = 2079; // 0x81f
-    field public static final int MAX_IPV4_CONNECTIONS = 2052; // 0x804
-    field public static final int MAX_IPV6_CONNECTIONS = 2053; // 0x805
-    field public static final int MAX_PPP_INACTIVITY_TIMER_EXPIRED = 2046; // 0x7fe
-    field public static final int MESSAGE_INCORRECT_SEMANTIC = 95; // 0x5f
-    field public static final int MESSAGE_TYPE_UNSUPPORTED = 97; // 0x61
-    field public static final int MIP_CONFIG_FAILURE = 2050; // 0x802
-    field public static final int MIP_FA_ADMIN_PROHIBITED = 2001; // 0x7d1
-    field public static final int MIP_FA_DELIVERY_STYLE_NOT_SUPPORTED = 2012; // 0x7dc
-    field public static final int MIP_FA_ENCAPSULATION_UNAVAILABLE = 2008; // 0x7d8
-    field public static final int MIP_FA_HOME_AGENT_AUTHENTICATION_FAILURE = 2004; // 0x7d4
-    field public static final int MIP_FA_INSUFFICIENT_RESOURCES = 2002; // 0x7d2
-    field public static final int MIP_FA_MALFORMED_REPLY = 2007; // 0x7d7
-    field public static final int MIP_FA_MALFORMED_REQUEST = 2006; // 0x7d6
-    field public static final int MIP_FA_MISSING_CHALLENGE = 2017; // 0x7e1
-    field public static final int MIP_FA_MISSING_HOME_ADDRESS = 2015; // 0x7df
-    field public static final int MIP_FA_MISSING_HOME_AGENT = 2014; // 0x7de
-    field public static final int MIP_FA_MISSING_NAI = 2013; // 0x7dd
-    field public static final int MIP_FA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2003; // 0x7d3
-    field public static final int MIP_FA_REASON_UNSPECIFIED = 2000; // 0x7d0
-    field public static final int MIP_FA_REQUESTED_LIFETIME_TOO_LONG = 2005; // 0x7d5
-    field public static final int MIP_FA_REVERSE_TUNNEL_IS_MANDATORY = 2011; // 0x7db
-    field public static final int MIP_FA_REVERSE_TUNNEL_UNAVAILABLE = 2010; // 0x7da
-    field public static final int MIP_FA_STALE_CHALLENGE = 2018; // 0x7e2
-    field public static final int MIP_FA_UNKNOWN_CHALLENGE = 2016; // 0x7e0
-    field public static final int MIP_FA_VJ_HEADER_COMPRESSION_UNAVAILABLE = 2009; // 0x7d9
-    field public static final int MIP_HA_ADMIN_PROHIBITED = 2020; // 0x7e4
-    field public static final int MIP_HA_ENCAPSULATION_UNAVAILABLE = 2029; // 0x7ed
-    field public static final int MIP_HA_FOREIGN_AGENT_AUTHENTICATION_FAILURE = 2023; // 0x7e7
-    field public static final int MIP_HA_INSUFFICIENT_RESOURCES = 2021; // 0x7e5
-    field public static final int MIP_HA_MALFORMED_REQUEST = 2025; // 0x7e9
-    field public static final int MIP_HA_MOBILE_NODE_AUTHENTICATION_FAILURE = 2022; // 0x7e6
-    field public static final int MIP_HA_REASON_UNSPECIFIED = 2019; // 0x7e3
-    field public static final int MIP_HA_REGISTRATION_ID_MISMATCH = 2024; // 0x7e8
-    field public static final int MIP_HA_REVERSE_TUNNEL_IS_MANDATORY = 2028; // 0x7ec
-    field public static final int MIP_HA_REVERSE_TUNNEL_UNAVAILABLE = 2027; // 0x7eb
-    field public static final int MIP_HA_UNKNOWN_HOME_AGENT_ADDRESS = 2026; // 0x7ea
-    field public static final int MISSING_UNKNOWN_APN = 27; // 0x1b
-    field public static final int MODEM_APP_PREEMPTED = 2032; // 0x7f0
-    field public static final int MODEM_RESTART = 2037; // 0x7f5
-    field public static final int MSC_TEMPORARILY_NOT_REACHABLE = 2180; // 0x884
-    field public static final int MSG_AND_PROTOCOL_STATE_UNCOMPATIBLE = 101; // 0x65
-    field public static final int MSG_TYPE_NONCOMPATIBLE_STATE = 98; // 0x62
-    field public static final int MS_IDENTITY_CANNOT_BE_DERIVED_BY_THE_NETWORK = 2099; // 0x833
-    field public static final int MULTIPLE_PDP_CALL_NOT_ALLOWED = 2192; // 0x890
-    field public static final int MULTI_CONN_TO_SAME_PDN_NOT_ALLOWED = 55; // 0x37
-    field public static final int NAS_LAYER_FAILURE = 2191; // 0x88f
-    field public static final int NAS_REQUEST_REJECTED_BY_NETWORK = 2167; // 0x877
-    field public static final int NAS_SIGNALLING = 14; // 0xe
-    field public static final int NETWORK_FAILURE = 38; // 0x26
-    field public static final int NETWORK_INITIATED_DETACH_NO_AUTO_REATTACH = 2154; // 0x86a
-    field public static final int NETWORK_INITIATED_DETACH_WITH_AUTO_REATTACH = 2153; // 0x869
-    field public static final int NETWORK_INITIATED_TERMINATION = 2031; // 0x7ef
-    field public static final int NONE = 0; // 0x0
-    field public static final int NON_IP_NOT_SUPPORTED = 2069; // 0x815
-    field public static final int NORMAL_RELEASE = 2218; // 0x8aa
-    field public static final int NO_CDMA_SERVICE = 2084; // 0x824
-    field public static final int NO_COLLOCATED_HDR = 2225; // 0x8b1
-    field public static final int NO_EPS_BEARER_CONTEXT_ACTIVATED = 2189; // 0x88d
-    field public static final int NO_GPRS_CONTEXT = 2094; // 0x82e
-    field public static final int NO_HYBRID_HDR_SERVICE = 2209; // 0x8a1
-    field public static final int NO_PDP_CONTEXT_ACTIVATED = 2107; // 0x83b
-    field public static final int NO_RESPONSE_FROM_BASE_STATION = 2081; // 0x821
-    field public static final int NO_SERVICE = 2216; // 0x8a8
-    field public static final int NO_SERVICE_ON_GATEWAY = 2093; // 0x82d
-    field public static final int NSAPI_IN_USE = 35; // 0x23
-    field public static final int NULL_APN_DISALLOWED = 2061; // 0x80d
-    field public static final int OEM_DCFAILCAUSE_1 = 4097; // 0x1001
-    field public static final int OEM_DCFAILCAUSE_10 = 4106; // 0x100a
-    field public static final int OEM_DCFAILCAUSE_11 = 4107; // 0x100b
-    field public static final int OEM_DCFAILCAUSE_12 = 4108; // 0x100c
-    field public static final int OEM_DCFAILCAUSE_13 = 4109; // 0x100d
-    field public static final int OEM_DCFAILCAUSE_14 = 4110; // 0x100e
-    field public static final int OEM_DCFAILCAUSE_15 = 4111; // 0x100f
-    field public static final int OEM_DCFAILCAUSE_2 = 4098; // 0x1002
-    field public static final int OEM_DCFAILCAUSE_3 = 4099; // 0x1003
-    field public static final int OEM_DCFAILCAUSE_4 = 4100; // 0x1004
-    field public static final int OEM_DCFAILCAUSE_5 = 4101; // 0x1005
-    field public static final int OEM_DCFAILCAUSE_6 = 4102; // 0x1006
-    field public static final int OEM_DCFAILCAUSE_7 = 4103; // 0x1007
-    field public static final int OEM_DCFAILCAUSE_8 = 4104; // 0x1008
-    field public static final int OEM_DCFAILCAUSE_9 = 4105; // 0x1009
-    field public static final int ONLY_IPV4V6_ALLOWED = 57; // 0x39
-    field public static final int ONLY_IPV4_ALLOWED = 50; // 0x32
-    field public static final int ONLY_IPV6_ALLOWED = 51; // 0x33
-    field public static final int ONLY_NON_IP_ALLOWED = 58; // 0x3a
-    field public static final int ONLY_SINGLE_BEARER_ALLOWED = 52; // 0x34
-    field public static final int OPERATOR_BARRED = 8; // 0x8
-    field public static final int OTASP_COMMIT_IN_PROGRESS = 2208; // 0x8a0
-    field public static final int PDN_CONN_DOES_NOT_EXIST = 54; // 0x36
-    field public static final int PDN_INACTIVITY_TIMER_EXPIRED = 2051; // 0x803
-    field public static final int PDN_IPV4_CALL_DISALLOWED = 2033; // 0x7f1
-    field public static final int PDN_IPV4_CALL_THROTTLED = 2034; // 0x7f2
-    field public static final int PDN_IPV6_CALL_DISALLOWED = 2035; // 0x7f3
-    field public static final int PDN_IPV6_CALL_THROTTLED = 2036; // 0x7f4
-    field public static final int PDN_NON_IP_CALL_DISALLOWED = 2071; // 0x817
-    field public static final int PDN_NON_IP_CALL_THROTTLED = 2070; // 0x816
-    field public static final int PDP_ACTIVATE_MAX_RETRY_FAILED = 2109; // 0x83d
-    field public static final int PDP_DUPLICATE = 2104; // 0x838
-    field public static final int PDP_ESTABLISH_TIMEOUT_EXPIRED = 2161; // 0x871
-    field public static final int PDP_INACTIVE_TIMEOUT_EXPIRED = 2163; // 0x873
-    field public static final int PDP_LOWERLAYER_ERROR = 2164; // 0x874
-    field public static final int PDP_MODIFY_COLLISION = 2165; // 0x875
-    field public static final int PDP_MODIFY_TIMEOUT_EXPIRED = 2162; // 0x872
-    field public static final int PDP_PPP_NOT_SUPPORTED = 2038; // 0x7f6
-    field public static final int PDP_WITHOUT_ACTIVE_TFT = 46; // 0x2e
-    field public static final int PHONE_IN_USE = 2222; // 0x8ae
-    field public static final int PHYSICAL_LINK_CLOSE_IN_PROGRESS = 2040; // 0x7f8
-    field public static final int PLMN_NOT_ALLOWED = 2101; // 0x835
-    field public static final int PPP_AUTH_FAILURE = 2229; // 0x8b5
-    field public static final int PPP_CHAP_FAILURE = 2232; // 0x8b8
-    field public static final int PPP_CLOSE_IN_PROGRESS = 2233; // 0x8b9
-    field public static final int PPP_OPTION_MISMATCH = 2230; // 0x8b6
-    field public static final int PPP_PAP_FAILURE = 2231; // 0x8b7
-    field public static final int PPP_TIMEOUT = 2228; // 0x8b4
-    field public static final int PREF_RADIO_TECH_CHANGED = -4; // 0xfffffffc
-    field public static final int PROFILE_BEARER_INCOMPATIBLE = 2042; // 0x7fa
-    field public static final int PROTOCOL_ERRORS = 111; // 0x6f
-    field public static final int QOS_NOT_ACCEPTED = 37; // 0x25
-    field public static final int RADIO_ACCESS_BEARER_FAILURE = 2110; // 0x83e
-    field public static final int RADIO_ACCESS_BEARER_SETUP_FAILURE = 2160; // 0x870
-    field public static final int RADIO_NOT_AVAILABLE = 65537; // 0x10001
-    field public static final int RADIO_POWER_OFF = -5; // 0xfffffffb
-    field public static final int REDIRECTION_OR_HANDOFF_IN_PROGRESS = 2220; // 0x8ac
-    field public static final int REGISTRATION_FAIL = -1; // 0xffffffff
-    field public static final int REGULAR_DEACTIVATION = 36; // 0x24
-    field public static final int REJECTED_BY_BASE_STATION = 2082; // 0x822
-    field public static final int RRC_CONNECTION_ABORTED_AFTER_HANDOVER = 2173; // 0x87d
-    field public static final int RRC_CONNECTION_ABORTED_AFTER_IRAT_CELL_CHANGE = 2174; // 0x87e
-    field public static final int RRC_CONNECTION_ABORTED_DUE_TO_IRAT_CHANGE = 2171; // 0x87b
-    field public static final int RRC_CONNECTION_ABORTED_DURING_IRAT_CELL_CHANGE = 2175; // 0x87f
-    field public static final int RRC_CONNECTION_ABORT_REQUEST = 2151; // 0x867
-    field public static final int RRC_CONNECTION_ACCESS_BARRED = 2139; // 0x85b
-    field public static final int RRC_CONNECTION_ACCESS_STRATUM_FAILURE = 2137; // 0x859
-    field public static final int RRC_CONNECTION_ANOTHER_PROCEDURE_IN_PROGRESS = 2138; // 0x85a
-    field public static final int RRC_CONNECTION_CELL_NOT_CAMPED = 2144; // 0x860
-    field public static final int RRC_CONNECTION_CELL_RESELECTION = 2140; // 0x85c
-    field public static final int RRC_CONNECTION_CONFIG_FAILURE = 2141; // 0x85d
-    field public static final int RRC_CONNECTION_INVALID_REQUEST = 2168; // 0x878
-    field public static final int RRC_CONNECTION_LINK_FAILURE = 2143; // 0x85f
-    field public static final int RRC_CONNECTION_NORMAL_RELEASE = 2147; // 0x863
-    field public static final int RRC_CONNECTION_OUT_OF_SERVICE_DURING_CELL_REGISTER = 2150; // 0x866
-    field public static final int RRC_CONNECTION_RADIO_LINK_FAILURE = 2148; // 0x864
-    field public static final int RRC_CONNECTION_REESTABLISHMENT_FAILURE = 2149; // 0x865
-    field public static final int RRC_CONNECTION_REJECT_BY_NETWORK = 2146; // 0x862
-    field public static final int RRC_CONNECTION_RELEASED_SECURITY_NOT_ACTIVE = 2172; // 0x87c
-    field public static final int RRC_CONNECTION_RF_UNAVAILABLE = 2170; // 0x87a
-    field public static final int RRC_CONNECTION_SYSTEM_INFORMATION_BLOCK_READ_ERROR = 2152; // 0x868
-    field public static final int RRC_CONNECTION_SYSTEM_INTERVAL_FAILURE = 2145; // 0x861
-    field public static final int RRC_CONNECTION_TIMER_EXPIRED = 2142; // 0x85e
-    field public static final int RRC_CONNECTION_TRACKING_AREA_ID_CHANGED = 2169; // 0x879
-    field public static final int RRC_UPLINK_CONNECTION_RELEASE = 2134; // 0x856
-    field public static final int RRC_UPLINK_DATA_TRANSMISSION_FAILURE = 2132; // 0x854
-    field public static final int RRC_UPLINK_DELIVERY_FAILED_DUE_TO_HANDOVER = 2133; // 0x855
-    field public static final int RRC_UPLINK_ERROR_REQUEST_FROM_NAS = 2136; // 0x858
-    field public static final int RRC_UPLINK_RADIO_LINK_FAILURE = 2135; // 0x857
-    field public static final int RUIM_NOT_PRESENT = 2085; // 0x825
-    field public static final int SECURITY_MODE_REJECTED = 2186; // 0x88a
-    field public static final int SERVICE_NOT_ALLOWED_ON_PLMN = 2129; // 0x851
-    field public static final int SERVICE_OPTION_NOT_SUBSCRIBED = 33; // 0x21
-    field public static final int SERVICE_OPTION_NOT_SUPPORTED = 32; // 0x20
-    field public static final int SERVICE_OPTION_OUT_OF_ORDER = 34; // 0x22
-    field public static final int SIGNAL_LOST = -3; // 0xfffffffd
-    field public static final int SIM_CARD_CHANGED = 2043; // 0x7fb
-    field public static final int SYNCHRONIZATION_FAILURE = 2184; // 0x888
-    field public static final int TEST_LOOPBACK_REGULAR_DEACTIVATION = 2196; // 0x894
-    field public static final int TETHERED_CALL_ACTIVE = -6; // 0xfffffffa
-    field public static final int TFT_SEMANTIC_ERROR = 41; // 0x29
-    field public static final int TFT_SYTAX_ERROR = 42; // 0x2a
-    field public static final int THERMAL_EMERGENCY = 2090; // 0x82a
-    field public static final int THERMAL_MITIGATION = 2062; // 0x80e
-    field public static final int TRAT_SWAP_FAILED = 2048; // 0x800
-    field public static final int UE_INITIATED_DETACH_OR_DISCONNECT = 128; // 0x80
-    field public static final int UE_IS_ENTERING_POWERSAVE_MODE = 2226; // 0x8b2
-    field public static final int UE_RAT_CHANGE = 2105; // 0x839
-    field public static final int UE_SECURITY_CAPABILITIES_MISMATCH = 2185; // 0x889
-    field public static final int UMTS_HANDOVER_TO_IWLAN = 2199; // 0x897
-    field public static final int UMTS_REACTIVATION_REQ = 39; // 0x27
-    field public static final int UNACCEPTABLE_NETWORK_PARAMETER = 65538; // 0x10002
-    field public static final int UNACCEPTABLE_NON_EPS_AUTHENTICATION = 2187; // 0x88b
-    field public static final int UNKNOWN = 65536; // 0x10000
-    field public static final int UNKNOWN_INFO_ELEMENT = 99; // 0x63
-    field public static final int UNKNOWN_PDP_ADDRESS_TYPE = 28; // 0x1c
-    field public static final int UNKNOWN_PDP_CONTEXT = 43; // 0x2b
-    field public static final int UNPREFERRED_RAT = 2039; // 0x7f7
-    field public static final int UNSUPPORTED_1X_PREV = 2214; // 0x8a6
-    field public static final int UNSUPPORTED_APN_IN_CURRENT_PLMN = 66; // 0x42
-    field public static final int UNSUPPORTED_QCI_VALUE = 59; // 0x3b
-    field public static final int USER_AUTHENTICATION = 29; // 0x1d
-    field public static final int VSNCP_ADMINISTRATIVELY_PROHIBITED = 2245; // 0x8c5
-    field public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be
-    field public static final int VSNCP_GEN_ERROR = 2237; // 0x8bd
-    field public static final int VSNCP_INSUFFICIENT_PARAMETERS = 2243; // 0x8c3
-    field public static final int VSNCP_NO_PDN_GATEWAY_ADDRESS = 2240; // 0x8c0
-    field public static final int VSNCP_PDN_EXISTS_FOR_THIS_APN = 2248; // 0x8c8
-    field public static final int VSNCP_PDN_GATEWAY_REJECT = 2242; // 0x8c2
-    field public static final int VSNCP_PDN_GATEWAY_UNREACHABLE = 2241; // 0x8c1
-    field public static final int VSNCP_PDN_ID_IN_USE = 2246; // 0x8c6
-    field public static final int VSNCP_PDN_LIMIT_EXCEEDED = 2239; // 0x8bf
-    field public static final int VSNCP_RECONNECT_NOT_ALLOWED = 2249; // 0x8c9
-    field public static final int VSNCP_RESOURCE_UNAVAILABLE = 2244; // 0x8c4
-    field public static final int VSNCP_SUBSCRIBER_LIMITATION = 2247; // 0x8c7
-    field public static final int VSNCP_TIMEOUT = 2236; // 0x8bc
+    field @Deprecated public static final int VSNCP_APN_UNATHORIZED = 2238; // 0x8be
   }
 
   public final class DataSpecificRegistrationInfo implements android.os.Parcelable {
diff --git a/api/test-current.txt b/api/test-current.txt
index 79d29f6..9e37a3c 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -180,8 +180,8 @@
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void resetHistoryParameters();
     method @RequiresPermission("android.permission.MANAGE_APPOPS") public void setHistoryParameters(int, long, int);
     method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(int, int, String, int);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(String, int, String, int);
-    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(String, int, int);
+    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setMode(@NonNull String, int, @Nullable String, int);
+    method @RequiresPermission("android.permission.MANAGE_APP_OPS_MODES") public void setUidMode(@NonNull String, int, int);
     method public static int strOpToOp(@NonNull String);
     field public static final int HISTORICAL_MODE_DISABLED = 0; // 0x0
     field public static final int HISTORICAL_MODE_ENABLED_ACTIVE = 1; // 0x1
@@ -846,6 +846,11 @@
     method @NonNull public static android.content.integrity.IntegrityFormula packageNameEquals(@NonNull String);
   }
 
+  public static final class IntegrityFormula.SourceStamp {
+    method @NonNull public static android.content.integrity.IntegrityFormula notTrusted();
+    method @NonNull public static android.content.integrity.IntegrityFormula stampCertificateHashEquals(@NonNull String);
+  }
+
   public final class Rule implements android.os.Parcelable {
     ctor public Rule(@NonNull android.content.integrity.IntegrityFormula, int);
     method public int describeContents();
@@ -1473,6 +1478,10 @@
     method @NonNull public String getOriginalId();
   }
 
+  public class MediaRouter2.RoutingController {
+    method @NonNull public String getOriginalId();
+  }
+
   public final class PlaybackParams implements android.os.Parcelable {
     method public int getAudioStretchMode();
     method public android.media.PlaybackParams setAudioStretchMode(int);
@@ -2529,6 +2538,11 @@
     method public void log(android.os.StrictMode.ViolationInfo);
   }
 
+  public static final class StrictMode.VmPolicy.Builder {
+    method @NonNull public android.os.StrictMode.VmPolicy.Builder detectIncorrectContextUse();
+    method @NonNull public android.os.StrictMode.VmPolicy.Builder permitIncorrectContextUse();
+  }
+
   public class SystemConfigManager {
     method @NonNull @RequiresPermission("android.permission.READ_CARRIER_APP_INFO") public java.util.Set<java.lang.String> getDisabledUntilUsedPreinstalledCarrierApps();
     method @NonNull @RequiresPermission("android.permission.READ_CARRIER_APP_INFO") public java.util.Map<java.lang.String,java.util.List<java.lang.String>> getDisabledUntilUsedPreinstalledCarrierAssociatedApps();
@@ -3145,6 +3159,7 @@
   public abstract class InlineSuggestionRenderService extends android.app.Service {
     ctor public InlineSuggestionRenderService();
     method @Nullable public final android.os.IBinder onBind(@NonNull android.content.Intent);
+    method @Nullable public android.os.Bundle onGetInlineSuggestionsRendererInfo();
     method @Nullable public android.view.View onRenderSuggestion(@NonNull android.service.autofill.InlinePresentation, int, int);
     field public static final String SERVICE_INTERFACE = "android.service.autofill.InlineSuggestionRenderService";
   }
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.cpp b/cmds/hid/jni/com_android_commands_hid_Device.cpp
index f56dd6e..95de6c5 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.cpp
+++ b/cmds/hid/jni/com_android_commands_hid_Device.cpp
@@ -129,7 +129,7 @@
 }
 
 std::unique_ptr<Device> Device::open(int32_t id, const char* name, int32_t vid, int32_t pid,
-                                     const std::vector<uint8_t>& descriptor,
+                                     uint16_t bus, const std::vector<uint8_t>& descriptor,
                                      std::unique_ptr<DeviceCallback> callback) {
     size_t size = descriptor.size();
     if (size > HID_MAX_DESCRIPTOR_SIZE) {
@@ -148,7 +148,7 @@
     strlcpy(reinterpret_cast<char*>(ev.u.create2.name), name, sizeof(ev.u.create2.name));
     memcpy(&ev.u.create2.rd_data, descriptor.data(), size * sizeof(ev.u.create2.rd_data[0]));
     ev.u.create2.rd_size = size;
-    ev.u.create2.bus = BUS_BLUETOOTH;
+    ev.u.create2.bus = bus;
     ev.u.create2.vendor = vid;
     ev.u.create2.product = pid;
     ev.u.create2.version = 0;
@@ -293,8 +293,8 @@
     return data;
 }
 
-static jlong openDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid, jint pid,
-        jbyteArray rawDescriptor, jobject callback) {
+static jlong openDevice(JNIEnv* env, jclass /* clazz */, jstring rawName, jint id, jint vid,
+                        jint pid, jint bus, jbyteArray rawDescriptor, jobject callback) {
     ScopedUtfChars name(env, rawName);
     if (name.c_str() == nullptr) {
         return 0;
@@ -305,7 +305,7 @@
     std::unique_ptr<uhid::DeviceCallback> cb(new uhid::DeviceCallback(env, callback));
 
     std::unique_ptr<uhid::Device> d =
-            uhid::Device::open(id, reinterpret_cast<const char*>(name.c_str()), vid, pid, desc,
+            uhid::Device::open(id, reinterpret_cast<const char*>(name.c_str()), vid, pid, bus, desc,
                                std::move(cb));
     return reinterpret_cast<jlong>(d.release());
 }
@@ -339,14 +339,14 @@
 }
 
 static JNINativeMethod sMethods[] = {
-    { "nativeOpenDevice",
-            "(Ljava/lang/String;III[B"
-            "Lcom/android/commands/hid/Device$DeviceCallback;)J",
-            reinterpret_cast<void*>(openDevice) },
-    { "nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport) },
-    { "nativeSendGetFeatureReportReply", "(JI[B)V",
-            reinterpret_cast<void*>(sendGetFeatureReportReply) },
-    { "nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice) },
+        {"nativeOpenDevice",
+         "(Ljava/lang/String;IIII[B"
+         "Lcom/android/commands/hid/Device$DeviceCallback;)J",
+         reinterpret_cast<void*>(openDevice)},
+        {"nativeSendReport", "(J[B)V", reinterpret_cast<void*>(sendReport)},
+        {"nativeSendGetFeatureReportReply", "(JI[B)V",
+         reinterpret_cast<void*>(sendGetFeatureReportReply)},
+        {"nativeCloseDevice", "(J)V", reinterpret_cast<void*>(closeDevice)},
 };
 
 int register_com_android_commands_hid_Device(JNIEnv* env) {
diff --git a/cmds/hid/jni/com_android_commands_hid_Device.h b/cmds/hid/jni/com_android_commands_hid_Device.h
index 93ea881..7202b45 100644
--- a/cmds/hid/jni/com_android_commands_hid_Device.h
+++ b/cmds/hid/jni/com_android_commands_hid_Device.h
@@ -43,7 +43,7 @@
 class Device {
 public:
     static std::unique_ptr<Device> open(int32_t id, const char* name, int32_t vid, int32_t pid,
-                                        const std::vector<uint8_t>& descriptor,
+                                        uint16_t bus, const std::vector<uint8_t>& descriptor,
                                         std::unique_ptr<DeviceCallback> callback);
 
     ~Device();
diff --git a/cmds/hid/src/com/android/commands/hid/Device.java b/cmds/hid/src/com/android/commands/hid/Device.java
index 874604c..dade415 100644
--- a/cmds/hid/src/com/android/commands/hid/Device.java
+++ b/cmds/hid/src/com/android/commands/hid/Device.java
@@ -52,13 +52,13 @@
         System.loadLibrary("hidcommand_jni");
     }
 
-    private static native long nativeOpenDevice(String name, int id, int vid, int pid,
+    private static native long nativeOpenDevice(String name, int id, int vid, int pid, int bus,
             byte[] descriptor, DeviceCallback callback);
     private static native void nativeSendReport(long ptr, byte[] data);
     private static native void nativeSendGetFeatureReportReply(long ptr, int id, byte[] data);
     private static native void nativeCloseDevice(long ptr);
 
-    public Device(int id, String name, int vid, int pid, byte[] descriptor,
+    public Device(int id, String name, int vid, int pid, int bus, byte[] descriptor,
             byte[] report, SparseArray<byte[]> featureReports, Map<ByteBuffer, byte[]> outputs) {
         mId = id;
         mThread = new HandlerThread("HidDeviceHandler");
@@ -70,6 +70,7 @@
         args.argi1 = id;
         args.argi2 = vid;
         args.argi3 = pid;
+        args.argi4 = bus;
         if (name != null) {
             args.arg1 = name;
         } else {
@@ -115,7 +116,7 @@
                 case MSG_OPEN_DEVICE:
                     SomeArgs args = (SomeArgs) msg.obj;
                     mPtr = nativeOpenDevice((String) args.arg1, args.argi1, args.argi2, args.argi3,
-                            (byte[]) args.arg2, new DeviceCallback());
+                            args.argi4, (byte[]) args.arg2, new DeviceCallback());
                     pauseEvents();
                     break;
                 case MSG_SEND_REPORT:
diff --git a/cmds/hid/src/com/android/commands/hid/Event.java b/cmds/hid/src/com/android/commands/hid/Event.java
index 62587a7..d4bf1d8 100644
--- a/cmds/hid/src/com/android/commands/hid/Event.java
+++ b/cmds/hid/src/com/android/commands/hid/Event.java
@@ -36,12 +36,28 @@
     public static final String COMMAND_DELAY = "delay";
     public static final String COMMAND_REPORT = "report";
 
+    // These constants come from "include/uapi/linux/input.h" in the kernel
+    enum Bus {
+        USB(0x03), BLUETOOTH(0x05);
+
+        Bus(int value) {
+            mValue = value;
+        }
+
+        int getValue() {
+            return mValue;
+        }
+
+        private int mValue;
+    }
+
     private int mId;
     private String mCommand;
     private String mName;
     private byte[] mDescriptor;
     private int mVid;
     private int mPid;
+    private Bus mBus;
     private byte[] mReport;
     private SparseArray<byte[]> mFeatureReports;
     private Map<ByteBuffer, byte[]> mOutputs;
@@ -71,6 +87,10 @@
         return mPid;
     }
 
+    public int getBus() {
+        return mBus.getValue();
+    }
+
     public byte[] getReport() {
         return mReport;
     }
@@ -94,6 +114,7 @@
             + ", descriptor=" + Arrays.toString(mDescriptor)
             + ", vid=" + mVid
             + ", pid=" + mPid
+            + ", bus=" + mBus
             + ", report=" + Arrays.toString(mReport)
             + ", feature_reports=" + mFeatureReports.toString()
             + ", outputs=" + mOutputs.toString()
@@ -144,6 +165,10 @@
             mEvent.mPid = pid;
         }
 
+        public void setBus(Bus bus) {
+            mEvent.mBus = bus;
+        }
+
         public void setDuration(int duration) {
             mEvent.mDuration = duration;
         }
@@ -206,6 +231,9 @@
                             case "pid":
                                 eb.setPid(readInt());
                                 break;
+                            case "bus":
+                                eb.setBus(readBus());
+                                break;
                             case "report":
                                 eb.setReport(readData());
                                 break;
@@ -264,6 +292,11 @@
             return Integer.decode(val);
         }
 
+        private Bus readBus() throws IOException {
+            String val = mReader.nextString();
+            return Bus.valueOf(val.toUpperCase());
+        }
+
         private SparseArray<byte[]> readFeatureReports()
                 throws IllegalStateException, IOException {
             SparseArray<byte[]> featureReports = new SparseArray<>();
diff --git a/cmds/hid/src/com/android/commands/hid/Hid.java b/cmds/hid/src/com/android/commands/hid/Hid.java
index 0ee2cc4..fac0ab2 100644
--- a/cmds/hid/src/com/android/commands/hid/Hid.java
+++ b/cmds/hid/src/com/android/commands/hid/Hid.java
@@ -113,7 +113,7 @@
                     "Tried to send command \"" + e.getCommand() + "\" to an unregistered device!");
         }
         int id = e.getId();
-        Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(),
+        Device d = new Device(id, e.getName(), e.getVendorId(), e.getProductId(), e.getBus(),
                 e.getDescriptor(), e.getReport(), e.getFeatureReports(), e.getOutputs());
         mDevices.append(id, d);
     }
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 41a1706..66f5c39 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -146,6 +146,7 @@
     host_supported: true,
     srcs: [
         "idmap2/Create.cpp",
+        "idmap2/CreateMultiple.cpp",
         "idmap2/Dump.cpp",
         "idmap2/Lookup.cpp",
         "idmap2/Main.cpp",
diff --git a/cmds/idmap2/idmap2/Commands.h b/cmds/idmap2/idmap2/Commands.h
index 718e361..e626738 100644
--- a/cmds/idmap2/idmap2/Commands.h
+++ b/cmds/idmap2/idmap2/Commands.h
@@ -23,6 +23,7 @@
 #include "idmap2/Result.h"
 
 android::idmap2::Result<android::idmap2::Unit> Create(const std::vector<std::string>& args);
+android::idmap2::Result<android::idmap2::Unit> CreateMultiple(const std::vector<std::string>& args);
 android::idmap2::Result<android::idmap2::Unit> Dump(const std::vector<std::string>& args);
 android::idmap2::Result<android::idmap2::Unit> Lookup(const std::vector<std::string>& args);
 android::idmap2::Result<android::idmap2::Unit> Scan(const std::vector<std::string>& args);
diff --git a/cmds/idmap2/idmap2/CreateMultiple.cpp b/cmds/idmap2/idmap2/CreateMultiple.cpp
new file mode 100644
index 0000000..0b0541f
--- /dev/null
+++ b/cmds/idmap2/idmap2/CreateMultiple.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include <sys/stat.h>   // umask
+#include <sys/types.h>  // umask
+
+#include <fstream>
+#include <memory>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "android-base/stringprintf.h"
+#include "idmap2/BinaryStreamVisitor.h"
+#include "idmap2/CommandLineOptions.h"
+#include "idmap2/FileUtils.h"
+#include "idmap2/Idmap.h"
+#include "idmap2/Policies.h"
+#include "idmap2/SysTrace.h"
+
+using android::ApkAssets;
+using android::base::StringPrintf;
+using android::idmap2::BinaryStreamVisitor;
+using android::idmap2::CommandLineOptions;
+using android::idmap2::Error;
+using android::idmap2::Idmap;
+using android::idmap2::PoliciesToBitmask;
+using android::idmap2::PolicyBitmask;
+using android::idmap2::PolicyFlags;
+using android::idmap2::Result;
+using android::idmap2::Unit;
+using android::idmap2::utils::kIdmapCacheDir;
+using android::idmap2::utils::kIdmapFilePermissionMask;
+using android::idmap2::utils::UidHasWriteAccessToPath;
+
+Result<Unit> CreateMultiple(const std::vector<std::string>& args) {
+  SYSTRACE << "CreateMultiple " << args;
+  std::string target_apk_path;
+  std::string idmap_dir = kIdmapCacheDir;
+  std::vector<std::string> overlay_apk_paths;
+  std::vector<std::string> policies;
+  bool ignore_overlayable = false;
+
+  const CommandLineOptions opts =
+      CommandLineOptions("idmap2 create-multiple")
+          .MandatoryOption("--target-apk-path",
+                           "input: path to apk which will have its resources overlaid",
+                           &target_apk_path)
+          .MandatoryOption("--overlay-apk-path",
+                           "input: path to apk which contains the new resource values",
+                           &overlay_apk_paths)
+          .OptionalOption("--idmap-dir",
+                          StringPrintf("output: path to the directory in which to write idmap file"
+                                       " (defaults to %s)",
+                                       kIdmapCacheDir),
+                          &idmap_dir)
+          .OptionalOption("--policy",
+                          "input: an overlayable policy this overlay fulfills"
+                          " (if none or supplied, the overlay policy will default to \"public\")",
+                          &policies)
+          .OptionalFlag("--ignore-overlayable", "disables overlayable and policy checks",
+                        &ignore_overlayable);
+  const auto opts_ok = opts.Parse(args);
+  if (!opts_ok) {
+    return opts_ok.GetError();
+  }
+
+  PolicyBitmask fulfilled_policies = 0;
+  auto conv_result = PoliciesToBitmask(policies);
+  if (conv_result) {
+    fulfilled_policies |= *conv_result;
+  } else {
+    return conv_result.GetError();
+  }
+
+  if (fulfilled_policies == 0) {
+    fulfilled_policies |= PolicyFlags::POLICY_PUBLIC;
+  }
+
+  const std::unique_ptr<const ApkAssets> target_apk = ApkAssets::Load(target_apk_path);
+  if (!target_apk) {
+    return Error("failed to load apk %s", target_apk_path.c_str());
+  }
+
+  std::vector<std::string> idmap_paths;
+  for (const std::string& overlay_apk_path : overlay_apk_paths) {
+    const std::string idmap_path = Idmap::CanonicalIdmapPathFor(idmap_dir, overlay_apk_path);
+    const uid_t uid = getuid();
+    if (!UidHasWriteAccessToPath(uid, idmap_path)) {
+      LOG(WARNING) << "uid " << uid << "does not have write access to " << idmap_path.c_str();
+      continue;
+    }
+
+    const std::unique_ptr<const ApkAssets> overlay_apk = ApkAssets::Load(overlay_apk_path);
+    if (!overlay_apk) {
+      LOG(WARNING) << "failed to load apk " << overlay_apk_path.c_str();
+      continue;
+    }
+
+    const auto idmap =
+        Idmap::FromApkAssets(*target_apk, *overlay_apk, fulfilled_policies, !ignore_overlayable);
+    if (!idmap) {
+      LOG(WARNING) << "failed to create idmap";
+      continue;
+    }
+
+    umask(kIdmapFilePermissionMask);
+    std::ofstream fout(idmap_path);
+    if (fout.fail()) {
+      LOG(WARNING) << "failed to open idmap path " << idmap_path.c_str();
+      continue;
+    }
+
+    BinaryStreamVisitor visitor(fout);
+    (*idmap)->accept(&visitor);
+    fout.close();
+    if (fout.fail()) {
+      LOG(WARNING) << "failed to write to idmap path %s" << idmap_path.c_str();
+      continue;
+    }
+
+    idmap_paths.emplace_back(idmap_path);
+  }
+
+  for (const std::string& idmap_path : idmap_paths) {
+    std::cout << idmap_path << std::endl;
+  }
+
+  return Unit{};
+}
diff --git a/cmds/idmap2/idmap2/Main.cpp b/cmds/idmap2/idmap2/Main.cpp
index 8794908..a07e793 100644
--- a/cmds/idmap2/idmap2/Main.cpp
+++ b/cmds/idmap2/idmap2/Main.cpp
@@ -53,7 +53,9 @@
 int main(int argc, char** argv) {
   SYSTRACE << "main";
   const NameToFunctionMap commands = {
-      {"create", Create}, {"dump", Dump}, {"lookup", Lookup}, {"scan", Scan}, {"verify", Verify},
+      {"create", Create}, {"create-multiple", CreateMultiple},
+      {"dump", Dump},     {"lookup", Lookup},
+      {"scan", Scan},     {"verify", Verify},
   };
   if (argc <= 1) {
     PrintUsage(commands, std::cerr);
diff --git a/cmds/statsd/Android.bp b/cmds/statsd/Android.bp
index 2ee055d..73a8f66 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -105,10 +105,6 @@
         "src/uid_data.proto",
     ],
 
-    cflags: [
-        "-DNEW_ENCODING_SCHEME",
-    ],
-
     local_include_dirs: [
         "src",
     ],
@@ -173,6 +169,11 @@
         "libcutils",
         "libstatslog",
     ],
+    apex_available: [
+        //TODO(b/149782403): Remove this once statsd no longer links against libstatsmetadata
+        "com.android.os.statsd",
+        "test_com.android.os.statsd",
+    ],
 }
 
 
@@ -216,7 +217,10 @@
 
     shared_libs: ["libgtest_prod"],
 
-    init_rc: ["statsd.rc"],
+    apex_available: [
+        "com.android.os.statsd",
+        "test_com.android.os.statsd",
+    ],
 }
 
 // ==============
@@ -298,6 +302,11 @@
     static_libs: [
         "libgmock",
         "libplatformprotos",
+
+        // TODO(b/149842105): Make libstatssocket shared and remove libcutils once statsd_test is
+        // moved to the apex.
+        "libstatssocket",
+        "libcutils",
     ],
 
     proto: {
@@ -307,7 +316,6 @@
 
     shared_libs: [
         "libprotobuf-cpp-lite",
-        "libstatssocket"
     ],
 
 }
@@ -316,55 +324,55 @@
 // statsd micro benchmark
 //#############################
 
-cc_benchmark {
-    name: "statsd_benchmark",
-    defaults: ["statsd_defaults"],
-
-    srcs: [
-        // atom_field_options.proto needs field_options.proto, but that is
-        // not included in libprotobuf-cpp-lite, so compile it here.
-        ":libprotobuf-internal-protos",
-
-        "benchmark/duration_metric_benchmark.cpp",
-        "benchmark/filter_value_benchmark.cpp",
-        "benchmark/get_dimensions_for_condition_benchmark.cpp",
-        "benchmark/hello_world_benchmark.cpp",
-        "benchmark/log_event_benchmark.cpp",
-        "benchmark/main.cpp",
-        "benchmark/metric_util.cpp",
-        "benchmark/stats_write_benchmark.cpp",
-        "src/atom_field_options.proto",
-        "src/atoms.proto",
-        "src/stats_log.proto",
-    ],
-
-    proto: {
-        type: "lite",
-        include_dirs: ["external/protobuf/src"],
-    },
-
-    cflags: [
-        "-Wall",
-        "-Werror",
-        "-Wno-unused-parameter",
-        "-Wno-unused-variable",
-        "-Wno-unused-function",
-
-        // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
-        "-Wno-varargs",
-    ],
-
-    static_libs: [
-        "libplatformprotos",
-    ],
-
-    shared_libs: [
-        "libgtest_prod",
-        "libprotobuf-cpp-lite",
-        "libstatslog",
-        "libstatssocket",
-    ],
-}
+//cc_benchmark {
+//    name: "statsd_benchmark",
+//    defaults: ["statsd_defaults"],
+//
+//    srcs: [
+//        // atom_field_options.proto needs field_options.proto, but that is
+//        // not included in libprotobuf-cpp-lite, so compile it here.
+//        ":libprotobuf-internal-protos",
+//
+//        "benchmark/duration_metric_benchmark.cpp",
+//        "benchmark/filter_value_benchmark.cpp",
+//        "benchmark/get_dimensions_for_condition_benchmark.cpp",
+//        "benchmark/hello_world_benchmark.cpp",
+//        "benchmark/log_event_benchmark.cpp",
+//        "benchmark/main.cpp",
+//        "benchmark/metric_util.cpp",
+//        "benchmark/stats_write_benchmark.cpp",
+//        "src/atom_field_options.proto",
+//        "src/atoms.proto",
+//        "src/stats_log.proto",
+//    ],
+//
+//    proto: {
+//        type: "lite",
+//        include_dirs: ["external/protobuf/src"],
+//    },
+//
+//    cflags: [
+//        "-Wall",
+//        "-Werror",
+//        "-Wno-unused-parameter",
+//        "-Wno-unused-variable",
+//        "-Wno-unused-function",
+//
+//        // Bug: http://b/29823425 Disable -Wvarargs for Clang update to r271374
+//        "-Wno-varargs",
+//    ],
+//
+//    static_libs: [
+//        "libplatformprotos",
+//    ],
+//
+//    shared_libs: [
+//        "libgtest_prod",
+//        "libprotobuf-cpp-lite",
+//        "libstatslog",
+//        "libstatssocket",
+//    ],
+//}
 
 // ====  java proto device library (for test only)  ==============================
 java_library {
diff --git a/cmds/statsd/src/StatsLogProcessor.cpp b/cmds/statsd/src/StatsLogProcessor.cpp
index 97e0a2e..649c004 100644
--- a/cmds/statsd/src/StatsLogProcessor.cpp
+++ b/cmds/statsd/src/StatsLogProcessor.cpp
@@ -208,12 +208,8 @@
     trainInfo.requiresLowLatencyMonitor =
             event->GetBool(5 /*requires low latency monitor field id*/, &err);
     trainInfo.status = int32_t(event->GetLong(6 /*state field id*/, &err));
-#ifdef NEW_ENCODING_SCHEME
     std::vector<uint8_t> trainExperimentIdBytes =
             event->GetStorage(7 /*experiment ids field id*/, &err);
-#else
-    string trainExperimentIdString = event->GetString(7 /*experiment ids field id*/, &err);
-#endif
     bool is_rollback = event->GetBool(10 /*is rollback field id*/, &err);
 
     if (err != NO_ERROR) {
@@ -221,12 +217,8 @@
         return;
     }
     ExperimentIds trainExperimentIds;
-#ifdef NEW_ENCODING_SCHEME
     if (!trainExperimentIds.ParseFromArray(trainExperimentIdBytes.data(),
                                            trainExperimentIdBytes.size())) {
-#else
-    if (!trainExperimentIds.ParseFromString(trainExperimentIdString)) {
-#endif
         ALOGE("Failed to parse experimentids in binary push state changed.");
         return;
     }
@@ -241,11 +233,7 @@
     int32_t userId = multiuser_get_user_id(uid);
 
     event->updateValue(2 /*train version field id*/, trainInfo.trainVersionCode, LONG);
-#ifdef NEW_ENCODING_SCHEME
     event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STORAGE);
-#else
-    event->updateValue(7 /*experiment ids field id*/, trainExperimentIdProto, STRING);
-#endif
     event->updateValue(8 /*user id field id*/, userId, INT);
 
     // If this event is a rollback event, then the following bits in the event
@@ -352,11 +340,7 @@
     vector<uint8_t> experimentIdProto;
     writeExperimentIdsToProto(experimentIds, &experimentIdProto);
 
-#ifdef NEW_ENCODING_SCHEME
     event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STORAGE);
-#else
-    event->updateValue(6 /*experiment ids field id*/, experimentIdProto, STRING);
-#endif
 }
 
 vector<int64_t> StatsLogProcessor::processWatchdogRollbackOccurred(const int32_t rollbackTypeIn,
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index bf6afe7..43d0fce 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -392,6 +392,7 @@
         WifiFailureStatReported wifi_failure_stat_reported = 252 [(module) = "wifi"];
         WifiConnectionResultReported wifi_connection_result_reported = 253 [(module) = "wifi"];
         AppFreezeChanged app_freeze_changed = 254 [(module) = "framework"];
+        SnapshotMergeReported snapshot_merge_reported = 255;
         SdkExtensionStatus sdk_extension_status = 354;
     }
 
@@ -4418,6 +4419,52 @@
     optional int32 error_code = 2;
 }
 
+/**
+ * Collects Virtual A/B statistics related to the use of dm-snapshot performed
+ * after an OTA.
+ *
+ * Logged from:
+ *  - system/core/fs_mgr/libsnapshot/snapshot.cpp
+ *  - system/core/fs_mgr/libsnapshot/snapshotctl.cpp
+ */
+message SnapshotMergeReported {
+    // Keep in sync with
+    // system/core/fs_mgr/libsnapshot/android/snapshot/snapshot.proto
+    enum UpdateState {
+        // No update or merge is in progress.
+        NONE = 0;
+        // An update is applying; snapshots may already exist.
+        INITIATED = 1;
+        // An update is pending, but has not been successfully booted yet.
+        UNVERIFIED = 2;
+        // The kernel is merging in the background.
+        MERGING = 3;
+        // Post-merge cleanup steps could not be completed due to a transient
+        // error, but the next reboot will finish any pending operations.
+        MERGE_NEEDS_REBOOT = 4;
+        // Merging is complete, and needs to be acknowledged.
+        MERGE_COMPLETED = 5;
+        // Merging failed due to an unrecoverable error.
+        MERGE_FAILED = 6;
+        // The update was implicitly cancelled, either by a rollback or a flash
+        // operation via fastboot. This state can only be returned by WaitForMerge.
+        CANCELLED = 7;
+    };
+
+    // Status of the update after the merge attempts.
+    optional UpdateState final_state = 1;
+
+    // Time to complete a merge operation in milliseconds.
+    // A negative value corresponds to the case in which the merge operation
+    // was interrupted and resumed (e.g. in case of a system reboot during the
+    // merge).
+    optional int64 duration_millis = 2;
+
+    // Number of reboots that occurred after issuing and before completing the
+    // merge of all the snapshot devices.
+    optional int32 intermediate_reboots = 3;
+}
+
 //////////////////////////////////////////////////////////////////////
 // Pulled atoms below this line //
 //////////////////////////////////////////////////////////////////////
@@ -8231,14 +8278,6 @@
 }
 
 /**
- * HWUI renders pipeline type: GL (0) or Vulkan (1).
- */
-enum PipelineType {
-    GL = 0;
-    VULKAN = 1;
-}
-
-/**
  * HWUI stats for a given app.
  */
 message GraphicsStats {
@@ -8251,9 +8290,16 @@
     // The start & end timestamps in UTC as
     // milliseconds since January 1, 1970
     // Compatible with java.util.Date#setTime()
-    optional int64 stats_start = 3;
+    optional int64 start_millis = 3;
 
-    optional int64 stats_end = 4;
+    optional int64 end_millis = 4;
+
+    // HWUI renders pipeline type: GL (1) or Vulkan (2).
+    enum PipelineType {
+        UNKNOWN = 0;
+        GL = 1;
+        VULKAN = 2;
+    }
 
     // HWUI renders pipeline type: GL or Vulkan.
     optional PipelineType pipeline = 5;
diff --git a/cmds/statsd/src/external/StatsCallbackPuller.cpp b/cmds/statsd/src/external/StatsCallbackPuller.cpp
index b6c8e34..0edf40b 100644
--- a/cmds/statsd/src/external/StatsCallbackPuller.cpp
+++ b/cmds/statsd/src/external/StatsCallbackPuller.cpp
@@ -69,8 +69,7 @@
                         uint8_t* buf = reinterpret_cast<uint8_t*>(
                                 const_cast<int8_t*>(parcel.buffer.data()));
                         shared_ptr<LogEvent> event = make_shared<LogEvent>(
-                                buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1,
-                                /*useNewSchema=*/true);
+                                buf, parcel.buffer.size(), /*uid=*/-1, /*pid=*/-1);
                         sharedData->push_back(event);
                     }
                     *pullSuccess = success;
diff --git a/cmds/statsd/src/logd/LogEvent.cpp b/cmds/statsd/src/logd/LogEvent.cpp
index 9c50846..3e46d13 100644
--- a/cmds/statsd/src/logd/LogEvent.cpp
+++ b/cmds/statsd/src/logd/LogEvent.cpp
@@ -74,29 +74,7 @@
       mLogUid(uid),
       mLogPid(pid)
 {
-#ifdef NEW_ENCODING_SCHEME
     initNew();
-# else
-    mContext = create_android_log_parser((char*)msg, len);
-    init(mContext);
-    if (mContext) android_log_destroy(&mContext); // set mContext to NULL
-#endif
-}
-
-LogEvent::LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema)
-    : mBuf(msg),
-      mRemainingLen(len),
-      mLogdTimestampNs(time(nullptr)),
-      mLogUid(uid),
-      mLogPid(pid)
-{
-    if (useNewSchema) {
-        initNew();
-    } else {
-        mContext = create_android_log_parser((char*)msg, len);
-        init(mContext);
-        if (mContext) android_log_destroy(&mContext);  // set mContext to NULL
-    }
 }
 
 LogEvent::LogEvent(const LogEvent& event) {
@@ -225,22 +203,6 @@
     }
 }
 
-void LogEvent::init() {
-    if (mContext) {
-        const char* buffer;
-        size_t len = android_log_write_list_buffer(mContext, &buffer);
-        // turns to reader mode
-        android_log_context contextForRead = create_android_log_parser(buffer, len);
-        if (contextForRead) {
-            init(contextForRead);
-            // destroy the context to save memory.
-            // android_log_destroy will set mContext to NULL
-            android_log_destroy(&contextForRead);
-        }
-        android_log_destroy(&mContext);
-    }
-}
-
 LogEvent::~LogEvent() {
     if (mContext) {
         // This is for the case when LogEvent is created using the test interface
@@ -577,132 +539,6 @@
     return (typeInfo >> 4) & 0x0F;
 }
 
-/**
- * The elements of each log event are stored as a vector of android_log_list_elements.
- * The goal is to do as little preprocessing as possible, because we read a tiny fraction
- * of the elements that are written to the log.
- *
- * The idea here is to read through the log items once, we get as much information we need for
- * matching as possible. Because this log will be matched against lots of matchers.
- */
-void LogEvent::init(android_log_context context) {
-    android_log_list_element elem;
-    int i = 0;
-    int depth = -1;
-    int pos[] = {1, 1, 1};
-    bool isKeyValuePairAtom = false;
-    do {
-        elem = android_log_read_next(context);
-        switch ((int)elem.type) {
-            case EVENT_TYPE_INT:
-                // elem at [0] is EVENT_TYPE_LIST, [1] is the timestamp, [2] is tag id.
-                if (i == 2) {
-                    mTagId = elem.data.int32;
-                    isKeyValuePairAtom = (mTagId == android::util::KEY_VALUE_PAIRS_ATOM);
-                } else {
-                    if (depth < 0 || depth > 2) {
-                        return;
-                    }
-
-                    mValues.push_back(
-                            FieldValue(Field(mTagId, pos, depth), Value((int32_t)elem.data.int32)));
-
-                    pos[depth]++;
-                }
-                break;
-            case EVENT_TYPE_FLOAT: {
-                if (depth < 0 || depth > 2) {
-                    ALOGE("Depth > 2. Not supported!");
-                    return;
-                }
-
-                // Handles the oneof field in KeyValuePair atom.
-                if (isKeyValuePairAtom && depth == 2) {
-                    pos[depth] = 5;
-                }
-
-                mValues.push_back(FieldValue(Field(mTagId, pos, depth), Value(elem.data.float32)));
-
-                pos[depth]++;
-
-            } break;
-            case EVENT_TYPE_STRING: {
-                if (depth < 0 || depth > 2) {
-                    ALOGE("Depth > 2. Not supported!");
-                    return;
-                }
-
-                // Handles the oneof field in KeyValuePair atom.
-                if (isKeyValuePairAtom && depth == 2) {
-                    pos[depth] = 4;
-                }
-                mValues.push_back(FieldValue(Field(mTagId, pos, depth),
-                                             Value(string(elem.data.string, elem.len))));
-
-                pos[depth]++;
-
-            } break;
-            case EVENT_TYPE_LONG: {
-                if (i == 1) {
-                    mElapsedTimestampNs = elem.data.int64;
-                } else {
-                    if (depth < 0 || depth > 2) {
-                        ALOGE("Depth > 2. Not supported!");
-                        return;
-                    }
-                    // Handles the oneof field in KeyValuePair atom.
-                    if (isKeyValuePairAtom && depth == 2) {
-                        pos[depth] = 3;
-                    }
-                    mValues.push_back(
-                            FieldValue(Field(mTagId, pos, depth), Value((int64_t)elem.data.int64)));
-
-                    pos[depth]++;
-                }
-            } break;
-            case EVENT_TYPE_LIST:
-                depth++;
-                if (depth > 2) {
-                    ALOGE("Depth > 2. Not supported!");
-                    return;
-                }
-                pos[depth] = 1;
-
-                break;
-            case EVENT_TYPE_LIST_STOP: {
-                int prevDepth = depth;
-                depth--;
-                if (depth >= 0 && depth < 2) {
-                    // Now go back to decorate the previous items that are last at prevDepth.
-                    // So that we can later easily match them with Position=Last matchers.
-                    pos[prevDepth]--;
-                    int path = getEncodedField(pos, prevDepth, false);
-                    for (auto it = mValues.rbegin(); it != mValues.rend(); ++it) {
-                        if (it->mField.getDepth() >= prevDepth &&
-                            it->mField.getPath(prevDepth) == path) {
-                            it->mField.decorateLastPos(prevDepth);
-                        } else {
-                            // Safe to break, because the items are in DFS order.
-                            break;
-                        }
-                    }
-                    pos[depth]++;
-                }
-                break;
-            }
-            case EVENT_TYPE_UNKNOWN:
-                break;
-            default:
-                break;
-        }
-        i++;
-    } while ((elem.type != EVENT_TYPE_UNKNOWN) && !elem.complete);
-    if (isKeyValuePairAtom && mValues.size() > 0) {
-        mValues[0] = FieldValue(Field(android::util::KEY_VALUE_PAIRS_ATOM, getSimpleField(1)),
-                                Value((int32_t)mLogUid));
-    }
-}
-
 int64_t LogEvent::GetLong(size_t key, status_t* err) const {
     // TODO(b/110561208): encapsulate the magical operations in Field struct as static functions
     int field = getSimpleField(key);
diff --git a/cmds/statsd/src/logd/LogEvent.h b/cmds/statsd/src/logd/LogEvent.h
index ea449b0..e167e67 100644
--- a/cmds/statsd/src/logd/LogEvent.h
+++ b/cmds/statsd/src/logd/LogEvent.h
@@ -71,11 +71,6 @@
     explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid);
 
     /**
-     * Temp constructor to use for pulled atoms until we flip the socket schema.
-     */
-    explicit LogEvent(uint8_t* msg, uint32_t len, int32_t uid, int32_t pid, bool useNewSchema);
-
-    /**
      * Constructs a LogEvent with synthetic data for testing. Must call init() before reading.
      */
     explicit LogEvent(int32_t tagId, int64_t wallClockTimestampNs, int64_t elapsedTimestampNs);
@@ -172,12 +167,6 @@
     void ToProto(android::util::ProtoOutputStream& out) const;
 
     /**
-     * Used with the constructor where tag is passed in. Converts the log_event_list to read mode
-     * and prepares the list for reading.
-     */
-    void init();
-
-    /**
      * Set elapsed timestamp if the original timestamp is missing.
      */
     void setElapsedTimestampNs(int64_t timestampNs) {
@@ -304,11 +293,6 @@
     uint8_t getTypeId(uint8_t typeInfo);
     uint8_t getNumAnnotations(uint8_t typeInfo);
 
-    /**
-     * Parses a log_msg into a LogEvent object.
-     */
-    void init(android_log_context context);
-
     // The items are naturally sorted in DFS order as we read them. this allows us to do fast
     // matching.
     std::vector<FieldValue> mValues;
diff --git a/cmds/statsd/src/storage/StorageManager.cpp b/cmds/statsd/src/storage/StorageManager.cpp
index 4899b4a..dcfdfe3 100644
--- a/cmds/statsd/src/storage/StorageManager.cpp
+++ b/cmds/statsd/src/storage/StorageManager.cpp
@@ -75,11 +75,11 @@
                         (long long)id);
 }
 
-static const char* findTrainInfoFileNameLocked(const string& trainName) {
+static string findTrainInfoFileNameLocked(const string& trainName) {
     unique_ptr<DIR, decltype(&closedir)> dir(opendir(TRAIN_INFO_DIR), closedir);
     if (dir == NULL) {
         VLOG("Path %s does not exist", TRAIN_INFO_DIR);
-        return nullptr;
+        return "";
     }
     dirent* de;
     while ((de = readdir(dir.get()))) {
@@ -90,12 +90,12 @@
         if (fileNameLength >= trainName.length()) {
             if (0 == strncmp(fileName + fileNameLength - trainName.length(), trainName.c_str(),
                              trainName.length())) {
-                return fileName;
+              return string(fileName);
             }
         }
     }
 
-    return nullptr;
+    return "";
 }
 
 // Returns array of int64_t which contains timestamp in seconds, uid,
@@ -267,13 +267,13 @@
 
 bool StorageManager::readTrainInfoLocked(const std::string& trainName, InstallTrainInfo& trainInfo) {
     trimToFit(TRAIN_INFO_DIR, /*parseTimestampOnly=*/ true);
-    const char* fileName = findTrainInfoFileNameLocked(trainName);
-    if (fileName == nullptr) {
+    string fileName = findTrainInfoFileNameLocked(trainName);
+    if (fileName.empty()) {
         return false;
     }
-    int fd = open(StringPrintf("%s/%s", TRAIN_INFO_DIR, fileName).c_str(), O_RDONLY | O_CLOEXEC);
+    int fd = open(StringPrintf("%s/%s", TRAIN_INFO_DIR, fileName.c_str()).c_str(), O_RDONLY | O_CLOEXEC);
     if (fd == -1) {
-        VLOG("Failed to open %s", fileName);
+        VLOG("Failed to open %s", fileName.c_str());
         return false;
     }
 
diff --git a/cmds/statsd/tests/FieldValue_test.cpp b/cmds/statsd/tests/FieldValue_test.cpp
index 9e69d97..a5ff067 100644
--- a/cmds/statsd/tests/FieldValue_test.cpp
+++ b/cmds/statsd/tests/FieldValue_test.cpp
@@ -72,65 +72,66 @@
     EXPECT_EQ((int32_t)0xff7f7f7f, matcher12.mMask);
 }
 
-TEST(AtomMatcherTest, TestFilter_ALL) {
-    FieldMatcher matcher1;
-    matcher1.set_field(10);
-    FieldMatcher* child = matcher1.add_child();
-    child->set_field(1);
-    child->set_position(Position::ALL);
-
-    child->add_child()->set_field(1);
-    child->add_child()->set_field(2);
-
-    child = matcher1.add_child();
-    child->set_field(2);
-
-    vector<Matcher> matchers;
-    translateFieldMatcher(matcher1, &matchers);
-
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    AttributionNodeInternal attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("location3");
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
-                                                              attribution_node3};
-
-    // Set up the event
-    LogEvent event(10, 12345);
-    event.write(attribution_nodes);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-    HashableDimensionKey output;
-
-    filterValues(matchers, event.getValues(), &output);
-
-    EXPECT_EQ((size_t)7, output.getValues().size());
-    EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
-    EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
-    EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
-    EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
-
-    EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
-    EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
-    EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
-    EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
-
-    EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
-    EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
-    EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
-    EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
-
-    EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
-    EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestFilter_ALL) {
+//    FieldMatcher matcher1;
+//    matcher1.set_field(10);
+//    FieldMatcher* child = matcher1.add_child();
+//    child->set_field(1);
+//    child->set_position(Position::ALL);
+//
+//    child->add_child()->set_field(1);
+//    child->add_child()->set_field(2);
+//
+//    child = matcher1.add_child();
+//    child->set_field(2);
+//
+//    vector<Matcher> matchers;
+//    translateFieldMatcher(matcher1, &matchers);
+//
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1111);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    AttributionNodeInternal attribution_node3;
+//    attribution_node3.set_uid(3333);
+//    attribution_node3.set_tag("location3");
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+//                                                              attribution_node3};
+//
+//    // Set up the event
+//    LogEvent event(10, 12345);
+//    event.write(attribution_nodes);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//    HashableDimensionKey output;
+//
+//    filterValues(matchers, event.getValues(), &output);
+//
+//    EXPECT_EQ((size_t)7, output.getValues().size());
+//    EXPECT_EQ((int32_t)0x02010101, output.getValues()[0].mField.getField());
+//    EXPECT_EQ((int32_t)1111, output.getValues()[0].mValue.int_value);
+//    EXPECT_EQ((int32_t)0x02010102, output.getValues()[1].mField.getField());
+//    EXPECT_EQ("location1", output.getValues()[1].mValue.str_value);
+//
+//    EXPECT_EQ((int32_t)0x02010201, output.getValues()[2].mField.getField());
+//    EXPECT_EQ((int32_t)2222, output.getValues()[2].mValue.int_value);
+//    EXPECT_EQ((int32_t)0x02010202, output.getValues()[3].mField.getField());
+//    EXPECT_EQ("location2", output.getValues()[3].mValue.str_value);
+//
+//    EXPECT_EQ((int32_t)0x02010301, output.getValues()[4].mField.getField());
+//    EXPECT_EQ((int32_t)3333, output.getValues()[4].mValue.int_value);
+//    EXPECT_EQ((int32_t)0x02010302, output.getValues()[5].mField.getField());
+//    EXPECT_EQ("location3", output.getValues()[5].mValue.str_value);
+//
+//    EXPECT_EQ((int32_t)0x00020000, output.getValues()[6].mField.getField());
+//    EXPECT_EQ("some value", output.getValues()[6].mValue.str_value);
+//}
 
 TEST(AtomMatcherTest, TestSubDimension) {
     HashableDimensionKey dim;
@@ -173,60 +174,61 @@
     EXPECT_TRUE(dim.contains(subDim4));
 }
 
-TEST(AtomMatcherTest, TestMetric2ConditionLink) {
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    AttributionNodeInternal attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("location3");
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
-                                                              attribution_node3};
-
-    // Set up the event
-    LogEvent event(10, 12345);
-    event.write(attribution_nodes);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-
-    FieldMatcher whatMatcher;
-    whatMatcher.set_field(10);
-    FieldMatcher* child11 = whatMatcher.add_child();
-    child11->set_field(1);
-    child11->set_position(Position::ANY);
-    child11 = child11->add_child();
-    child11->set_field(1);
-
-    FieldMatcher conditionMatcher;
-    conditionMatcher.set_field(27);
-    FieldMatcher* child2 = conditionMatcher.add_child();
-    child2->set_field(2);
-    child2->set_position(Position::LAST);
-
-    child2 = child2->add_child();
-    child2->set_field(2);
-
-    Metric2Condition link;
-
-    translateFieldMatcher(whatMatcher, &link.metricFields);
-    translateFieldMatcher(conditionMatcher, &link.conditionFields);
-
-    EXPECT_EQ((size_t)1, link.metricFields.size());
-    EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
-    EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
-    EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
-
-    EXPECT_EQ((size_t)1, link.conditionFields.size());
-    EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
-    EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
-    EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestMetric2ConditionLink) {
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1111);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    AttributionNodeInternal attribution_node3;
+//    attribution_node3.set_uid(3333);
+//    attribution_node3.set_tag("location3");
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+//                                                              attribution_node3};
+//
+//    // Set up the event
+//    LogEvent event(10, 12345);
+//    event.write(attribution_nodes);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    FieldMatcher whatMatcher;
+//    whatMatcher.set_field(10);
+//    FieldMatcher* child11 = whatMatcher.add_child();
+//    child11->set_field(1);
+//    child11->set_position(Position::ANY);
+//    child11 = child11->add_child();
+//    child11->set_field(1);
+//
+//    FieldMatcher conditionMatcher;
+//    conditionMatcher.set_field(27);
+//    FieldMatcher* child2 = conditionMatcher.add_child();
+//    child2->set_field(2);
+//    child2->set_position(Position::LAST);
+//
+//    child2 = child2->add_child();
+//    child2->set_field(2);
+//
+//    Metric2Condition link;
+//
+//    translateFieldMatcher(whatMatcher, &link.metricFields);
+//    translateFieldMatcher(conditionMatcher, &link.conditionFields);
+//
+//    EXPECT_EQ((size_t)1, link.metricFields.size());
+//    EXPECT_EQ((int32_t)0x02010001, link.metricFields[0].mMatcher.getField());
+//    EXPECT_EQ((int32_t)0xff7f007f, link.metricFields[0].mMask);
+//    EXPECT_EQ((int32_t)10, link.metricFields[0].mMatcher.getTag());
+//
+//    EXPECT_EQ((size_t)1, link.conditionFields.size());
+//    EXPECT_EQ((int32_t)0x02028002, link.conditionFields[0].mMatcher.getField());
+//    EXPECT_EQ((int32_t)0xff7f807f, link.conditionFields[0].mMask);
+//    EXPECT_EQ((int32_t)27, link.conditionFields[0].mMatcher.getTag());
+//}
 
 TEST(AtomMatcherTest, TestWriteDimensionPath) {
     for (auto position : {Position::ANY, Position::ALL, Position::FIRST, Position::LAST}) {
@@ -437,49 +439,50 @@
     EXPECT_EQ(99999, dim4.value_long());
 }
 
-TEST(AtomMatcherTest, TestWriteAtomToProto) {
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
-
-    // Set up the event
-    LogEvent event(4, 12345);
-    event.write(attribution_nodes);
-    event.write((int32_t)999);
-    // Convert to a LogEvent
-    event.init();
-
-    android::util::ProtoOutputStream protoOutput;
-    writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
-
-    vector<uint8_t> outData;
-    outData.resize(protoOutput.size());
-    size_t pos = 0;
-    sp<ProtoReader> reader = protoOutput.data();
-    while (reader->readBuffer() != NULL) {
-        size_t toRead = reader->currentToRead();
-        std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
-        pos += toRead;
-        reader->move(toRead);
-    }
-
-    Atom result;
-    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
-    EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
-    const auto& atom = result.ble_scan_result_received();
-    EXPECT_EQ(2, atom.attribution_node_size());
-    EXPECT_EQ(1111, atom.attribution_node(0).uid());
-    EXPECT_EQ("location1", atom.attribution_node(0).tag());
-    EXPECT_EQ(2222, atom.attribution_node(1).uid());
-    EXPECT_EQ("location2", atom.attribution_node(1).tag());
-    EXPECT_EQ(999, atom.num_results());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(AtomMatcherTest, TestWriteAtomToProto) {
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1111);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2};
+//
+//    // Set up the event
+//    LogEvent event(4, 12345);
+//    event.write(attribution_nodes);
+//    event.write((int32_t)999);
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    android::util::ProtoOutputStream protoOutput;
+//    writeFieldValueTreeToStream(event.GetTagId(), event.getValues(), &protoOutput);
+//
+//    vector<uint8_t> outData;
+//    outData.resize(protoOutput.size());
+//    size_t pos = 0;
+//    sp<ProtoReader> reader = protoOutput.data();
+//    while (reader->readBuffer() != NULL) {
+//        size_t toRead = reader->currentToRead();
+//        std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
+//        pos += toRead;
+//        reader->move(toRead);
+//    }
+//
+//    Atom result;
+//    EXPECT_EQ(true, result.ParseFromArray(&outData[0], outData.size()));
+//    EXPECT_EQ(Atom::PushedCase::kBleScanResultReceived, result.pushed_case());
+//    const auto& atom = result.ble_scan_result_received();
+//    EXPECT_EQ(2, atom.attribution_node_size());
+//    EXPECT_EQ(1111, atom.attribution_node(0).uid());
+//    EXPECT_EQ("location1", atom.attribution_node(0).tag());
+//    EXPECT_EQ(2222, atom.attribution_node(1).uid());
+//    EXPECT_EQ("location2", atom.attribution_node(1).tag());
+//    EXPECT_EQ(999, atom.num_results());
+//}
 
 /*
  * Test two Matchers is not a subset of one Matcher.
diff --git a/cmds/statsd/tests/LogEntryMatcher_test.cpp b/cmds/statsd/tests/LogEntryMatcher_test.cpp
index 441d3c8..2de6377 100644
--- a/cmds/statsd/tests/LogEntryMatcher_test.cpp
+++ b/cmds/statsd/tests/LogEntryMatcher_test.cpp
@@ -39,645 +39,646 @@
 
 
 #ifdef __ANDROID__
-TEST(AtomMatcherTest, TestSimpleMatcher) {
-    UidMap uidMap;
-
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-
-    LogEvent event(TAG_ID, 0);
-    EXPECT_TRUE(event.write(11));
-    event.init();
-
-    // Test
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Wrong tag id.
-    simpleMatcher->set_atom_id(TAG_ID + 1);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestAttributionMatcher) {
-    UidMap uidMap;
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    AttributionNodeInternal attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("location3");
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
-                                                              attribution_node3};
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(attribution_nodes);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-
-    // Match first node.
-    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
-    attributionMatcher->set_field(FIELD_ID_1);
-    attributionMatcher->set_position(Position::FIRST);
-    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
-        ATTRIBUTION_TAG_FIELD_ID);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("tag");
-
-    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
-    fieldMatcher->set_field(FIELD_ID_2);
-    fieldMatcher->set_eq_string("some value");
-
-    // Tag not matched.
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location3");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Match last node.
-    attributionMatcher->set_position(Position::LAST);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Match any node.
-    attributionMatcher->set_position(Position::ANY);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location2");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location4");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Attribution match but primitive field not match.
-    attributionMatcher->set_position(Position::ANY);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("location2");
-    fieldMatcher->set_eq_string("wrong value");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    fieldMatcher->set_eq_string("some value");
-
-    // Uid match.
-    attributionMatcher->set_position(Position::ANY);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_field(
-        ATTRIBUTION_UID_FIELD_ID);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("pkg0");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    uidMap.updateMap(
-            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
-            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
-             android::String16("v1"), android::String16("v2")},
-            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
-            {android::String16(""), android::String16(""), android::String16(""),
-             android::String16(""), android::String16("")});
-
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::FIRST);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::LAST);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Uid + tag.
-    attributionMatcher->set_position(Position::ANY);
-    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
-        ATTRIBUTION_TAG_FIELD_ID);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location2");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::FIRST);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location2");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::LAST);
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg0");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg1");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location2");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg2");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
-        ->set_eq_string("pkg3");
-    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
-        ->set_eq_string("location1");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestUidFieldMatcher) {
-    UidMap uidMap;
-    uidMap.updateMap(
-        1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
-        {android::String16("v1"), android::String16("v1"), android::String16("v2"),
-         android::String16("v1"), android::String16("v2")},
-        {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-         android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
-        {android::String16(""), android::String16(""), android::String16(""),
-         android::String16(""), android::String16("")});
-
-    // Set up matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-    simpleMatcher->add_field_value_matcher()->set_field(1);
-    simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("pkg0");
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(1111);
-    event.init();
-
-    LogEvent event2(TAG_ID_2, 0);
-    event2.write(1111);
-    event2.write("some value");
-    event2.init();
-
-    // Tag not in kAtomsWithUidField
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // Tag found in kAtomsWithUidField and has matching uid
-    simpleMatcher->set_atom_id(TAG_ID_2);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
-
-    // Tag found in kAtomsWithUidField but has non-matching uid
-    simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("Pkg2");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2));
-}
-
-TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
-    UidMap uidMap;
-    uidMap.updateMap(
-            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
-            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
-             android::String16("v1"), android::String16("v2")},
-            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
-            {android::String16(""), android::String16(""), android::String16(""),
-             android::String16(""), android::String16("")});
-
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1111);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    AttributionNodeInternal attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("location3");
-
-    AttributionNodeInternal attribution_node4;
-    attribution_node4.set_uid(1066);
-    attribution_node4.set_tag("location3");
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
-                                                              attribution_node3, attribution_node4};
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(attribution_nodes);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-
-    // Match first node.
-    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
-    attributionMatcher->set_field(FIELD_ID_1);
-    attributionMatcher->set_position(Position::FIRST);
-    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
-            ATTRIBUTION_UID_FIELD_ID);
-    auto neqStringList = attributionMatcher->mutable_matches_tuple()
-                                 ->mutable_field_value_matcher(0)
-                                 ->mutable_neq_any_string();
-    neqStringList->add_str_value("pkg2");
-    neqStringList->add_str_value("pkg3");
-
-    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
-    fieldMatcher->set_field(FIELD_ID_2);
-    fieldMatcher->set_eq_string("some value");
-
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    neqStringList->Clear();
-    neqStringList->add_str_value("pkg1");
-    neqStringList->add_str_value("pkg3");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::ANY);
-    neqStringList->Clear();
-    neqStringList->add_str_value("maps.com");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    neqStringList->Clear();
-    neqStringList->add_str_value("PkG3");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::LAST);
-    neqStringList->Clear();
-    neqStringList->add_str_value("AID_STATSD");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
-    UidMap uidMap;
-    uidMap.updateMap(
-            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
-            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
-             android::String16("v1"), android::String16("v2")},
-            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
-             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
-            {android::String16(""), android::String16(""), android::String16(""),
-             android::String16(""), android::String16("")});
-
-    AttributionNodeInternal attribution_node1;
-    attribution_node1.set_uid(1067);
-    attribution_node1.set_tag("location1");
-
-    AttributionNodeInternal attribution_node2;
-    attribution_node2.set_uid(2222);
-    attribution_node2.set_tag("location2");
-
-    AttributionNodeInternal attribution_node3;
-    attribution_node3.set_uid(3333);
-    attribution_node3.set_tag("location3");
-
-    AttributionNodeInternal attribution_node4;
-    attribution_node4.set_uid(1066);
-    attribution_node4.set_tag("location3");
-    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
-                                                              attribution_node3, attribution_node4};
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(attribution_nodes);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-
-    // Match first node.
-    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
-    attributionMatcher->set_field(FIELD_ID_1);
-    attributionMatcher->set_position(Position::FIRST);
-    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
-            ATTRIBUTION_UID_FIELD_ID);
-    auto eqStringList = attributionMatcher->mutable_matches_tuple()
-                                ->mutable_field_value_matcher(0)
-                                ->mutable_eq_any_string();
-    eqStringList->add_str_value("AID_ROOT");
-    eqStringList->add_str_value("AID_INCIDENTD");
-
-    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
-    fieldMatcher->set_field(FIELD_ID_2);
-    fieldMatcher->set_eq_string("some value");
-
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    attributionMatcher->set_position(Position::ANY);
-    eqStringList->Clear();
-    eqStringList->add_str_value("AID_STATSD");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    eqStringList->Clear();
-    eqStringList->add_str_value("pkg1");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    auto normalStringField = fieldMatcher->mutable_eq_any_string();
-    normalStringField->add_str_value("some value123");
-    normalStringField->add_str_value("some value");
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    normalStringField->Clear();
-    normalStringField->add_str_value("AID_STATSD");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    eqStringList->Clear();
-    eqStringList->add_str_value("maps.com");
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestBoolMatcher) {
-    UidMap uidMap;
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-    auto keyValue1 = simpleMatcher->add_field_value_matcher();
-    keyValue1->set_field(FIELD_ID_1);
-    auto keyValue2 = simpleMatcher->add_field_value_matcher();
-    keyValue2->set_field(FIELD_ID_2);
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    EXPECT_TRUE(event.write(true));
-    EXPECT_TRUE(event.write(false));
-    // Convert to a LogEvent
-    event.init();
-
-    // Test
-    keyValue1->set_eq_bool(true);
-    keyValue2->set_eq_bool(false);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    keyValue1->set_eq_bool(false);
-    keyValue2->set_eq_bool(false);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    keyValue1->set_eq_bool(false);
-    keyValue2->set_eq_bool(true);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    keyValue1->set_eq_bool(true);
-    keyValue2->set_eq_bool(true);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestStringMatcher) {
-    UidMap uidMap;
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-    auto keyValue = simpleMatcher->add_field_value_matcher();
-    keyValue->set_field(FIELD_ID_1);
-    keyValue->set_eq_string("some value");
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write("some value");
-    // Convert to a LogEvent
-    event.init();
-
-    // Test
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
-    UidMap uidMap;
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-    auto keyValue1 = simpleMatcher->add_field_value_matcher();
-    keyValue1->set_field(FIELD_ID_1);
-    auto keyValue2 = simpleMatcher->add_field_value_matcher();
-    keyValue2->set_field(FIELD_ID_2);
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(2);
-    event.write(3);
-
-    // Convert to a LogEvent
-    event.init();
-
-    // Test
-    keyValue1->set_eq_int(2);
-    keyValue2->set_eq_int(3);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    keyValue1->set_eq_int(2);
-    keyValue2->set_eq_int(4);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    keyValue1->set_eq_int(4);
-    keyValue2->set_eq_int(3);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestIntComparisonMatcher) {
-    UidMap uidMap;
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-
-    simpleMatcher->set_atom_id(TAG_ID);
-    auto keyValue = simpleMatcher->add_field_value_matcher();
-    keyValue->set_field(FIELD_ID_1);
-
-    // Set up the event
-    LogEvent event(TAG_ID, 0);
-    event.write(11);
-    event.init();
-
-    // Test
-
-    // eq_int
-    keyValue->set_eq_int(10);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_eq_int(11);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_eq_int(12);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // lt_int
-    keyValue->set_lt_int(10);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_lt_int(11);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_lt_int(12);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // lte_int
-    keyValue->set_lte_int(10);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_lte_int(11);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_lte_int(12);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // gt_int
-    keyValue->set_gt_int(10);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_gt_int(11);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_gt_int(12);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-
-    // gte_int
-    keyValue->set_gte_int(10);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_gte_int(11);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
-    keyValue->set_gte_int(12);
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
-}
-
-TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
-    UidMap uidMap;
-    // Set up the matcher
-    AtomMatcher matcher;
-    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
-    simpleMatcher->set_atom_id(TAG_ID);
-
-    auto keyValue = simpleMatcher->add_field_value_matcher();
-    keyValue->set_field(FIELD_ID_1);
-
-    LogEvent event1(TAG_ID, 0);
-    keyValue->set_lt_float(10.0);
-    event1.write(10.1f);
-    event1.init();
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1));
-
-    LogEvent event2(TAG_ID, 0);
-    event2.write(9.9f);
-    event2.init();
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
-
-    LogEvent event3(TAG_ID, 0);
-    event3.write(10.1f);
-    event3.init();
-    keyValue->set_gt_float(10.0);
-    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3));
-
-    LogEvent event4(TAG_ID, 0);
-    event4.write(9.9f);
-    event4.init();
-    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AtomMatcherTest, TestSimpleMatcher) {
+//    UidMap uidMap;
+//
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//
+//    LogEvent event(TAG_ID, 0);
+//    EXPECT_TRUE(event.write(11));
+//    event.init();
+//
+//    // Test
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Wrong tag id.
+//    simpleMatcher->set_atom_id(TAG_ID + 1);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestAttributionMatcher) {
+//    UidMap uidMap;
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1111);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    AttributionNodeInternal attribution_node3;
+//    attribution_node3.set_uid(3333);
+//    attribution_node3.set_tag("location3");
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+//                                                              attribution_node3};
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(attribution_nodes);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//
+//    // Match first node.
+//    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+//    attributionMatcher->set_field(FIELD_ID_1);
+//    attributionMatcher->set_position(Position::FIRST);
+//    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+//        ATTRIBUTION_TAG_FIELD_ID);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("tag");
+//
+//    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+//    fieldMatcher->set_field(FIELD_ID_2);
+//    fieldMatcher->set_eq_string("some value");
+//
+//    // Tag not matched.
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location3");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Match last node.
+//    attributionMatcher->set_position(Position::LAST);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Match any node.
+//    attributionMatcher->set_position(Position::ANY);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location2");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location4");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Attribution match but primitive field not match.
+//    attributionMatcher->set_position(Position::ANY);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("location2");
+//    fieldMatcher->set_eq_string("wrong value");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    fieldMatcher->set_eq_string("some value");
+//
+//    // Uid match.
+//    attributionMatcher->set_position(Position::ANY);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_field(
+//        ATTRIBUTION_UID_FIELD_ID);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)->set_eq_string("pkg0");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    uidMap.updateMap(
+//            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+//            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+//             android::String16("v1"), android::String16("v2")},
+//            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+//             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+//            {android::String16(""), android::String16(""), android::String16(""),
+//             android::String16(""), android::String16("")});
+//
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::FIRST);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::LAST);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Uid + tag.
+//    attributionMatcher->set_position(Position::ANY);
+//    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+//        ATTRIBUTION_TAG_FIELD_ID);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location2");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::FIRST);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location2");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::LAST);
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg0");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg1");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location2");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg2");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(0)
+//        ->set_eq_string("pkg3");
+//    attributionMatcher->mutable_matches_tuple()->mutable_field_value_matcher(1)
+//        ->set_eq_string("location1");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestUidFieldMatcher) {
+//    UidMap uidMap;
+//    uidMap.updateMap(
+//        1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+//        {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+//         android::String16("v1"), android::String16("v2")},
+//        {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+//         android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+//        {android::String16(""), android::String16(""), android::String16(""),
+//         android::String16(""), android::String16("")});
+//
+//    // Set up matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//    simpleMatcher->add_field_value_matcher()->set_field(1);
+//    simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("pkg0");
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(1111);
+//    event.init();
+//
+//    LogEvent event2(TAG_ID_2, 0);
+//    event2.write(1111);
+//    event2.write("some value");
+//    event2.init();
+//
+//    // Tag not in kAtomsWithUidField
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // Tag found in kAtomsWithUidField and has matching uid
+//    simpleMatcher->set_atom_id(TAG_ID_2);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
+//
+//    // Tag found in kAtomsWithUidField but has non-matching uid
+//    simpleMatcher->mutable_field_value_matcher(0)->set_eq_string("Pkg2");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event2));
+//}
+//
+//TEST(AtomMatcherTest, TestNeqAnyStringMatcher) {
+//    UidMap uidMap;
+//    uidMap.updateMap(
+//            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+//            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+//             android::String16("v1"), android::String16("v2")},
+//            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+//             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+//            {android::String16(""), android::String16(""), android::String16(""),
+//             android::String16(""), android::String16("")});
+//
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1111);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    AttributionNodeInternal attribution_node3;
+//    attribution_node3.set_uid(3333);
+//    attribution_node3.set_tag("location3");
+//
+//    AttributionNodeInternal attribution_node4;
+//    attribution_node4.set_uid(1066);
+//    attribution_node4.set_tag("location3");
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+//                                                              attribution_node3, attribution_node4};
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(attribution_nodes);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//
+//    // Match first node.
+//    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+//    attributionMatcher->set_field(FIELD_ID_1);
+//    attributionMatcher->set_position(Position::FIRST);
+//    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+//            ATTRIBUTION_UID_FIELD_ID);
+//    auto neqStringList = attributionMatcher->mutable_matches_tuple()
+//                                 ->mutable_field_value_matcher(0)
+//                                 ->mutable_neq_any_string();
+//    neqStringList->add_str_value("pkg2");
+//    neqStringList->add_str_value("pkg3");
+//
+//    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+//    fieldMatcher->set_field(FIELD_ID_2);
+//    fieldMatcher->set_eq_string("some value");
+//
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    neqStringList->Clear();
+//    neqStringList->add_str_value("pkg1");
+//    neqStringList->add_str_value("pkg3");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::ANY);
+//    neqStringList->Clear();
+//    neqStringList->add_str_value("maps.com");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    neqStringList->Clear();
+//    neqStringList->add_str_value("PkG3");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::LAST);
+//    neqStringList->Clear();
+//    neqStringList->add_str_value("AID_STATSD");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestEqAnyStringMatcher) {
+//    UidMap uidMap;
+//    uidMap.updateMap(
+//            1, {1111, 1111, 2222, 3333, 3333} /* uid list */, {1, 1, 2, 1, 2} /* version list */,
+//            {android::String16("v1"), android::String16("v1"), android::String16("v2"),
+//             android::String16("v1"), android::String16("v2")},
+//            {android::String16("pkg0"), android::String16("pkg1"), android::String16("pkg1"),
+//             android::String16("Pkg2"), android::String16("PkG3")} /* package name list */,
+//            {android::String16(""), android::String16(""), android::String16(""),
+//             android::String16(""), android::String16("")});
+//
+//    AttributionNodeInternal attribution_node1;
+//    attribution_node1.set_uid(1067);
+//    attribution_node1.set_tag("location1");
+//
+//    AttributionNodeInternal attribution_node2;
+//    attribution_node2.set_uid(2222);
+//    attribution_node2.set_tag("location2");
+//
+//    AttributionNodeInternal attribution_node3;
+//    attribution_node3.set_uid(3333);
+//    attribution_node3.set_tag("location3");
+//
+//    AttributionNodeInternal attribution_node4;
+//    attribution_node4.set_uid(1066);
+//    attribution_node4.set_tag("location3");
+//    std::vector<AttributionNodeInternal> attribution_nodes = {attribution_node1, attribution_node2,
+//                                                              attribution_node3, attribution_node4};
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(attribution_nodes);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//
+//    // Match first node.
+//    auto attributionMatcher = simpleMatcher->add_field_value_matcher();
+//    attributionMatcher->set_field(FIELD_ID_1);
+//    attributionMatcher->set_position(Position::FIRST);
+//    attributionMatcher->mutable_matches_tuple()->add_field_value_matcher()->set_field(
+//            ATTRIBUTION_UID_FIELD_ID);
+//    auto eqStringList = attributionMatcher->mutable_matches_tuple()
+//                                ->mutable_field_value_matcher(0)
+//                                ->mutable_eq_any_string();
+//    eqStringList->add_str_value("AID_ROOT");
+//    eqStringList->add_str_value("AID_INCIDENTD");
+//
+//    auto fieldMatcher = simpleMatcher->add_field_value_matcher();
+//    fieldMatcher->set_field(FIELD_ID_2);
+//    fieldMatcher->set_eq_string("some value");
+//
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    attributionMatcher->set_position(Position::ANY);
+//    eqStringList->Clear();
+//    eqStringList->add_str_value("AID_STATSD");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    eqStringList->Clear();
+//    eqStringList->add_str_value("pkg1");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    auto normalStringField = fieldMatcher->mutable_eq_any_string();
+//    normalStringField->add_str_value("some value123");
+//    normalStringField->add_str_value("some value");
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    normalStringField->Clear();
+//    normalStringField->add_str_value("AID_STATSD");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    eqStringList->Clear();
+//    eqStringList->add_str_value("maps.com");
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestBoolMatcher) {
+//    UidMap uidMap;
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//    auto keyValue1 = simpleMatcher->add_field_value_matcher();
+//    keyValue1->set_field(FIELD_ID_1);
+//    auto keyValue2 = simpleMatcher->add_field_value_matcher();
+//    keyValue2->set_field(FIELD_ID_2);
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    EXPECT_TRUE(event.write(true));
+//    EXPECT_TRUE(event.write(false));
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Test
+//    keyValue1->set_eq_bool(true);
+//    keyValue2->set_eq_bool(false);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    keyValue1->set_eq_bool(false);
+//    keyValue2->set_eq_bool(false);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    keyValue1->set_eq_bool(false);
+//    keyValue2->set_eq_bool(true);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    keyValue1->set_eq_bool(true);
+//    keyValue2->set_eq_bool(true);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestStringMatcher) {
+//    UidMap uidMap;
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//    auto keyValue = simpleMatcher->add_field_value_matcher();
+//    keyValue->set_field(FIELD_ID_1);
+//    keyValue->set_eq_string("some value");
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write("some value");
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Test
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestMultiFieldsMatcher) {
+//    UidMap uidMap;
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//    auto keyValue1 = simpleMatcher->add_field_value_matcher();
+//    keyValue1->set_field(FIELD_ID_1);
+//    auto keyValue2 = simpleMatcher->add_field_value_matcher();
+//    keyValue2->set_field(FIELD_ID_2);
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(2);
+//    event.write(3);
+//
+//    // Convert to a LogEvent
+//    event.init();
+//
+//    // Test
+//    keyValue1->set_eq_int(2);
+//    keyValue2->set_eq_int(3);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    keyValue1->set_eq_int(2);
+//    keyValue2->set_eq_int(4);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    keyValue1->set_eq_int(4);
+//    keyValue2->set_eq_int(3);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestIntComparisonMatcher) {
+//    UidMap uidMap;
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//
+//    simpleMatcher->set_atom_id(TAG_ID);
+//    auto keyValue = simpleMatcher->add_field_value_matcher();
+//    keyValue->set_field(FIELD_ID_1);
+//
+//    // Set up the event
+//    LogEvent event(TAG_ID, 0);
+//    event.write(11);
+//    event.init();
+//
+//    // Test
+//
+//    // eq_int
+//    keyValue->set_eq_int(10);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_eq_int(11);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_eq_int(12);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // lt_int
+//    keyValue->set_lt_int(10);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_lt_int(11);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_lt_int(12);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // lte_int
+//    keyValue->set_lte_int(10);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_lte_int(11);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_lte_int(12);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // gt_int
+//    keyValue->set_gt_int(10);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_gt_int(11);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_gt_int(12);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//
+//    // gte_int
+//    keyValue->set_gte_int(10);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_gte_int(11);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event));
+//    keyValue->set_gte_int(12);
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event));
+//}
+//
+//TEST(AtomMatcherTest, TestFloatComparisonMatcher) {
+//    UidMap uidMap;
+//    // Set up the matcher
+//    AtomMatcher matcher;
+//    auto simpleMatcher = matcher.mutable_simple_atom_matcher();
+//    simpleMatcher->set_atom_id(TAG_ID);
+//
+//    auto keyValue = simpleMatcher->add_field_value_matcher();
+//    keyValue->set_field(FIELD_ID_1);
+//
+//    LogEvent event1(TAG_ID, 0);
+//    keyValue->set_lt_float(10.0);
+//    event1.write(10.1f);
+//    event1.init();
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event1));
+//
+//    LogEvent event2(TAG_ID, 0);
+//    event2.write(9.9f);
+//    event2.init();
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event2));
+//
+//    LogEvent event3(TAG_ID, 0);
+//    event3.write(10.1f);
+//    event3.init();
+//    keyValue->set_gt_float(10.0);
+//    EXPECT_TRUE(matchesSimple(uidMap, *simpleMatcher, event3));
+//
+//    LogEvent event4(TAG_ID, 0);
+//    event4.write(9.9f);
+//    event4.init();
+//    EXPECT_FALSE(matchesSimple(uidMap, *simpleMatcher, event4));
+//}
 
 // Helper for the composite matchers.
 void addSimpleMatcher(SimpleAtomMatcher* simpleMatcher, int tag, int key, int val) {
diff --git a/cmds/statsd/tests/LogEvent_test.cpp b/cmds/statsd/tests/LogEvent_test.cpp
index f624e12..7542faf 100644
--- a/cmds/statsd/tests/LogEvent_test.cpp
+++ b/cmds/statsd/tests/LogEvent_test.cpp
@@ -31,9 +31,6 @@
 using util::ProtoOutputStream;
 using util::ProtoReader;
 
-
-#ifdef NEW_ENCODING_SCHEME
-
 Field getField(int32_t tag, const vector<int32_t>& pos, int32_t depth, const vector<bool>& last) {
     Field f(tag, (int32_t*)pos.data(), depth);
 
@@ -241,480 +238,6 @@
     AStatsEvent_release(event);
 }
 
-#else // NEW_ENCODING_SCHEME
-
-TEST(LogEventTest, TestLogParsing) {
-    LogEvent event1(1, 2000);
-
-    std::vector<AttributionNodeInternal> nodes;
-
-    AttributionNodeInternal node1;
-    node1.set_uid(1000);
-    node1.set_tag("tag1");
-    nodes.push_back(node1);
-
-    AttributionNodeInternal node2;
-    node2.set_uid(2000);
-    node2.set_tag("tag2");
-    nodes.push_back(node2);
-
-    event1.write(nodes);
-    event1.write("hello");
-    event1.write((int32_t)10);
-    event1.write((int64_t)20);
-    event1.write((float)1.1);
-    event1.init();
-
-    const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)8, items.size());
-    EXPECT_EQ(1, event1.GetTagId());
-
-    const FieldValue& item0 = event1.getValues()[0];
-    EXPECT_EQ(0x2010101, item0.mField.getField());
-    EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(1000, item0.mValue.int_value);
-
-    const FieldValue& item1 = event1.getValues()[1];
-    EXPECT_EQ(0x2010182, item1.mField.getField());
-    EXPECT_EQ(Type::STRING, item1.mValue.getType());
-    EXPECT_EQ("tag1", item1.mValue.str_value);
-
-    const FieldValue& item2 = event1.getValues()[2];
-    EXPECT_EQ(0x2018201, item2.mField.getField());
-    EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(2000, item2.mValue.int_value);
-
-    const FieldValue& item3 = event1.getValues()[3];
-    EXPECT_EQ(0x2018282, item3.mField.getField());
-    EXPECT_EQ(Type::STRING, item3.mValue.getType());
-    EXPECT_EQ("tag2", item3.mValue.str_value);
-
-    const FieldValue& item4 = event1.getValues()[4];
-    EXPECT_EQ(0x20000, item4.mField.getField());
-    EXPECT_EQ(Type::STRING, item4.mValue.getType());
-    EXPECT_EQ("hello", item4.mValue.str_value);
-
-    const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x30000, item5.mField.getField());
-    EXPECT_EQ(Type::INT, item5.mValue.getType());
-    EXPECT_EQ(10, item5.mValue.int_value);
-
-    const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x40000, item6.mField.getField());
-    EXPECT_EQ(Type::LONG, item6.mValue.getType());
-    EXPECT_EQ((int64_t)20, item6.mValue.long_value);
-
-    const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x50000, item7.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
-    EXPECT_EQ((float)1.1, item7.mValue.float_value);
-}
-
-TEST(LogEventTest, TestKeyValuePairsAtomParsing) {
-    LogEvent event1(83, 2000, 1000);
-    std::map<int32_t, int32_t> int_map;
-    std::map<int32_t, int64_t> long_map;
-    std::map<int32_t, std::string> string_map;
-    std::map<int32_t, float> float_map;
-
-    int_map[11] = 123;
-    int_map[22] = 345;
-
-    long_map[33] = 678L;
-    long_map[44] = 890L;
-
-    string_map[1] = "test2";
-    string_map[2] = "test1";
-
-    float_map[111] = 2.2f;
-    float_map[222] = 1.1f;
-
-    EXPECT_TRUE(event1.writeKeyValuePairs(0, // Logging side logs 0 uid.
-                                          int_map,
-                                          long_map,
-                                          string_map,
-                                          float_map));
-    event1.init();
-
-    EXPECT_EQ(83, event1.GetTagId());
-    const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)17, items.size());
-
-    const FieldValue& item0 = event1.getValues()[0];
-    EXPECT_EQ(0x10000, item0.mField.getField());
-    EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(1000, item0.mValue.int_value);
-
-    const FieldValue& item1 = event1.getValues()[1];
-    EXPECT_EQ(0x2010201, item1.mField.getField());
-    EXPECT_EQ(Type::INT, item1.mValue.getType());
-    EXPECT_EQ(11, item1.mValue.int_value);
-
-    const FieldValue& item2 = event1.getValues()[2];
-    EXPECT_EQ(0x2010282, item2.mField.getField());
-    EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(123, item2.mValue.int_value);
-
-    const FieldValue& item3 = event1.getValues()[3];
-    EXPECT_EQ(0x2010301, item3.mField.getField());
-    EXPECT_EQ(Type::INT, item3.mValue.getType());
-    EXPECT_EQ(22, item3.mValue.int_value);
-
-    const FieldValue& item4 = event1.getValues()[4];
-    EXPECT_EQ(0x2010382, item4.mField.getField());
-    EXPECT_EQ(Type::INT, item4.mValue.getType());
-    EXPECT_EQ(345, item4.mValue.int_value);
-
-    const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x2010401, item5.mField.getField());
-    EXPECT_EQ(Type::INT, item5.mValue.getType());
-    EXPECT_EQ(33, item5.mValue.int_value);
-
-    const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x2010483, item6.mField.getField());
-    EXPECT_EQ(Type::LONG, item6.mValue.getType());
-    EXPECT_EQ(678L, item6.mValue.int_value);
-
-    const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x2010501, item7.mField.getField());
-    EXPECT_EQ(Type::INT, item7.mValue.getType());
-    EXPECT_EQ(44, item7.mValue.int_value);
-
-    const FieldValue& item8 = event1.getValues()[8];
-    EXPECT_EQ(0x2010583, item8.mField.getField());
-    EXPECT_EQ(Type::LONG, item8.mValue.getType());
-    EXPECT_EQ(890L, item8.mValue.int_value);
-
-    const FieldValue& item9 = event1.getValues()[9];
-    EXPECT_EQ(0x2010601, item9.mField.getField());
-    EXPECT_EQ(Type::INT, item9.mValue.getType());
-    EXPECT_EQ(1, item9.mValue.int_value);
-
-    const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2010684, item10.mField.getField());
-    EXPECT_EQ(Type::STRING, item10.mValue.getType());
-    EXPECT_EQ("test2", item10.mValue.str_value);
-
-    const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2010701, item11.mField.getField());
-    EXPECT_EQ(Type::INT, item11.mValue.getType());
-    EXPECT_EQ(2, item11.mValue.int_value);
-
-    const FieldValue& item12 = event1.getValues()[12];
-    EXPECT_EQ(0x2010784, item12.mField.getField());
-    EXPECT_EQ(Type::STRING, item12.mValue.getType());
-    EXPECT_EQ("test1", item12.mValue.str_value);
-
-    const FieldValue& item13 = event1.getValues()[13];
-    EXPECT_EQ(0x2010801, item13.mField.getField());
-    EXPECT_EQ(Type::INT, item13.mValue.getType());
-    EXPECT_EQ(111, item13.mValue.int_value);
-
-    const FieldValue& item14 = event1.getValues()[14];
-    EXPECT_EQ(0x2010885, item14.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
-    EXPECT_EQ(2.2f, item14.mValue.float_value);
-
-    const FieldValue& item15 = event1.getValues()[15];
-    EXPECT_EQ(0x2018901, item15.mField.getField());
-    EXPECT_EQ(Type::INT, item15.mValue.getType());
-    EXPECT_EQ(222, item15.mValue.int_value);
-
-    const FieldValue& item16 = event1.getValues()[16];
-    EXPECT_EQ(0x2018985, item16.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
-    EXPECT_EQ(1.1f, item16.mValue.float_value);
-}
-
-TEST(LogEventTest, TestLogParsing2) {
-    LogEvent event1(1, 2000);
-
-    std::vector<AttributionNodeInternal> nodes;
-
-    event1.write("hello");
-
-    // repeated msg can be in the middle
-    AttributionNodeInternal node1;
-    node1.set_uid(1000);
-    node1.set_tag("tag1");
-    nodes.push_back(node1);
-
-    AttributionNodeInternal node2;
-    node2.set_uid(2000);
-    node2.set_tag("tag2");
-    nodes.push_back(node2);
-    event1.write(nodes);
-
-    event1.write((int32_t)10);
-    event1.write((int64_t)20);
-    event1.write((float)1.1);
-    event1.init();
-
-    const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)8, items.size());
-    EXPECT_EQ(1, event1.GetTagId());
-
-    const FieldValue& item = event1.getValues()[0];
-    EXPECT_EQ(0x00010000, item.mField.getField());
-    EXPECT_EQ(Type::STRING, item.mValue.getType());
-    EXPECT_EQ("hello", item.mValue.str_value);
-
-    const FieldValue& item0 = event1.getValues()[1];
-    EXPECT_EQ(0x2020101, item0.mField.getField());
-    EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(1000, item0.mValue.int_value);
-
-    const FieldValue& item1 = event1.getValues()[2];
-    EXPECT_EQ(0x2020182, item1.mField.getField());
-    EXPECT_EQ(Type::STRING, item1.mValue.getType());
-    EXPECT_EQ("tag1", item1.mValue.str_value);
-
-    const FieldValue& item2 = event1.getValues()[3];
-    EXPECT_EQ(0x2028201, item2.mField.getField());
-    EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(2000, item2.mValue.int_value);
-
-    const FieldValue& item3 = event1.getValues()[4];
-    EXPECT_EQ(0x2028282, item3.mField.getField());
-    EXPECT_EQ(Type::STRING, item3.mValue.getType());
-    EXPECT_EQ("tag2", item3.mValue.str_value);
-
-    const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x30000, item5.mField.getField());
-    EXPECT_EQ(Type::INT, item5.mValue.getType());
-    EXPECT_EQ(10, item5.mValue.int_value);
-
-    const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x40000, item6.mField.getField());
-    EXPECT_EQ(Type::LONG, item6.mValue.getType());
-    EXPECT_EQ((int64_t)20, item6.mValue.long_value);
-
-    const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x50000, item7.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item7.mValue.getType());
-    EXPECT_EQ((float)1.1, item7.mValue.float_value);
-}
-
-TEST(LogEventTest, TestKeyValuePairsEvent) {
-    std::map<int32_t, int32_t> int_map;
-    std::map<int32_t, int64_t> long_map;
-    std::map<int32_t, std::string> string_map;
-    std::map<int32_t, float> float_map;
-
-    int_map[11] = 123;
-    int_map[22] = 345;
-
-    long_map[33] = 678L;
-    long_map[44] = 890L;
-
-    string_map[1] = "test2";
-    string_map[2] = "test1";
-
-    float_map[111] = 2.2f;
-    float_map[222] = 1.1f;
-
-    LogEvent event1(83, 2000, 2001, 10001, int_map, long_map, string_map, float_map);
-    event1.init();
-
-    EXPECT_EQ(83, event1.GetTagId());
-    EXPECT_EQ((int64_t)2000, event1.GetLogdTimestampNs());
-    EXPECT_EQ((int64_t)2001, event1.GetElapsedTimestampNs());
-    EXPECT_EQ((int64_t)10001, event1.GetUid());
-
-    const auto& items = event1.getValues();
-    EXPECT_EQ((size_t)17, items.size());
-
-    const FieldValue& item0 = event1.getValues()[0];
-    EXPECT_EQ(0x00010000, item0.mField.getField());
-    EXPECT_EQ(Type::INT, item0.mValue.getType());
-    EXPECT_EQ(10001, item0.mValue.int_value);
-
-    const FieldValue& item1 = event1.getValues()[1];
-    EXPECT_EQ(0x2020101, item1.mField.getField());
-    EXPECT_EQ(Type::INT, item1.mValue.getType());
-    EXPECT_EQ(11, item1.mValue.int_value);
-
-    const FieldValue& item2 = event1.getValues()[2];
-    EXPECT_EQ(0x2020182, item2.mField.getField());
-    EXPECT_EQ(Type::INT, item2.mValue.getType());
-    EXPECT_EQ(123, item2.mValue.int_value);
-
-    const FieldValue& item3 = event1.getValues()[3];
-    EXPECT_EQ(0x2020201, item3.mField.getField());
-    EXPECT_EQ(Type::INT, item3.mValue.getType());
-    EXPECT_EQ(22, item3.mValue.int_value);
-
-    const FieldValue& item4 = event1.getValues()[4];
-    EXPECT_EQ(0x2020282, item4.mField.getField());
-    EXPECT_EQ(Type::INT, item4.mValue.getType());
-    EXPECT_EQ(345, item4.mValue.int_value);
-
-    const FieldValue& item5 = event1.getValues()[5];
-    EXPECT_EQ(0x2020301, item5.mField.getField());
-    EXPECT_EQ(Type::INT, item5.mValue.getType());
-    EXPECT_EQ(33, item5.mValue.int_value);
-
-    const FieldValue& item6 = event1.getValues()[6];
-    EXPECT_EQ(0x2020383, item6.mField.getField());
-    EXPECT_EQ(Type::LONG, item6.mValue.getType());
-    EXPECT_EQ(678L, item6.mValue.long_value);
-
-    const FieldValue& item7 = event1.getValues()[7];
-    EXPECT_EQ(0x2020401, item7.mField.getField());
-    EXPECT_EQ(Type::INT, item7.mValue.getType());
-    EXPECT_EQ(44, item7.mValue.int_value);
-
-    const FieldValue& item8 = event1.getValues()[8];
-    EXPECT_EQ(0x2020483, item8.mField.getField());
-    EXPECT_EQ(Type::LONG, item8.mValue.getType());
-    EXPECT_EQ(890L, item8.mValue.long_value);
-
-    const FieldValue& item9 = event1.getValues()[9];
-    EXPECT_EQ(0x2020501, item9.mField.getField());
-    EXPECT_EQ(Type::INT, item9.mValue.getType());
-    EXPECT_EQ(1, item9.mValue.int_value);
-
-    const FieldValue& item10 = event1.getValues()[10];
-    EXPECT_EQ(0x2020584, item10.mField.getField());
-    EXPECT_EQ(Type::STRING, item10.mValue.getType());
-    EXPECT_EQ("test2", item10.mValue.str_value);
-
-    const FieldValue& item11 = event1.getValues()[11];
-    EXPECT_EQ(0x2020601, item11.mField.getField());
-    EXPECT_EQ(Type::INT, item11.mValue.getType());
-    EXPECT_EQ(2, item11.mValue.int_value);
-
-    const FieldValue& item12 = event1.getValues()[12];
-    EXPECT_EQ(0x2020684, item12.mField.getField());
-    EXPECT_EQ(Type::STRING, item12.mValue.getType());
-    EXPECT_EQ("test1", item12.mValue.str_value);
-
-    const FieldValue& item13 = event1.getValues()[13];
-    EXPECT_EQ(0x2020701, item13.mField.getField());
-    EXPECT_EQ(Type::INT, item13.mValue.getType());
-    EXPECT_EQ(111, item13.mValue.int_value);
-
-    const FieldValue& item14 = event1.getValues()[14];
-    EXPECT_EQ(0x2020785, item14.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item14.mValue.getType());
-    EXPECT_EQ(2.2f, item14.mValue.float_value);
-
-    const FieldValue& item15 = event1.getValues()[15];
-    EXPECT_EQ(0x2028801, item15.mField.getField());
-    EXPECT_EQ(Type::INT, item15.mValue.getType());
-    EXPECT_EQ(222, item15.mValue.int_value);
-
-    const FieldValue& item16 = event1.getValues()[16];
-    EXPECT_EQ(0x2028885, item16.mField.getField());
-    EXPECT_EQ(Type::FLOAT, item16.mValue.getType());
-    EXPECT_EQ(1.1f, item16.mValue.float_value);
-}
-
-TEST(LogEventTest, TestBinaryFieldAtom) {
-    Atom launcherAtom;
-    auto launcher_event = launcherAtom.mutable_launcher_event();
-    launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
-    launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
-    launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
-
-    auto extension = launcher_event->mutable_extension();
-
-    auto src_target = extension->add_src_target();
-    src_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
-    src_target->set_item(stats::launcher::LauncherTarget_Item_FOLDER_ICON);
-
-    auto dst_target = extension->add_dst_target();
-    dst_target->set_type(stats::launcher::LauncherTarget_Type_ITEM_TYPE);
-    dst_target->set_item(stats::launcher::LauncherTarget_Item_WIDGET);
-
-    string extension_str;
-    extension->SerializeToString(&extension_str);
-
-    LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
-
-    event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
-    event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
-    event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
-    event1.writeBytes(extension_str);
-    event1.init();
-
-    ProtoOutputStream proto;
-    event1.ToProto(proto);
-
-    std::vector<uint8_t> outData;
-    outData.resize(proto.size());
-    size_t pos = 0;
-    sp<ProtoReader> reader = proto.data();
-    while (reader->readBuffer() != NULL) {
-        size_t toRead = reader->currentToRead();
-        std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
-        pos += toRead;
-        reader->move(toRead);
-    }
-
-    std::string result_str(outData.begin(), outData.end());
-    std::string orig_str;
-    launcherAtom.SerializeToString(&orig_str);
-
-    EXPECT_EQ(orig_str, result_str);
-}
-
-TEST(LogEventTest, TestBinaryFieldAtom_empty) {
-    Atom launcherAtom;
-    auto launcher_event = launcherAtom.mutable_launcher_event();
-    launcher_event->set_action(stats::launcher::LauncherAction::LONGPRESS);
-    launcher_event->set_src_state(stats::launcher::LauncherState::OVERVIEW);
-    launcher_event->set_dst_state(stats::launcher::LauncherState::ALLAPPS);
-
-    // empty string.
-    string extension_str;
-
-    LogEvent event1(Atom::kLauncherEventFieldNumber, 1000);
-
-    event1.write((int32_t)stats::launcher::LauncherAction::LONGPRESS);
-    event1.write((int32_t)stats::launcher::LauncherState::OVERVIEW);
-    event1.write((int64_t)stats::launcher::LauncherState::ALLAPPS);
-    event1.writeBytes(extension_str);
-    event1.init();
-
-    ProtoOutputStream proto;
-    event1.ToProto(proto);
-
-    std::vector<uint8_t> outData;
-    outData.resize(proto.size());
-    size_t pos = 0;
-    sp<ProtoReader> reader = proto.data();
-    while (reader->readBuffer() != NULL) {
-        size_t toRead = reader->currentToRead();
-        std::memcpy(&(outData[pos]), reader->readBuffer(), toRead);
-        pos += toRead;
-        reader->move(toRead);
-    }
-
-    std::string result_str(outData.begin(), outData.end());
-    std::string orig_str;
-    launcherAtom.SerializeToString(&orig_str);
-
-    EXPECT_EQ(orig_str, result_str);
-}
-
-TEST(LogEventTest, TestWriteExperimentIdsToProto) {
-    std::vector<int64_t> expIds;
-    expIds.push_back(5038);
-    std::vector<uint8_t> proto;
-
-    writeExperimentIdsToProto(expIds, &proto);
-
-    EXPECT_EQ(proto.size(), 3);
-    // Proto wire format for field ID 1, varint
-    EXPECT_EQ(proto[0], 0x08);
-    // varint of 5038, 2 bytes long
-    EXPECT_EQ(proto[1], 0xae);
-    EXPECT_EQ(proto[2], 0x27);
-}
-#endif // NEW_ENCODING_SCHEME
-
-
 }  // namespace statsd
 }  // namespace os
 }  // namespace android
diff --git a/cmds/statsd/tests/StatsLogProcessor_test.cpp b/cmds/statsd/tests/StatsLogProcessor_test.cpp
index 3d7e5c9..81d6f72 100644
--- a/cmds/statsd/tests/StatsLogProcessor_test.cpp
+++ b/cmds/statsd/tests/StatsLogProcessor_test.cpp
@@ -253,1415 +253,1416 @@
     EXPECT_EQ(2, report.annotation(0).field_int32());
 }
 
-TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
-    // Setup a simple config.
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    *config.add_atom_matcher() = wakelockAcquireMatcher;
-
-    auto countMetric = config.add_count_metric();
-    countMetric->set_id(123456);
-    countMetric->set_what(wakelockAcquireMatcher.id());
-    countMetric->set_bucket(FIVE_MINUTES);
-
-    ConfigKey cfgKey;
-    sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
-
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 2);
-    processor->OnLogEvent(event.get());
-
-    vector<uint8_t> bytes;
-    ConfigMetricsReportList output;
-
-    // Dump report WITHOUT erasing data.
-    processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
-    output.ParseFromArray(bytes.data(), bytes.size());
-    EXPECT_EQ(output.reports_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
-
-    // Dump report WITH erasing data. There should be data since we didn't previously erase it.
-    processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
-    output.ParseFromArray(bytes.data(), bytes.size());
-    EXPECT_EQ(output.reports_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics_size(), 1);
-    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
-
-    // Dump report again. There should be no data since we erased it.
-    processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
-    output.ParseFromArray(bytes.data(), bytes.size());
-    // We don't care whether statsd has a report, as long as it has no count metrics in it.
-    bool noData = output.reports_size() == 0
-            || output.reports(0).metrics_size() == 0
-            || output.reports(0).metrics(0).count_metrics().data_size() == 0;
-    EXPECT_TRUE(noData);
-}
-
-TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
-    int uid = 1111;
-
-    // Setup a simple config, no activation
-    StatsdConfig config1;
-    int64_t cfgId1 = 12341;
-    config1.set_id(cfgId1);
-    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    *config1.add_atom_matcher() = wakelockAcquireMatcher;
-
-    long metricId1 = 1234561;
-    long metricId2 = 1234562;
-    auto countMetric1 = config1.add_count_metric();
-    countMetric1->set_id(metricId1);
-    countMetric1->set_what(wakelockAcquireMatcher.id());
-    countMetric1->set_bucket(FIVE_MINUTES);
-
-    auto countMetric2 = config1.add_count_metric();
-    countMetric2->set_id(metricId2);
-    countMetric2->set_what(wakelockAcquireMatcher.id());
-    countMetric2->set_bucket(FIVE_MINUTES);
-
-    ConfigKey cfgKey1(uid, cfgId1);
-
-    // Add another config, with two metrics, one with activation
-    StatsdConfig config2;
-    int64_t cfgId2 = 12342;
-    config2.set_id(cfgId2);
-    config2.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    *config2.add_atom_matcher() = wakelockAcquireMatcher;
-
-    long metricId3 = 1234561;
-    long metricId4 = 1234562;
-
-    auto countMetric3 = config2.add_count_metric();
-    countMetric3->set_id(metricId3);
-    countMetric3->set_what(wakelockAcquireMatcher.id());
-    countMetric3->set_bucket(FIVE_MINUTES);
-
-    auto countMetric4 = config2.add_count_metric();
-    countMetric4->set_id(metricId4);
-    countMetric4->set_what(wakelockAcquireMatcher.id());
-    countMetric4->set_bucket(FIVE_MINUTES);
-
-    auto metric3Activation = config2.add_metric_activation();
-    metric3Activation->set_metric_id(metricId3);
-    metric3Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
-    auto metric3ActivationTrigger = metric3Activation->add_event_activation();
-    metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric3ActivationTrigger->set_ttl_seconds(100);
-
-    ConfigKey cfgKey2(uid, cfgId2);
-
-    // Add another config, with two metrics, both with activations
-    StatsdConfig config3;
-    int64_t cfgId3 = 12343;
-    config3.set_id(cfgId3);
-    config3.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    *config3.add_atom_matcher() = wakelockAcquireMatcher;
-
-    long metricId5 = 1234565;
-    long metricId6 = 1234566;
-    auto countMetric5 = config3.add_count_metric();
-    countMetric5->set_id(metricId5);
-    countMetric5->set_what(wakelockAcquireMatcher.id());
-    countMetric5->set_bucket(FIVE_MINUTES);
-
-    auto countMetric6 = config3.add_count_metric();
-    countMetric6->set_id(metricId6);
-    countMetric6->set_what(wakelockAcquireMatcher.id());
-    countMetric6->set_bucket(FIVE_MINUTES);
-
-    auto metric5Activation = config3.add_metric_activation();
-    metric5Activation->set_metric_id(metricId5);
-    metric5Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
-    auto metric5ActivationTrigger = metric5Activation->add_event_activation();
-    metric5ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric5ActivationTrigger->set_ttl_seconds(100);
-
-    auto metric6Activation = config3.add_metric_activation();
-    metric6Activation->set_metric_id(metricId6);
-    metric6Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
-    auto metric6ActivationTrigger = metric6Activation->add_event_activation();
-    metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric6ActivationTrigger->set_ttl_seconds(200);
-
-    ConfigKey cfgKey3(uid, cfgId3);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            timeBase1, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(1, cfgKey1, config1);
-    processor.OnConfigUpdated(2, cfgKey2, config2);
-    processor.OnConfigUpdated(3, cfgKey3, config3);
-
-    EXPECT_EQ(3, processor.mMetricsManagers.size());
-
-    // Expect the first config and both metrics in it to be active.
-    auto it = processor.mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor.mMetricsManagers.end());
-    auto& metricsManager1 = it->second;
-    EXPECT_TRUE(metricsManager1->isActive());
-
-    auto metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer1 = *metricIt;
-    EXPECT_TRUE(metricProducer1->isActive());
-
-    metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer2 = *metricIt;
-    EXPECT_TRUE(metricProducer2->isActive());
-
-    // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active.
-    it = processor.mMetricsManagers.find(cfgKey2);
-    EXPECT_TRUE(it != processor.mMetricsManagers.end());
-    auto& metricsManager2 = it->second;
-    EXPECT_TRUE(metricsManager2->isActive());
-
-    metricIt = metricsManager2->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId3) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
-    auto& metricProducer3 = *metricIt;
-    EXPECT_FALSE(metricProducer3->isActive());
-
-    metricIt = metricsManager2->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId4) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
-    auto& metricProducer4 = *metricIt;
-    EXPECT_TRUE(metricProducer4->isActive());
-
-    // Expect the third config and both metrics in it to be inactive.
-    it = processor.mMetricsManagers.find(cfgKey3);
-    EXPECT_TRUE(it != processor.mMetricsManagers.end());
-    auto& metricsManager3 = it->second;
-    EXPECT_FALSE(metricsManager3->isActive());
-
-    metricIt = metricsManager3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId5) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
-    auto& metricProducer5 = *metricIt;
-    EXPECT_FALSE(metricProducer5->isActive());
-
-    metricIt = metricsManager3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId6) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
-    auto& metricProducer6 = *metricIt;
-    EXPECT_FALSE(metricProducer6->isActive());
-
-    // No broadcast for active configs should have happened yet.
-    EXPECT_EQ(broadcastCount, 0);
-
-    // Activate all 3 metrics that were not active.
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor.OnLogEvent(event.get());
-
-    // Assert that all 3 configs are active.
-    EXPECT_TRUE(metricsManager1->isActive());
-    EXPECT_TRUE(metricsManager2->isActive());
-    EXPECT_TRUE(metricsManager3->isActive());
-
-    // A broadcast should have happened, and all 3 configs should be active in the broadcast.
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 3);
-    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1)
-            != activeConfigsBroadcast.end());
-    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2)
-            != activeConfigsBroadcast.end());
-    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3)
-            != activeConfigsBroadcast.end());
-
-    // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns.
-    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor.SaveActiveConfigsToDisk(shutDownTime);
-    const int64_t ttl3 = event->GetElapsedTimestampNs() +
-            metric3ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
-    const int64_t ttl5 = event->GetElapsedTimestampNs() +
-            metric5ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
-    const int64_t ttl6 = event->GetElapsedTimestampNs() +
-            metric6ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
-
-    // Create a second StatsLogProcessor and push the same 3 configs.
-    long timeBase2 = 1000;
-    sp<StatsLogProcessor> processor2 =
-            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-    processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
-    processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
-
-    EXPECT_EQ(3, processor2->mMetricsManagers.size());
-
-    // First config and both metrics are active.
-    it = processor2->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1001 = it->second;
-    EXPECT_TRUE(metricsManager1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1001 = *metricIt;
-    EXPECT_TRUE(metricProducer1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1002 = *metricIt;
-    EXPECT_TRUE(metricProducer1002->isActive());
-
-    // Second config is active. Metric 3 is inactive, metric 4 is active.
-    it = processor2->mMetricsManagers.find(cfgKey2);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1002 = it->second;
-    EXPECT_TRUE(metricsManager1002->isActive());
-
-    metricIt = metricsManager1002->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId3) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
-    auto& metricProducer1003 = *metricIt;
-    EXPECT_FALSE(metricProducer1003->isActive());
-
-    metricIt = metricsManager1002->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId4) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
-    auto& metricProducer1004 = *metricIt;
-    EXPECT_TRUE(metricProducer1004->isActive());
-
-    // Config 3 is inactive. both metrics are inactive.
-    it = processor2->mMetricsManagers.find(cfgKey3);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1003 = it->second;
-    EXPECT_FALSE(metricsManager1003->isActive());
-    EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
-
-    metricIt = metricsManager1003->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId5) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
-    auto& metricProducer1005 = *metricIt;
-    EXPECT_FALSE(metricProducer1005->isActive());
-
-    metricIt = metricsManager1003->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1003->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId6) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
-    auto& metricProducer1006 = *metricIt;
-    EXPECT_FALSE(metricProducer1006->isActive());
-
-    // Assert that all 3 metrics with activation are inactive and that the ttls were properly set.
-    EXPECT_FALSE(metricProducer1003->isActive());
-    const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second;
-    EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
-    EXPECT_EQ(0, activation1003->start_ns);
-    EXPECT_FALSE(metricProducer1005->isActive());
-    const auto& activation1005 = metricProducer1005->mEventActivationMap.begin()->second;
-    EXPECT_EQ(100 * NS_PER_SEC, activation1005->ttl_ns);
-    EXPECT_EQ(0, activation1005->start_ns);
-    EXPECT_FALSE(metricProducer1006->isActive());
-    const auto& activation1006 = metricProducer1006->mEventActivationMap.begin()->second;
-    EXPECT_EQ(200 * NS_PER_SEC, activation1006->ttl_ns);
-    EXPECT_EQ(0, activation1006->start_ns);
-
-    processor2->LoadActiveConfigsFromDisk();
-
-    // After loading activations from disk, assert that all 3 metrics are active.
-    EXPECT_TRUE(metricProducer1003->isActive());
-    EXPECT_EQ(timeBase2 + ttl3 - activation1003->ttl_ns, activation1003->start_ns);
-    EXPECT_TRUE(metricProducer1005->isActive());
-    EXPECT_EQ(timeBase2 + ttl5 - activation1005->ttl_ns, activation1005->start_ns);
-    EXPECT_TRUE(metricProducer1006->isActive());
-    EXPECT_EQ(timeBase2 + ttl6 - activation1006->ttl_ns, activation1003->start_ns);
-
-    // Make sure no more broadcasts have happened.
-    EXPECT_EQ(broadcastCount, 1);
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBoot) {
-    int uid = 1111;
-
-    StatsdConfig config1;
-    config1.set_id(12341);
-    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    *config1.add_atom_matcher() = wakelockAcquireMatcher;
-
-    long metricId1 = 1234561;
-    long metricId2 = 1234562;
-    auto countMetric1 = config1.add_count_metric();
-    countMetric1->set_id(metricId1);
-    countMetric1->set_what(wakelockAcquireMatcher.id());
-    countMetric1->set_bucket(FIVE_MINUTES);
-
-    auto countMetric2 = config1.add_count_metric();
-    countMetric2->set_id(metricId2);
-    countMetric2->set_what(wakelockAcquireMatcher.id());
-    countMetric2->set_bucket(FIVE_MINUTES);
-
-    auto metric1Activation = config1.add_metric_activation();
-    metric1Activation->set_metric_id(metricId1);
-    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
-    auto metric1ActivationTrigger = metric1Activation->add_event_activation();
-    metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric1ActivationTrigger->set_ttl_seconds(100);
-
-    ConfigKey cfgKey1(uid, 12341);
-    long timeBase1 = 1;
-    sp<StatsLogProcessor> processor =
-            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    auto it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
-    auto& metricsManager1 = it->second;
-    EXPECT_TRUE(metricsManager1->isActive());
-
-    auto metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer1 = *metricIt;
-    EXPECT_FALSE(metricProducer1->isActive());
-
-    metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer2 = *metricIt;
-    EXPECT_TRUE(metricProducer2->isActive());
-
-    const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
-    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kNotActive, activation1->state);
-
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor->OnLogEvent(event.get());
-
-    EXPECT_FALSE(metricProducer1->isActive());
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1->state);
-
-    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_FALSE(metricProducer1->isActive());
-    const int64_t ttl1 = metric1ActivationTrigger->ttl_seconds() * NS_PER_SEC;
-
-    long timeBase2 = 1000;
-    sp<StatsLogProcessor> processor2 =
-            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
-    it = processor2->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1001 = it->second;
-    EXPECT_TRUE(metricsManager1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1001 = *metricIt;
-    EXPECT_FALSE(metricProducer1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1002 = *metricIt;
-    EXPECT_TRUE(metricProducer1002->isActive());
-
-    const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
-    EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
-    EXPECT_EQ(0, activation1001->start_ns);
-    EXPECT_EQ(kNotActive, activation1001->state);
-
-    processor2->LoadActiveConfigsFromDisk();
-
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001->ttl_ns, activation1001->start_ns);
-    EXPECT_EQ(kActive, activation1001->state);
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
-    int uid = 1111;
-
-    // Create config with 2 metrics:
-    // Metric 1: Activate on boot with 2 activations
-    // Metric 2: Always active
-    StatsdConfig config1;
-    config1.set_id(12341);
-    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    *config1.add_atom_matcher() = wakelockAcquireMatcher;
-    *config1.add_atom_matcher() = screenOnMatcher;
-
-    long metricId1 = 1234561;
-    long metricId2 = 1234562;
-
-    auto countMetric1 = config1.add_count_metric();
-    countMetric1->set_id(metricId1);
-    countMetric1->set_what(wakelockAcquireMatcher.id());
-    countMetric1->set_bucket(FIVE_MINUTES);
-
-    auto countMetric2 = config1.add_count_metric();
-    countMetric2->set_id(metricId2);
-    countMetric2->set_what(wakelockAcquireMatcher.id());
-    countMetric2->set_bucket(FIVE_MINUTES);
-
-    auto metric1Activation = config1.add_metric_activation();
-    metric1Activation->set_metric_id(metricId1);
-    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
-    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric1ActivationTrigger1->set_ttl_seconds(100);
-    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
-    metric1ActivationTrigger2->set_ttl_seconds(200);
-
-    ConfigKey cfgKey1(uid, 12341);
-    long timeBase1 = 1;
-    sp<StatsLogProcessor> processor =
-            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    auto it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
-    auto& metricsManager1 = it->second;
-    EXPECT_TRUE(metricsManager1->isActive());
-
-    auto metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer1 = *metricIt;
-    EXPECT_FALSE(metricProducer1->isActive());
-
-    metricIt = metricsManager1->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
-    auto& metricProducer2 = *metricIt;
-    EXPECT_TRUE(metricProducer2->isActive());
-
-    int i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kNotActive, activation1->state);
-
-    i = 0;
-    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-    // }}}------------------------------------------------------------------------------
-
-    // Trigger Activation 1 for Metric 1
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor->OnLogEvent(event.get());
-
-    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducer1->isActive());
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1->state);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-
-    EXPECT_TRUE(metricProducer2->isActive());
-    // }}}-----------------------------------------------------------------------------
-
-    // Simulate shutdown by saving state to disk
-    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_FALSE(metricProducer1->isActive());
-    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
-
-    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
-    // same config.
-    long timeBase2 = 1000;
-    sp<StatsLogProcessor> processor2 =
-            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
-    it = processor2->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager1001 = it->second;
-    EXPECT_TRUE(metricsManager1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1001 = *metricIt;
-    EXPECT_FALSE(metricProducer1001->isActive());
-
-    metricIt = metricsManager1001->mAllMetricProducers.begin();
-    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
-    auto& metricProducer1002 = *metricIt;
-    EXPECT_TRUE(metricProducer1002->isActive());
-
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
-    EXPECT_EQ(0, activation1001_1->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_1->state);
-
-    i = 0;
-    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
-        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
-    // }}}-----------------------------------------------------------------------------------
-
-    // Load saved state from disk.
-    processor2->LoadActiveConfigsFromDisk();
-
-    // Metric 1 active; Activation 1 is active, Activation 2 is not active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1001_2->state);
-
-    EXPECT_TRUE(metricProducer1002->isActive());
-    // }}}--------------------------------------------------------------------------------
-
-    // Trigger Activation 2 for Metric 1.
-    auto screenOnEvent = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON,
-            timeBase2 + 200
-    );
-    processor2->OnLogEvent(screenOnEvent.get());
-
-    // Metric 1 active; Activation 1 is active, Activation 2 is set to kActiveOnBoot
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
-    EXPECT_EQ(kActive, activation1001_1->state);
-    EXPECT_EQ(0, activation1001_2->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1001_2->state);
-
-    EXPECT_TRUE(metricProducer1002->isActive());
-    // }}}---------------------------------------------------------------------------
-
-    // Simulate shutdown by saving state to disk
-    shutDownTime = timeBase2 + 50 * NS_PER_SEC;
-    processor2->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_TRUE(metricProducer1002->isActive());
-    ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
-    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC;
-
-    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
-    // same config.
-    long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
-    sp<StatsLogProcessor> processor3 =
-            CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor3->mMetricsManagers.size());
-    it = processor3->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor3->mMetricsManagers.end());
-    auto& metricsManagerTimeBase3 = it->second;
-    EXPECT_TRUE(metricsManagerTimeBase3->isActive());
-
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_1 = *metricIt;
-    EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
-
-    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
-    auto& metricProducerTimeBase3_2 = *metricIt;
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
-
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-
-    i = 0;
-    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
-
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
-    // }}}----------------------------------------------------------------------------------
-
-    // Load saved state from disk.
-    processor3->LoadActiveConfigsFromDisk();
-
-    // Metric 1 active: Activation 1 is active, Activation 2 is active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_1->state);
-    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
-
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
-    // }}}-------------------------------------------------------------------------------
-
-    // Trigger Activation 2 for Metric 1 again.
-    screenOnEvent = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON,
-            timeBase3 + 100 * NS_PER_SEC
-    );
-    processor3->OnLogEvent(screenOnEvent.get());
-
-    // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
-    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
-    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
-    EXPECT_EQ(kActive, activationTimeBase3_2->state);
-
-    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
-    // }}}---------------------------------------------------------------------------
-
-    // Simulate shutdown by saving state to disk.
-    shutDownTime = timeBase3 + 500 * NS_PER_SEC;
-    processor3->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_TRUE(metricProducer1001->isActive());
-    EXPECT_TRUE(metricProducer1002->isActive());
-    ttl1 = timeBase3 + ttl1 - shutDownTime;
-    ttl2 = timeBase3 + metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
-
-    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
-    // same config.
-    long timeBase4 = timeBase3 + 600 * NS_PER_SEC;
-    sp<StatsLogProcessor> processor4 =
-            CreateStatsLogProcessor(timeBase4, timeBase4, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor4->mMetricsManagers.size());
-    it = processor4->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor4->mMetricsManagers.end());
-    auto& metricsManagerTimeBase4 = it->second;
-    EXPECT_TRUE(metricsManagerTimeBase4->isActive());
-
-    metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId1) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
-    auto& metricProducerTimeBase4_1 = *metricIt;
-    EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
-
-    metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
-    for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
-        if ((*metricIt)->getMetricId() == metricId2) {
-            break;
-        }
-    }
-    EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
-    auto& metricProducerTimeBase4_2 = *metricIt;
-    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
-
-    i = 0;
-    for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger1->atom_matcher_id()) {
-            break;
-        }
-    }
-    const auto& activationTimeBase4_1 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
-    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase4_1->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase4_1->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
-
-    i = 0;
-    for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
-        if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
-                metric1ActivationTrigger2->atom_matcher_id()) {
-            break;
-        }
-    }
-
-    const auto& activationTimeBase4_2 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
-    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase4_2->ttl_ns);
-    EXPECT_EQ(0, activationTimeBase4_2->start_ns);
-    EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
-
-    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
-    // }}}----------------------------------------------------------------------------------
-
-    // Load saved state from disk.
-    processor4->LoadActiveConfigsFromDisk();
-
-    // Metric 1 active: Activation 1 is not active, Activation 2 is not active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
-    EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
-    EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
-
-    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
-    // }}}-------------------------------------------------------------------------------
-}
-
-TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes) {
-    int uid = 1111;
-
-    // Create config with 2 metrics:
-    // Metric 1: Activate on boot with 2 activations
-    // Metric 2: Always active
-    StatsdConfig config1;
-    config1.set_id(12341);
-    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    *config1.add_atom_matcher() = wakelockAcquireMatcher;
-    *config1.add_atom_matcher() = screenOnMatcher;
-
-    long metricId1 = 1234561;
-    long metricId2 = 1234562;
-
-    auto countMetric1 = config1.add_count_metric();
-    countMetric1->set_id(metricId1);
-    countMetric1->set_what(wakelockAcquireMatcher.id());
-    countMetric1->set_bucket(FIVE_MINUTES);
-
-    auto countMetric2 = config1.add_count_metric();
-    countMetric2->set_id(metricId2);
-    countMetric2->set_what(wakelockAcquireMatcher.id());
-    countMetric2->set_bucket(FIVE_MINUTES);
-
-    auto metric1Activation = config1.add_metric_activation();
-    metric1Activation->set_metric_id(metricId1);
-    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
-    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric1ActivationTrigger1->set_ttl_seconds(100);
-    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
-    metric1ActivationTrigger2->set_ttl_seconds(200);
-    metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
-    ConfigKey cfgKey1(uid, 12341);
-    long timeBase1 = 1;
-    sp<StatsLogProcessor> processor1 =
-            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor1->mMetricsManagers.size());
-    auto it = processor1->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor1->mMetricsManagers.end());
-    auto& metricsManager1 = it->second;
-    EXPECT_TRUE(metricsManager1->isActive());
-
-    EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
-    // We assume that the index of a MetricProducer within the mAllMetricProducers
-    // array follows the order in which metrics are added to the config.
-    auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
-    EXPECT_FALSE(metricProducer1_1->isActive());  // inactive due to associated MetricActivation
-
-    auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
-    EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
-    EXPECT_TRUE(metricProducer1_2->isActive());
-
-    EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
-    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
-    // that matchers are indexed in the order that they are added to the config.
-    const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
-    EXPECT_EQ(0, activation1_1_1->start_ns);
-    EXPECT_EQ(kNotActive, activation1_1_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
-
-    const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
-    EXPECT_EQ(0, activation1_1_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1_1_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
-    // }}}------------------------------------------------------------------------------
-
-    // Trigger Activation 1 for Metric 1
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
-    processor1->OnLogEvent(event.get());
-
-    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducer1_1->isActive());
-    EXPECT_EQ(0, activation1_1_1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
-    EXPECT_EQ(0, activation1_1_2->start_ns);
-    EXPECT_EQ(kNotActive, activation1_1_2->state);
-
-    EXPECT_TRUE(metricProducer1_2->isActive());
-    // }}}-----------------------------------------------------------------------------
-
-    // Simulate shutdown by saving state to disk
-    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
-    processor1->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_FALSE(metricProducer1_1->isActive());
-
-    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
-    // same config.
-    long timeBase2 = 1000;
-    sp<StatsLogProcessor> processor2 =
-            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor2->mMetricsManagers.size());
-    it = processor2->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
-    auto& metricsManager2 = it->second;
-    EXPECT_TRUE(metricsManager2->isActive());
-
-    EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
-    // We assume that the index of a MetricProducer within the mAllMetricProducers
-    // array follows the order in which metrics are added to the config.
-    auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
-    EXPECT_FALSE(metricProducer2_1->isActive());
-
-    auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
-    EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
-    EXPECT_TRUE(metricProducer2_2->isActive());
-
-    EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
-    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
-    // that matchers are indexed in the order that they are added to the config.
-    const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
-    EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
-    EXPECT_EQ(0, activation2_1_1->start_ns);
-    EXPECT_EQ(kNotActive, activation2_1_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
-
-    const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
-    EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
-    EXPECT_EQ(0, activation2_1_2->start_ns);
-    EXPECT_EQ(kNotActive, activation2_1_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
-    // }}}-----------------------------------------------------------------------------------
-
-    // Load saved state from disk.
-    processor2->LoadActiveConfigsFromDisk();
-
-    // Metric 1 active; Activation 1 is active, Activation 2 is not active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer2_1->isActive());
-    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
-    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
-    EXPECT_EQ(kActive, activation2_1_1->state);
-    EXPECT_EQ(0, activation2_1_2->start_ns);
-    EXPECT_EQ(kNotActive, activation2_1_2->state);
-
-    EXPECT_TRUE(metricProducer2_2->isActive());
-    // }}}--------------------------------------------------------------------------------
-
-    // Trigger Activation 2 for Metric 1.
-    auto screenOnEvent = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON,
-            timeBase2 + 200
-    );
-    processor2->OnLogEvent(screenOnEvent.get());
-
-    // Metric 1 active; Activation 1 is active, Activation 2 is active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer2_1->isActive());
-    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
-    EXPECT_EQ(kActive, activation2_1_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
-    EXPECT_EQ(kActive, activation2_1_2->state);
-
-    EXPECT_TRUE(metricProducer2_2->isActive());
-    // }}}---------------------------------------------------------------------------
-
-    // Simulate shutdown by saving state to disk
-    shutDownTime = timeBase2 + 50 * NS_PER_SEC;
-    processor2->SaveActiveConfigsToDisk(shutDownTime);
-    EXPECT_TRUE(metricProducer2_1->isActive());
-    EXPECT_TRUE(metricProducer2_2->isActive());
-    ttl1 -= shutDownTime - timeBase2;
-    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
-            - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
-
-    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
-    // same config.
-    long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
-    sp<StatsLogProcessor> processor3 =
-            CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
-
-    // Metric 1 is not active.
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor3->mMetricsManagers.size());
-    it = processor3->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor3->mMetricsManagers.end());
-    auto& metricsManager3 = it->second;
-    EXPECT_TRUE(metricsManager3->isActive());
-
-    EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
-    // We assume that the index of a MetricProducer within the mAllMetricProducers
-    // array follows the order in which metrics are added to the config.
-    auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
-    EXPECT_FALSE(metricProducer3_1->isActive());
-
-    auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
-    EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
-    EXPECT_TRUE(metricProducer3_2->isActive());
-
-    EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
-    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
-    // that matchers are indexed in the order that they are added to the config.
-    const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
-    EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
-    EXPECT_EQ(0, activation3_1_1->start_ns);
-    EXPECT_EQ(kNotActive, activation3_1_1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
-
-    const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
-    EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
-    EXPECT_EQ(0, activation3_1_2->start_ns);
-    EXPECT_EQ(kNotActive, activation3_1_2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
-    // }}}----------------------------------------------------------------------------------
-
-    // Load saved state from disk.
-    processor3->LoadActiveConfigsFromDisk();
-
-    // Metric 1 active: Activation 1 is active, Activation 2 is active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer3_1->isActive());
-    EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
-    EXPECT_EQ(kActive, activation3_1_1->state);
-    EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
-    EXPECT_EQ(kActive, activation3_1_2->state);
-
-    EXPECT_TRUE(metricProducer3_2->isActive());
-    // }}}-------------------------------------------------------------------------------
-
-
-    // Trigger Activation 2 for Metric 1 again.
-    screenOnEvent = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_ON,
-            timeBase3 + 100 * NS_PER_SEC
-    );
-    processor3->OnLogEvent(screenOnEvent.get());
-
-    // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
-    //                  Activation 2 is set to active
-    // Metric 2 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_TRUE(metricProducer3_1->isActive());
-    EXPECT_EQ(kNotActive, activation3_1_1->state);
-    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
-    EXPECT_EQ(kActive, activation3_1_2->state);
-
-    EXPECT_TRUE(metricProducer3_2->isActive());
-    // }}}---------------------------------------------------------------------------
-}
-
-TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
-    int uid = 9876;
-    long configId = 12341;
-
-    // Create config with 3 metrics:
-    // Metric 1: Activate on 2 activations, 1 on boot, 1 immediate.
-    // Metric 2: Activate on 2 activations, 1 on boot, 1 immediate.
-    // Metric 3: Always active
-    StatsdConfig config1;
-    config1.set_id(configId);
-    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    auto jobStartMatcher = CreateStartScheduledJobAtomMatcher();
-    auto jobFinishMatcher = CreateFinishScheduledJobAtomMatcher();
-    *config1.add_atom_matcher() = wakelockAcquireMatcher;
-    *config1.add_atom_matcher() = screenOnMatcher;
-    *config1.add_atom_matcher() = jobStartMatcher;
-    *config1.add_atom_matcher() = jobFinishMatcher;
-
-    long metricId1 = 1234561;
-    long metricId2 = 1234562;
-    long metricId3 = 1234563;
-
-    auto countMetric1 = config1.add_count_metric();
-    countMetric1->set_id(metricId1);
-    countMetric1->set_what(wakelockAcquireMatcher.id());
-    countMetric1->set_bucket(FIVE_MINUTES);
-
-    auto countMetric2 = config1.add_count_metric();
-    countMetric2->set_id(metricId2);
-    countMetric2->set_what(wakelockAcquireMatcher.id());
-    countMetric2->set_bucket(FIVE_MINUTES);
-
-    auto countMetric3 = config1.add_count_metric();
-    countMetric3->set_id(metricId3);
-    countMetric3->set_what(wakelockAcquireMatcher.id());
-    countMetric3->set_bucket(FIVE_MINUTES);
-
-    // Metric 1 activates on boot for wakelock acquire, immediately for screen on.
-    auto metric1Activation = config1.add_metric_activation();
-    metric1Activation->set_metric_id(metricId1);
-    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
-    metric1ActivationTrigger1->set_ttl_seconds(100);
-    metric1ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
-    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
-    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
-    metric1ActivationTrigger2->set_ttl_seconds(200);
-    metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
-    // Metric 2 activates on boot for scheduled job start, immediately for scheduled job finish.
-    auto metric2Activation = config1.add_metric_activation();
-    metric2Activation->set_metric_id(metricId2);
-    auto metric2ActivationTrigger1 = metric2Activation->add_event_activation();
-    metric2ActivationTrigger1->set_atom_matcher_id(jobStartMatcher.id());
-    metric2ActivationTrigger1->set_ttl_seconds(100);
-    metric2ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
-    auto metric2ActivationTrigger2 = metric2Activation->add_event_activation();
-    metric2ActivationTrigger2->set_atom_matcher_id(jobFinishMatcher.id());
-    metric2ActivationTrigger2->set_ttl_seconds(200);
-    metric2ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
-
-    // Send the config.
-    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
-    string serialized = config1.SerializeAsString();
-    service->addConfigurationChecked(uid, configId, {serialized.begin(), serialized.end()});
-
-    // Make sure the config is stored on disk. Otherwise, we will not reset on system server death.
-    StatsdConfig tmpConfig;
-    ConfigKey cfgKey1(uid, configId);
-    EXPECT_TRUE(StorageManager::readConfigFromDisk(cfgKey1, &tmpConfig));
-
-    // Metric 1 is not active.
-    // Metric 2 is not active.
-    // Metric 3 is active.
-    // {{{---------------------------------------------------------------------------
-    sp<StatsLogProcessor> processor = service->mProcessor;
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    auto it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
-    auto& metricsManager1 = it->second;
-    EXPECT_TRUE(metricsManager1->isActive());
-    EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
-
-    auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
-    EXPECT_EQ(metricId1, metricProducer1->getMetricId());
-    EXPECT_FALSE(metricProducer1->isActive());
-
-    auto& metricProducer2 = metricsManager1->mAllMetricProducers[1];
-    EXPECT_EQ(metricId2, metricProducer2->getMetricId());
-    EXPECT_FALSE(metricProducer2->isActive());
-
-    auto& metricProducer3 = metricsManager1->mAllMetricProducers[2];
-    EXPECT_EQ(metricId3, metricProducer3->getMetricId());
-    EXPECT_TRUE(metricProducer3->isActive());
-
-    // Check event activations.
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
-              metric1ActivationTrigger1->atom_matcher_id());
-    const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kNotActive, activation1->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
-
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
-              metric1ActivationTrigger2->atom_matcher_id());
-    const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
-    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
-
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
-              metric2ActivationTrigger1->atom_matcher_id());
-    const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
-    EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
-    EXPECT_EQ(0, activation3->start_ns);
-    EXPECT_EQ(kNotActive, activation3->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
-
-    EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
-              metric2ActivationTrigger2->atom_matcher_id());
-    const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
-    EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
-    EXPECT_EQ(0, activation4->start_ns);
-    EXPECT_EQ(kNotActive, activation4->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation4->activationType);
-    // }}}------------------------------------------------------------------------------
-
-    // Trigger Activation 1 for Metric 1. Should activate on boot.
-    // Trigger Activation 4 for Metric 2. Should activate immediately.
-    long configAddedTimeNs = metricsManager1->mLastReportTimeNs;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 1 + configAddedTimeNs);
-    processor->OnLogEvent(event.get());
-
-    event = CreateFinishScheduledJobEvent(attributions1, "finish1", 2 + configAddedTimeNs);
-    processor->OnLogEvent(event.get());
-
-    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
-    // Metric 2 is active. Activation 4 set to kActive
-    // Metric 3 is active.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_FALSE(metricProducer1->isActive());
-    EXPECT_EQ(0, activation1->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1->state);
-    EXPECT_EQ(0, activation2->start_ns);
-    EXPECT_EQ(kNotActive, activation2->state);
-
-    EXPECT_TRUE(metricProducer2->isActive());
-    EXPECT_EQ(0, activation3->start_ns);
-    EXPECT_EQ(kNotActive, activation3->state);
-    EXPECT_EQ(2 + configAddedTimeNs, activation4->start_ns);
-    EXPECT_EQ(kActive, activation4->state);
-
-    EXPECT_TRUE(metricProducer3->isActive());
-    // }}}-----------------------------------------------------------------------------
-
-    // Can't fake time with StatsService.
-    // Lets get a time close to the system server death time and make sure it's sane.
-    int64_t approximateSystemServerDeath = getElapsedRealtimeNs();
-    EXPECT_TRUE(approximateSystemServerDeath > 2 + configAddedTimeNs);
-    EXPECT_TRUE(approximateSystemServerDeath < NS_PER_SEC + configAddedTimeNs);
-
-    // System server dies.
-    service->statsCompanionServiceDiedImpl();
-
-    // We should have a new metrics manager. Lets get it and ensure activation status is restored.
-    // {{{---------------------------------------------------------------------------
-    EXPECT_EQ(1, processor->mMetricsManagers.size());
-    it = processor->mMetricsManagers.find(cfgKey1);
-    EXPECT_TRUE(it != processor->mMetricsManagers.end());
-    auto& metricsManager2 = it->second;
-    EXPECT_TRUE(metricsManager2->isActive());
-    EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
-
-    auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
-    EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
-    EXPECT_FALSE(metricProducer1001->isActive());
-
-    auto& metricProducer1002 = metricsManager2->mAllMetricProducers[1];
-    EXPECT_EQ(metricId2, metricProducer1002->getMetricId());
-    EXPECT_TRUE(metricProducer1002->isActive());
-
-    auto& metricProducer1003 = metricsManager2->mAllMetricProducers[2];
-    EXPECT_EQ(metricId3, metricProducer1003->getMetricId());
-    EXPECT_TRUE(metricProducer1003->isActive());
-
-    // Check event activations.
-    // Activation 1 is kActiveOnBoot.
-    // Activation 2 and 3 are not active.
-    // Activation 4 is active.
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
-              metric1ActivationTrigger1->atom_matcher_id());
-    const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
-    EXPECT_EQ(0, activation1001->start_ns);
-    EXPECT_EQ(kActiveOnBoot, activation1001->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
-
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
-              metric1ActivationTrigger2->atom_matcher_id());
-    const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
-    EXPECT_EQ(0, activation1002->start_ns);
-    EXPECT_EQ(kNotActive, activation1002->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
-
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
-              metric2ActivationTrigger1->atom_matcher_id());
-    const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
-    EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
-    EXPECT_EQ(0, activation1003->start_ns);
-    EXPECT_EQ(kNotActive, activation1003->state);
-    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
-
-    EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
-              metric2ActivationTrigger2->atom_matcher_id());
-    const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
-    EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
-    EXPECT_EQ(2 + configAddedTimeNs, activation1004->start_ns);
-    EXPECT_EQ(kActive, activation1004->state);
-    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1004->activationType);
-    // }}}------------------------------------------------------------------------------
-
-    // Clear the data stored on disk as a result of the system server death.
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey1, configAddedTimeNs + NS_PER_SEC, false, true,
-                                ADB_DUMP, FAST, &buffer);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(StatsLogProcessorTest, TestOnDumpReportEraseData) {
+//    // Setup a simple config.
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    *config.add_atom_matcher() = wakelockAcquireMatcher;
+//
+//    auto countMetric = config.add_count_metric();
+//    countMetric->set_id(123456);
+//    countMetric->set_what(wakelockAcquireMatcher.id());
+//    countMetric->set_bucket(FIVE_MINUTES);
+//
+//    ConfigKey cfgKey;
+//    sp<StatsLogProcessor> processor = CreateStatsLogProcessor(1, 1, config, cfgKey);
+//
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 2);
+//    processor->OnLogEvent(event.get());
+//
+//    vector<uint8_t> bytes;
+//    ConfigMetricsReportList output;
+//
+//    // Dump report WITHOUT erasing data.
+//    processor->onDumpReport(cfgKey, 3, true, false /* Do NOT erase data. */, ADB_DUMP, FAST, &bytes);
+//    output.ParseFromArray(bytes.data(), bytes.size());
+//    EXPECT_EQ(output.reports_size(), 1);
+//    EXPECT_EQ(output.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+//
+//    // Dump report WITH erasing data. There should be data since we didn't previously erase it.
+//    processor->onDumpReport(cfgKey, 4, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
+//    output.ParseFromArray(bytes.data(), bytes.size());
+//    EXPECT_EQ(output.reports_size(), 1);
+//    EXPECT_EQ(output.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(output.reports(0).metrics(0).count_metrics().data_size(), 1);
+//
+//    // Dump report again. There should be no data since we erased it.
+//    processor->onDumpReport(cfgKey, 5, true, true /* DO erase data. */, ADB_DUMP, FAST, &bytes);
+//    output.ParseFromArray(bytes.data(), bytes.size());
+//    // We don't care whether statsd has a report, as long as it has no count metrics in it.
+//    bool noData = output.reports_size() == 0
+//            || output.reports(0).metrics_size() == 0
+//            || output.reports(0).metrics(0).count_metrics().data_size() == 0;
+//    EXPECT_TRUE(noData);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActiveConfigMetricDiskWriteRead) {
+//    int uid = 1111;
+//
+//    // Setup a simple config, no activation
+//    StatsdConfig config1;
+//    int64_t cfgId1 = 12341;
+//    config1.set_id(cfgId1);
+//    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//
+//    long metricId1 = 1234561;
+//    long metricId2 = 1234562;
+//    auto countMetric1 = config1.add_count_metric();
+//    countMetric1->set_id(metricId1);
+//    countMetric1->set_what(wakelockAcquireMatcher.id());
+//    countMetric1->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric2 = config1.add_count_metric();
+//    countMetric2->set_id(metricId2);
+//    countMetric2->set_what(wakelockAcquireMatcher.id());
+//    countMetric2->set_bucket(FIVE_MINUTES);
+//
+//    ConfigKey cfgKey1(uid, cfgId1);
+//
+//    // Add another config, with two metrics, one with activation
+//    StatsdConfig config2;
+//    int64_t cfgId2 = 12342;
+//    config2.set_id(cfgId2);
+//    config2.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    *config2.add_atom_matcher() = wakelockAcquireMatcher;
+//
+//    long metricId3 = 1234561;
+//    long metricId4 = 1234562;
+//
+//    auto countMetric3 = config2.add_count_metric();
+//    countMetric3->set_id(metricId3);
+//    countMetric3->set_what(wakelockAcquireMatcher.id());
+//    countMetric3->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric4 = config2.add_count_metric();
+//    countMetric4->set_id(metricId4);
+//    countMetric4->set_what(wakelockAcquireMatcher.id());
+//    countMetric4->set_bucket(FIVE_MINUTES);
+//
+//    auto metric3Activation = config2.add_metric_activation();
+//    metric3Activation->set_metric_id(metricId3);
+//    metric3Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+//    auto metric3ActivationTrigger = metric3Activation->add_event_activation();
+//    metric3ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric3ActivationTrigger->set_ttl_seconds(100);
+//
+//    ConfigKey cfgKey2(uid, cfgId2);
+//
+//    // Add another config, with two metrics, both with activations
+//    StatsdConfig config3;
+//    int64_t cfgId3 = 12343;
+//    config3.set_id(cfgId3);
+//    config3.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    *config3.add_atom_matcher() = wakelockAcquireMatcher;
+//
+//    long metricId5 = 1234565;
+//    long metricId6 = 1234566;
+//    auto countMetric5 = config3.add_count_metric();
+//    countMetric5->set_id(metricId5);
+//    countMetric5->set_what(wakelockAcquireMatcher.id());
+//    countMetric5->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric6 = config3.add_count_metric();
+//    countMetric6->set_id(metricId6);
+//    countMetric6->set_what(wakelockAcquireMatcher.id());
+//    countMetric6->set_bucket(FIVE_MINUTES);
+//
+//    auto metric5Activation = config3.add_metric_activation();
+//    metric5Activation->set_metric_id(metricId5);
+//    metric5Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+//    auto metric5ActivationTrigger = metric5Activation->add_event_activation();
+//    metric5ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric5ActivationTrigger->set_ttl_seconds(100);
+//
+//    auto metric6Activation = config3.add_metric_activation();
+//    metric6Activation->set_metric_id(metricId6);
+//    metric6Activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+//    auto metric6ActivationTrigger = metric6Activation->add_event_activation();
+//    metric6ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric6ActivationTrigger->set_ttl_seconds(200);
+//
+//    ConfigKey cfgKey3(uid, cfgId3);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            timeBase1, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(1, cfgKey1, config1);
+//    processor.OnConfigUpdated(2, cfgKey2, config2);
+//    processor.OnConfigUpdated(3, cfgKey3, config3);
+//
+//    EXPECT_EQ(3, processor.mMetricsManagers.size());
+//
+//    // Expect the first config and both metrics in it to be active.
+//    auto it = processor.mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor.mMetricsManagers.end());
+//    auto& metricsManager1 = it->second;
+//    EXPECT_TRUE(metricsManager1->isActive());
+//
+//    auto metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer1 = *metricIt;
+//    EXPECT_TRUE(metricProducer1->isActive());
+//
+//    metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer2 = *metricIt;
+//    EXPECT_TRUE(metricProducer2->isActive());
+//
+//    // Expect config 2 to be active. Metric 3 shouldn't be active, metric 4 should be active.
+//    it = processor.mMetricsManagers.find(cfgKey2);
+//    EXPECT_TRUE(it != processor.mMetricsManagers.end());
+//    auto& metricsManager2 = it->second;
+//    EXPECT_TRUE(metricsManager2->isActive());
+//
+//    metricIt = metricsManager2->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId3) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
+//    auto& metricProducer3 = *metricIt;
+//    EXPECT_FALSE(metricProducer3->isActive());
+//
+//    metricIt = metricsManager2->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId4) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager2->mAllMetricProducers.end());
+//    auto& metricProducer4 = *metricIt;
+//    EXPECT_TRUE(metricProducer4->isActive());
+//
+//    // Expect the third config and both metrics in it to be inactive.
+//    it = processor.mMetricsManagers.find(cfgKey3);
+//    EXPECT_TRUE(it != processor.mMetricsManagers.end());
+//    auto& metricsManager3 = it->second;
+//    EXPECT_FALSE(metricsManager3->isActive());
+//
+//    metricIt = metricsManager3->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager2->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId5) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
+//    auto& metricProducer5 = *metricIt;
+//    EXPECT_FALSE(metricProducer5->isActive());
+//
+//    metricIt = metricsManager3->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager3->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId6) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager3->mAllMetricProducers.end());
+//    auto& metricProducer6 = *metricIt;
+//    EXPECT_FALSE(metricProducer6->isActive());
+//
+//    // No broadcast for active configs should have happened yet.
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    // Activate all 3 metrics that were not active.
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+//    processor.OnLogEvent(event.get());
+//
+//    // Assert that all 3 configs are active.
+//    EXPECT_TRUE(metricsManager1->isActive());
+//    EXPECT_TRUE(metricsManager2->isActive());
+//    EXPECT_TRUE(metricsManager3->isActive());
+//
+//    // A broadcast should have happened, and all 3 configs should be active in the broadcast.
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 3);
+//    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId1)
+//            != activeConfigsBroadcast.end());
+//    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId2)
+//            != activeConfigsBroadcast.end());
+//    EXPECT_TRUE(std::find(activeConfigsBroadcast.begin(), activeConfigsBroadcast.end(), cfgId3)
+//            != activeConfigsBroadcast.end());
+//
+//    // When we shut down, metrics 3 & 5 have 100ns remaining, metric 6 has 100s + 100ns.
+//    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+//    processor.SaveActiveConfigsToDisk(shutDownTime);
+//    const int64_t ttl3 = event->GetElapsedTimestampNs() +
+//            metric3ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//    const int64_t ttl5 = event->GetElapsedTimestampNs() +
+//            metric5ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//    const int64_t ttl6 = event->GetElapsedTimestampNs() +
+//            metric6ActivationTrigger->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//
+//    // Create a second StatsLogProcessor and push the same 3 configs.
+//    long timeBase2 = 1000;
+//    sp<StatsLogProcessor> processor2 =
+//            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//    processor2->OnConfigUpdated(timeBase2, cfgKey2, config2);
+//    processor2->OnConfigUpdated(timeBase2, cfgKey3, config3);
+//
+//    EXPECT_EQ(3, processor2->mMetricsManagers.size());
+//
+//    // First config and both metrics are active.
+//    it = processor2->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager1001 = it->second;
+//    EXPECT_TRUE(metricsManager1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1001 = *metricIt;
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1002 = *metricIt;
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//
+//    // Second config is active. Metric 3 is inactive, metric 4 is active.
+//    it = processor2->mMetricsManagers.find(cfgKey2);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager1002 = it->second;
+//    EXPECT_TRUE(metricsManager1002->isActive());
+//
+//    metricIt = metricsManager1002->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId3) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
+//    auto& metricProducer1003 = *metricIt;
+//    EXPECT_FALSE(metricProducer1003->isActive());
+//
+//    metricIt = metricsManager1002->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId4) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1002->mAllMetricProducers.end());
+//    auto& metricProducer1004 = *metricIt;
+//    EXPECT_TRUE(metricProducer1004->isActive());
+//
+//    // Config 3 is inactive. both metrics are inactive.
+//    it = processor2->mMetricsManagers.find(cfgKey3);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager1003 = it->second;
+//    EXPECT_FALSE(metricsManager1003->isActive());
+//    EXPECT_EQ(2, metricsManager1003->mAllMetricProducers.size());
+//
+//    metricIt = metricsManager1003->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1002->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId5) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
+//    auto& metricProducer1005 = *metricIt;
+//    EXPECT_FALSE(metricProducer1005->isActive());
+//
+//    metricIt = metricsManager1003->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1003->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId6) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1003->mAllMetricProducers.end());
+//    auto& metricProducer1006 = *metricIt;
+//    EXPECT_FALSE(metricProducer1006->isActive());
+//
+//    // Assert that all 3 metrics with activation are inactive and that the ttls were properly set.
+//    EXPECT_FALSE(metricProducer1003->isActive());
+//    const auto& activation1003 = metricProducer1003->mEventActivationMap.begin()->second;
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
+//    EXPECT_EQ(0, activation1003->start_ns);
+//    EXPECT_FALSE(metricProducer1005->isActive());
+//    const auto& activation1005 = metricProducer1005->mEventActivationMap.begin()->second;
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1005->ttl_ns);
+//    EXPECT_EQ(0, activation1005->start_ns);
+//    EXPECT_FALSE(metricProducer1006->isActive());
+//    const auto& activation1006 = metricProducer1006->mEventActivationMap.begin()->second;
+//    EXPECT_EQ(200 * NS_PER_SEC, activation1006->ttl_ns);
+//    EXPECT_EQ(0, activation1006->start_ns);
+//
+//    processor2->LoadActiveConfigsFromDisk();
+//
+//    // After loading activations from disk, assert that all 3 metrics are active.
+//    EXPECT_TRUE(metricProducer1003->isActive());
+//    EXPECT_EQ(timeBase2 + ttl3 - activation1003->ttl_ns, activation1003->start_ns);
+//    EXPECT_TRUE(metricProducer1005->isActive());
+//    EXPECT_EQ(timeBase2 + ttl5 - activation1005->ttl_ns, activation1005->start_ns);
+//    EXPECT_TRUE(metricProducer1006->isActive());
+//    EXPECT_EQ(timeBase2 + ttl6 - activation1006->ttl_ns, activation1003->start_ns);
+//
+//    // Make sure no more broadcasts have happened.
+//    EXPECT_EQ(broadcastCount, 1);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBoot) {
+//    int uid = 1111;
+//
+//    StatsdConfig config1;
+//    config1.set_id(12341);
+//    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//
+//    long metricId1 = 1234561;
+//    long metricId2 = 1234562;
+//    auto countMetric1 = config1.add_count_metric();
+//    countMetric1->set_id(metricId1);
+//    countMetric1->set_what(wakelockAcquireMatcher.id());
+//    countMetric1->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric2 = config1.add_count_metric();
+//    countMetric2->set_id(metricId2);
+//    countMetric2->set_what(wakelockAcquireMatcher.id());
+//    countMetric2->set_bucket(FIVE_MINUTES);
+//
+//    auto metric1Activation = config1.add_metric_activation();
+//    metric1Activation->set_metric_id(metricId1);
+//    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+//    auto metric1ActivationTrigger = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric1ActivationTrigger->set_ttl_seconds(100);
+//
+//    ConfigKey cfgKey1(uid, 12341);
+//    long timeBase1 = 1;
+//    sp<StatsLogProcessor> processor =
+//            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+//    EXPECT_EQ(1, processor->mMetricsManagers.size());
+//    auto it = processor->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+//    auto& metricsManager1 = it->second;
+//    EXPECT_TRUE(metricsManager1->isActive());
+//
+//    auto metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer1 = *metricIt;
+//    EXPECT_FALSE(metricProducer1->isActive());
+//
+//    metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer2 = *metricIt;
+//    EXPECT_TRUE(metricProducer2->isActive());
+//
+//    const auto& activation1 = metricProducer1->mEventActivationMap.begin()->second;
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kNotActive, activation1->state);
+//
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+//    processor->OnLogEvent(event.get());
+//
+//    EXPECT_FALSE(metricProducer1->isActive());
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1->state);
+//
+//    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+//    processor->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_FALSE(metricProducer1->isActive());
+//    const int64_t ttl1 = metric1ActivationTrigger->ttl_seconds() * NS_PER_SEC;
+//
+//    long timeBase2 = 1000;
+//    sp<StatsLogProcessor> processor2 =
+//            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+//    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+//    it = processor2->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager1001 = it->second;
+//    EXPECT_TRUE(metricsManager1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1001 = *metricIt;
+//    EXPECT_FALSE(metricProducer1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1002 = *metricIt;
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//
+//    const auto& activation1001 = metricProducer1001->mEventActivationMap.begin()->second;
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
+//    EXPECT_EQ(0, activation1001->start_ns);
+//    EXPECT_EQ(kNotActive, activation1001->state);
+//
+//    processor2->LoadActiveConfigsFromDisk();
+//
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//    EXPECT_EQ(timeBase2 + ttl1 - activation1001->ttl_ns, activation1001->start_ns);
+//    EXPECT_EQ(kActive, activation1001->state);
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivations) {
+//    int uid = 1111;
+//
+//    // Create config with 2 metrics:
+//    // Metric 1: Activate on boot with 2 activations
+//    // Metric 2: Always active
+//    StatsdConfig config1;
+//    config1.set_id(12341);
+//    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//    *config1.add_atom_matcher() = screenOnMatcher;
+//
+//    long metricId1 = 1234561;
+//    long metricId2 = 1234562;
+//
+//    auto countMetric1 = config1.add_count_metric();
+//    countMetric1->set_id(metricId1);
+//    countMetric1->set_what(wakelockAcquireMatcher.id());
+//    countMetric1->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric2 = config1.add_count_metric();
+//    countMetric2->set_id(metricId2);
+//    countMetric2->set_what(wakelockAcquireMatcher.id());
+//    countMetric2->set_bucket(FIVE_MINUTES);
+//
+//    auto metric1Activation = config1.add_metric_activation();
+//    metric1Activation->set_metric_id(metricId1);
+//    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+//    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric1ActivationTrigger1->set_ttl_seconds(100);
+//    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+//    metric1ActivationTrigger2->set_ttl_seconds(200);
+//
+//    ConfigKey cfgKey1(uid, 12341);
+//    long timeBase1 = 1;
+//    sp<StatsLogProcessor> processor =
+//            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor->mMetricsManagers.size());
+//    auto it = processor->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+//    auto& metricsManager1 = it->second;
+//    EXPECT_TRUE(metricsManager1->isActive());
+//
+//    auto metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer1 = *metricIt;
+//    EXPECT_FALSE(metricProducer1->isActive());
+//
+//    metricIt = metricsManager1->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1->mAllMetricProducers.end());
+//    auto& metricProducer2 = *metricIt;
+//    EXPECT_TRUE(metricProducer2->isActive());
+//
+//    int i = 0;
+//    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
+//        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger1->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//    const auto& activation1 = metricProducer1->mEventActivationMap.at(i);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kNotActive, activation1->state);
+//
+//    i = 0;
+//    for (; i < metricsManager1->mAllAtomMatchers.size(); i++) {
+//        if (metricsManager1->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger2->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//    const auto& activation2 = metricProducer1->mEventActivationMap.at(i);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
+//    EXPECT_EQ(0, activation2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2->state);
+//    // }}}------------------------------------------------------------------------------
+//
+//    // Trigger Activation 1 for Metric 1
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+//    processor->OnLogEvent(event.get());
+//
+//    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_FALSE(metricProducer1->isActive());
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1->state);
+//    EXPECT_EQ(0, activation2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2->state);
+//
+//    EXPECT_TRUE(metricProducer2->isActive());
+//    // }}}-----------------------------------------------------------------------------
+//
+//    // Simulate shutdown by saving state to disk
+//    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+//    processor->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_FALSE(metricProducer1->isActive());
+//    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+//
+//    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+//    // same config.
+//    long timeBase2 = 1000;
+//    sp<StatsLogProcessor> processor2 =
+//            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+//    it = processor2->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager1001 = it->second;
+//    EXPECT_TRUE(metricsManager1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1001 = *metricIt;
+//    EXPECT_FALSE(metricProducer1001->isActive());
+//
+//    metricIt = metricsManager1001->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManager1001->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManager1001->mAllMetricProducers.end());
+//    auto& metricProducer1002 = *metricIt;
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//
+//    i = 0;
+//    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
+//        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger1->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//    const auto& activation1001_1 = metricProducer1001->mEventActivationMap.at(i);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1001_1->ttl_ns);
+//    EXPECT_EQ(0, activation1001_1->start_ns);
+//    EXPECT_EQ(kNotActive, activation1001_1->state);
+//
+//    i = 0;
+//    for (; i < metricsManager1001->mAllAtomMatchers.size(); i++) {
+//        if (metricsManager1001->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger2->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//
+//    const auto& activation1001_2 = metricProducer1001->mEventActivationMap.at(i);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation1001_2->ttl_ns);
+//    EXPECT_EQ(0, activation1001_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation1001_2->state);
+//    // }}}-----------------------------------------------------------------------------------
+//
+//    // Load saved state from disk.
+//    processor2->LoadActiveConfigsFromDisk();
+//
+//    // Metric 1 active; Activation 1 is active, Activation 2 is not active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
+//    EXPECT_EQ(kActive, activation1001_1->state);
+//    EXPECT_EQ(0, activation1001_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation1001_2->state);
+//
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//    // }}}--------------------------------------------------------------------------------
+//
+//    // Trigger Activation 2 for Metric 1.
+//    auto screenOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_ON,
+//            timeBase2 + 200
+//    );
+//    processor2->OnLogEvent(screenOnEvent.get());
+//
+//    // Metric 1 active; Activation 1 is active, Activation 2 is set to kActiveOnBoot
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//    EXPECT_EQ(timeBase2 + ttl1 - activation1001_1->ttl_ns, activation1001_1->start_ns);
+//    EXPECT_EQ(kActive, activation1001_1->state);
+//    EXPECT_EQ(0, activation1001_2->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1001_2->state);
+//
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//    // }}}---------------------------------------------------------------------------
+//
+//    // Simulate shutdown by saving state to disk
+//    shutDownTime = timeBase2 + 50 * NS_PER_SEC;
+//    processor2->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//    ttl1 = timeBase2 + metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC;
+//
+//    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+//    // same config.
+//    long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
+//    sp<StatsLogProcessor> processor3 =
+//            CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor3->mMetricsManagers.size());
+//    it = processor3->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor3->mMetricsManagers.end());
+//    auto& metricsManagerTimeBase3 = it->second;
+//    EXPECT_TRUE(metricsManagerTimeBase3->isActive());
+//
+//    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
+//    auto& metricProducerTimeBase3_1 = *metricIt;
+//    EXPECT_FALSE(metricProducerTimeBase3_1->isActive());
+//
+//    metricIt = metricsManagerTimeBase3->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManagerTimeBase3->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManagerTimeBase3->mAllMetricProducers.end());
+//    auto& metricProducerTimeBase3_2 = *metricIt;
+//    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+//
+//    i = 0;
+//    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
+//        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger1->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//    const auto& activationTimeBase3_1 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
+//    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase3_1->ttl_ns);
+//    EXPECT_EQ(0, activationTimeBase3_1->start_ns);
+//    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
+//
+//    i = 0;
+//    for (; i < metricsManagerTimeBase3->mAllAtomMatchers.size(); i++) {
+//        if (metricsManagerTimeBase3->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger2->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//
+//    const auto& activationTimeBase3_2 = metricProducerTimeBase3_1->mEventActivationMap.at(i);
+//    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase3_2->ttl_ns);
+//    EXPECT_EQ(0, activationTimeBase3_2->start_ns);
+//    EXPECT_EQ(kNotActive, activationTimeBase3_2->state);
+//
+//    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+//    // }}}----------------------------------------------------------------------------------
+//
+//    // Load saved state from disk.
+//    processor3->LoadActiveConfigsFromDisk();
+//
+//    // Metric 1 active: Activation 1 is active, Activation 2 is active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
+//    EXPECT_EQ(timeBase3 + ttl1 - activationTimeBase3_1->ttl_ns, activationTimeBase3_1->start_ns);
+//    EXPECT_EQ(kActive, activationTimeBase3_1->state);
+//    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
+//    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+//
+//    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+//    // }}}-------------------------------------------------------------------------------
+//
+//    // Trigger Activation 2 for Metric 1 again.
+//    screenOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_ON,
+//            timeBase3 + 100 * NS_PER_SEC
+//    );
+//    processor3->OnLogEvent(screenOnEvent.get());
+//
+//    // Metric 1 active; Activation 1 is not active, Activation 2 is set to active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducerTimeBase3_1->isActive());
+//    EXPECT_EQ(kNotActive, activationTimeBase3_1->state);
+//    EXPECT_EQ(timeBase3 + ttl2 - activationTimeBase3_2->ttl_ns, activationTimeBase3_2->start_ns);
+//    EXPECT_EQ(kActive, activationTimeBase3_2->state);
+//
+//    EXPECT_TRUE(metricProducerTimeBase3_2->isActive());
+//    // }}}---------------------------------------------------------------------------
+//
+//    // Simulate shutdown by saving state to disk.
+//    shutDownTime = timeBase3 + 500 * NS_PER_SEC;
+//    processor3->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_TRUE(metricProducer1001->isActive());
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//    ttl1 = timeBase3 + ttl1 - shutDownTime;
+//    ttl2 = timeBase3 + metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC - shutDownTime;
+//
+//    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+//    // same config.
+//    long timeBase4 = timeBase3 + 600 * NS_PER_SEC;
+//    sp<StatsLogProcessor> processor4 =
+//            CreateStatsLogProcessor(timeBase4, timeBase4, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor4->mMetricsManagers.size());
+//    it = processor4->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor4->mMetricsManagers.end());
+//    auto& metricsManagerTimeBase4 = it->second;
+//    EXPECT_TRUE(metricsManagerTimeBase4->isActive());
+//
+//    metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId1) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
+//    auto& metricProducerTimeBase4_1 = *metricIt;
+//    EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
+//
+//    metricIt = metricsManagerTimeBase4->mAllMetricProducers.begin();
+//    for (; metricIt != metricsManagerTimeBase4->mAllMetricProducers.end(); metricIt++) {
+//        if ((*metricIt)->getMetricId() == metricId2) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(metricIt != metricsManagerTimeBase4->mAllMetricProducers.end());
+//    auto& metricProducerTimeBase4_2 = *metricIt;
+//    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+//
+//    i = 0;
+//    for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
+//        if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger1->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//    const auto& activationTimeBase4_1 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
+//    EXPECT_EQ(100 * NS_PER_SEC, activationTimeBase4_1->ttl_ns);
+//    EXPECT_EQ(0, activationTimeBase4_1->start_ns);
+//    EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
+//
+//    i = 0;
+//    for (; i < metricsManagerTimeBase4->mAllAtomMatchers.size(); i++) {
+//        if (metricsManagerTimeBase4->mAllAtomMatchers[i]->getId() ==
+//                metric1ActivationTrigger2->atom_matcher_id()) {
+//            break;
+//        }
+//    }
+//
+//    const auto& activationTimeBase4_2 = metricProducerTimeBase4_1->mEventActivationMap.at(i);
+//    EXPECT_EQ(200 * NS_PER_SEC, activationTimeBase4_2->ttl_ns);
+//    EXPECT_EQ(0, activationTimeBase4_2->start_ns);
+//    EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
+//
+//    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+//    // }}}----------------------------------------------------------------------------------
+//
+//    // Load saved state from disk.
+//    processor4->LoadActiveConfigsFromDisk();
+//
+//    // Metric 1 active: Activation 1 is not active, Activation 2 is not active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_FALSE(metricProducerTimeBase4_1->isActive());
+//    EXPECT_EQ(kNotActive, activationTimeBase4_1->state);
+//    EXPECT_EQ(kNotActive, activationTimeBase4_2->state);
+//
+//    EXPECT_TRUE(metricProducerTimeBase4_2->isActive());
+//    // }}}-------------------------------------------------------------------------------
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationOnBootMultipleActivationsDifferentActivationTypes) {
+//    int uid = 1111;
+//
+//    // Create config with 2 metrics:
+//    // Metric 1: Activate on boot with 2 activations
+//    // Metric 2: Always active
+//    StatsdConfig config1;
+//    config1.set_id(12341);
+//    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//    *config1.add_atom_matcher() = screenOnMatcher;
+//
+//    long metricId1 = 1234561;
+//    long metricId2 = 1234562;
+//
+//    auto countMetric1 = config1.add_count_metric();
+//    countMetric1->set_id(metricId1);
+//    countMetric1->set_what(wakelockAcquireMatcher.id());
+//    countMetric1->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric2 = config1.add_count_metric();
+//    countMetric2->set_id(metricId2);
+//    countMetric2->set_what(wakelockAcquireMatcher.id());
+//    countMetric2->set_bucket(FIVE_MINUTES);
+//
+//    auto metric1Activation = config1.add_metric_activation();
+//    metric1Activation->set_metric_id(metricId1);
+//    metric1Activation->set_activation_type(ACTIVATE_ON_BOOT);
+//    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric1ActivationTrigger1->set_ttl_seconds(100);
+//    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+//    metric1ActivationTrigger2->set_ttl_seconds(200);
+//    metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+//    ConfigKey cfgKey1(uid, 12341);
+//    long timeBase1 = 1;
+//    sp<StatsLogProcessor> processor1 =
+//            CreateStatsLogProcessor(timeBase1, timeBase1, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor1->mMetricsManagers.size());
+//    auto it = processor1->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor1->mMetricsManagers.end());
+//    auto& metricsManager1 = it->second;
+//    EXPECT_TRUE(metricsManager1->isActive());
+//
+//    EXPECT_EQ(metricsManager1->mAllMetricProducers.size(), 2);
+//    // We assume that the index of a MetricProducer within the mAllMetricProducers
+//    // array follows the order in which metrics are added to the config.
+//    auto& metricProducer1_1 = metricsManager1->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer1_1->getMetricId(), metricId1);
+//    EXPECT_FALSE(metricProducer1_1->isActive());  // inactive due to associated MetricActivation
+//
+//    auto& metricProducer1_2 = metricsManager1->mAllMetricProducers[1];
+//    EXPECT_EQ(metricProducer1_2->getMetricId(), metricId2);
+//    EXPECT_TRUE(metricProducer1_2->isActive());
+//
+//    EXPECT_EQ(metricProducer1_1->mEventActivationMap.size(), 2);
+//    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+//    // that matchers are indexed in the order that they are added to the config.
+//    const auto& activation1_1_1 = metricProducer1_1->mEventActivationMap.at(0);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1_1_1->ttl_ns);
+//    EXPECT_EQ(0, activation1_1_1->start_ns);
+//    EXPECT_EQ(kNotActive, activation1_1_1->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1_1_1->activationType);
+//
+//    const auto& activation1_1_2 = metricProducer1_1->mEventActivationMap.at(1);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation1_1_2->ttl_ns);
+//    EXPECT_EQ(0, activation1_1_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation1_1_2->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1_1_2->activationType);
+//    // }}}------------------------------------------------------------------------------
+//
+//    // Trigger Activation 1 for Metric 1
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 100 + timeBase1);
+//    processor1->OnLogEvent(event.get());
+//
+//    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_FALSE(metricProducer1_1->isActive());
+//    EXPECT_EQ(0, activation1_1_1->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1_1_1->state);
+//    EXPECT_EQ(0, activation1_1_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation1_1_2->state);
+//
+//    EXPECT_TRUE(metricProducer1_2->isActive());
+//    // }}}-----------------------------------------------------------------------------
+//
+//    // Simulate shutdown by saving state to disk
+//    int64_t shutDownTime = timeBase1 + 100 * NS_PER_SEC;
+//    processor1->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_FALSE(metricProducer1_1->isActive());
+//
+//    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+//    // same config.
+//    long timeBase2 = 1000;
+//    sp<StatsLogProcessor> processor2 =
+//            CreateStatsLogProcessor(timeBase2, timeBase2, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor2->mMetricsManagers.size());
+//    it = processor2->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor2->mMetricsManagers.end());
+//    auto& metricsManager2 = it->second;
+//    EXPECT_TRUE(metricsManager2->isActive());
+//
+//    EXPECT_EQ(metricsManager2->mAllMetricProducers.size(), 2);
+//    // We assume that the index of a MetricProducer within the mAllMetricProducers
+//    // array follows the order in which metrics are added to the config.
+//    auto& metricProducer2_1 = metricsManager2->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer2_1->getMetricId(), metricId1);
+//    EXPECT_FALSE(metricProducer2_1->isActive());
+//
+//    auto& metricProducer2_2 = metricsManager2->mAllMetricProducers[1];
+//    EXPECT_EQ(metricProducer2_2->getMetricId(), metricId2);
+//    EXPECT_TRUE(metricProducer2_2->isActive());
+//
+//    EXPECT_EQ(metricProducer2_1->mEventActivationMap.size(), 2);
+//    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+//    // that matchers are indexed in the order that they are added to the config.
+//    const auto& activation2_1_1 = metricProducer2_1->mEventActivationMap.at(0);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation2_1_1->ttl_ns);
+//    EXPECT_EQ(0, activation2_1_1->start_ns);
+//    EXPECT_EQ(kNotActive, activation2_1_1->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation2_1_1->activationType);
+//
+//    const auto& activation2_1_2 = metricProducer2_1->mEventActivationMap.at(1);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation2_1_2->ttl_ns);
+//    EXPECT_EQ(0, activation2_1_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2_1_2->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2_1_2->activationType);
+//    // }}}-----------------------------------------------------------------------------------
+//
+//    // Load saved state from disk.
+//    processor2->LoadActiveConfigsFromDisk();
+//
+//    // Metric 1 active; Activation 1 is active, Activation 2 is not active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer2_1->isActive());
+//    int64_t ttl1 = metric1ActivationTrigger1->ttl_seconds() * NS_PER_SEC;
+//    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+//    EXPECT_EQ(kActive, activation2_1_1->state);
+//    EXPECT_EQ(0, activation2_1_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2_1_2->state);
+//
+//    EXPECT_TRUE(metricProducer2_2->isActive());
+//    // }}}--------------------------------------------------------------------------------
+//
+//    // Trigger Activation 2 for Metric 1.
+//    auto screenOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_ON,
+//            timeBase2 + 200
+//    );
+//    processor2->OnLogEvent(screenOnEvent.get());
+//
+//    // Metric 1 active; Activation 1 is active, Activation 2 is active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer2_1->isActive());
+//    EXPECT_EQ(timeBase2 + ttl1 - activation2_1_1->ttl_ns, activation2_1_1->start_ns);
+//    EXPECT_EQ(kActive, activation2_1_1->state);
+//    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation2_1_2->start_ns);
+//    EXPECT_EQ(kActive, activation2_1_2->state);
+//
+//    EXPECT_TRUE(metricProducer2_2->isActive());
+//    // }}}---------------------------------------------------------------------------
+//
+//    // Simulate shutdown by saving state to disk
+//    shutDownTime = timeBase2 + 50 * NS_PER_SEC;
+//    processor2->SaveActiveConfigsToDisk(shutDownTime);
+//    EXPECT_TRUE(metricProducer2_1->isActive());
+//    EXPECT_TRUE(metricProducer2_2->isActive());
+//    ttl1 -= shutDownTime - timeBase2;
+//    int64_t ttl2 = metric1ActivationTrigger2->ttl_seconds() * NS_PER_SEC
+//            - (shutDownTime - screenOnEvent->GetElapsedTimestampNs());
+//
+//    // Simulate device restarted state by creating new instance of StatsLogProcessor with the
+//    // same config.
+//    long timeBase3 = timeBase2 + 120 * NS_PER_SEC;
+//    sp<StatsLogProcessor> processor3 =
+//            CreateStatsLogProcessor(timeBase3, timeBase3, config1, cfgKey1);
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor3->mMetricsManagers.size());
+//    it = processor3->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor3->mMetricsManagers.end());
+//    auto& metricsManager3 = it->second;
+//    EXPECT_TRUE(metricsManager3->isActive());
+//
+//    EXPECT_EQ(metricsManager3->mAllMetricProducers.size(), 2);
+//    // We assume that the index of a MetricProducer within the mAllMetricProducers
+//    // array follows the order in which metrics are added to the config.
+//    auto& metricProducer3_1 = metricsManager3->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer3_1->getMetricId(), metricId1);
+//    EXPECT_FALSE(metricProducer3_1->isActive());
+//
+//    auto& metricProducer3_2 = metricsManager3->mAllMetricProducers[1];
+//    EXPECT_EQ(metricProducer3_2->getMetricId(), metricId2);
+//    EXPECT_TRUE(metricProducer3_2->isActive());
+//
+//    EXPECT_EQ(metricProducer3_1->mEventActivationMap.size(), 2);
+//    // The key in mEventActivationMap is the index of the associated atom matcher. We assume
+//    // that matchers are indexed in the order that they are added to the config.
+//    const auto& activation3_1_1 = metricProducer3_1->mEventActivationMap.at(0);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation3_1_1->ttl_ns);
+//    EXPECT_EQ(0, activation3_1_1->start_ns);
+//    EXPECT_EQ(kNotActive, activation3_1_1->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3_1_1->activationType);
+//
+//    const auto& activation3_1_2 = metricProducer3_1->mEventActivationMap.at(1);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation3_1_2->ttl_ns);
+//    EXPECT_EQ(0, activation3_1_2->start_ns);
+//    EXPECT_EQ(kNotActive, activation3_1_2->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation3_1_2->activationType);
+//    // }}}----------------------------------------------------------------------------------
+//
+//    // Load saved state from disk.
+//    processor3->LoadActiveConfigsFromDisk();
+//
+//    // Metric 1 active: Activation 1 is active, Activation 2 is active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer3_1->isActive());
+//    EXPECT_EQ(timeBase3 + ttl1 - activation3_1_1->ttl_ns, activation3_1_1->start_ns);
+//    EXPECT_EQ(kActive, activation3_1_1->state);
+//    EXPECT_EQ(timeBase3 + ttl2 - activation3_1_2->ttl_ns, activation3_1_2->start_ns);
+//    EXPECT_EQ(kActive, activation3_1_2->state);
+//
+//    EXPECT_TRUE(metricProducer3_2->isActive());
+//    // }}}-------------------------------------------------------------------------------
+//
+//
+//    // Trigger Activation 2 for Metric 1 again.
+//    screenOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_ON,
+//            timeBase3 + 100 * NS_PER_SEC
+//    );
+//    processor3->OnLogEvent(screenOnEvent.get());
+//
+//    // Metric 1 active; Activation 1 is inactive (above screenOnEvent causes ttl1 to expire),
+//    //                  Activation 2 is set to active
+//    // Metric 2 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_TRUE(metricProducer3_1->isActive());
+//    EXPECT_EQ(kNotActive, activation3_1_1->state);
+//    EXPECT_EQ(screenOnEvent->GetElapsedTimestampNs(), activation3_1_2->start_ns);
+//    EXPECT_EQ(kActive, activation3_1_2->state);
+//
+//    EXPECT_TRUE(metricProducer3_2->isActive());
+//    // }}}---------------------------------------------------------------------------
+//}
+//
+//TEST(StatsLogProcessorTest, TestActivationsPersistAcrossSystemServerRestart) {
+//    int uid = 9876;
+//    long configId = 12341;
+//
+//    // Create config with 3 metrics:
+//    // Metric 1: Activate on 2 activations, 1 on boot, 1 immediate.
+//    // Metric 2: Activate on 2 activations, 1 on boot, 1 immediate.
+//    // Metric 3: Always active
+//    StatsdConfig config1;
+//    config1.set_id(configId);
+//    config1.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//    auto wakelockAcquireMatcher = CreateAcquireWakelockAtomMatcher();
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    auto jobStartMatcher = CreateStartScheduledJobAtomMatcher();
+//    auto jobFinishMatcher = CreateFinishScheduledJobAtomMatcher();
+//    *config1.add_atom_matcher() = wakelockAcquireMatcher;
+//    *config1.add_atom_matcher() = screenOnMatcher;
+//    *config1.add_atom_matcher() = jobStartMatcher;
+//    *config1.add_atom_matcher() = jobFinishMatcher;
+//
+//    long metricId1 = 1234561;
+//    long metricId2 = 1234562;
+//    long metricId3 = 1234563;
+//
+//    auto countMetric1 = config1.add_count_metric();
+//    countMetric1->set_id(metricId1);
+//    countMetric1->set_what(wakelockAcquireMatcher.id());
+//    countMetric1->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric2 = config1.add_count_metric();
+//    countMetric2->set_id(metricId2);
+//    countMetric2->set_what(wakelockAcquireMatcher.id());
+//    countMetric2->set_bucket(FIVE_MINUTES);
+//
+//    auto countMetric3 = config1.add_count_metric();
+//    countMetric3->set_id(metricId3);
+//    countMetric3->set_what(wakelockAcquireMatcher.id());
+//    countMetric3->set_bucket(FIVE_MINUTES);
+//
+//    // Metric 1 activates on boot for wakelock acquire, immediately for screen on.
+//    auto metric1Activation = config1.add_metric_activation();
+//    metric1Activation->set_metric_id(metricId1);
+//    auto metric1ActivationTrigger1 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger1->set_atom_matcher_id(wakelockAcquireMatcher.id());
+//    metric1ActivationTrigger1->set_ttl_seconds(100);
+//    metric1ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+//    auto metric1ActivationTrigger2 = metric1Activation->add_event_activation();
+//    metric1ActivationTrigger2->set_atom_matcher_id(screenOnMatcher.id());
+//    metric1ActivationTrigger2->set_ttl_seconds(200);
+//    metric1ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+//    // Metric 2 activates on boot for scheduled job start, immediately for scheduled job finish.
+//    auto metric2Activation = config1.add_metric_activation();
+//    metric2Activation->set_metric_id(metricId2);
+//    auto metric2ActivationTrigger1 = metric2Activation->add_event_activation();
+//    metric2ActivationTrigger1->set_atom_matcher_id(jobStartMatcher.id());
+//    metric2ActivationTrigger1->set_ttl_seconds(100);
+//    metric2ActivationTrigger1->set_activation_type(ACTIVATE_ON_BOOT);
+//    auto metric2ActivationTrigger2 = metric2Activation->add_event_activation();
+//    metric2ActivationTrigger2->set_atom_matcher_id(jobFinishMatcher.id());
+//    metric2ActivationTrigger2->set_ttl_seconds(200);
+//    metric2ActivationTrigger2->set_activation_type(ACTIVATE_IMMEDIATELY);
+//
+//    // Send the config.
+//    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+//    string serialized = config1.SerializeAsString();
+//    service->addConfigurationChecked(uid, configId, {serialized.begin(), serialized.end()});
+//
+//    // Make sure the config is stored on disk. Otherwise, we will not reset on system server death.
+//    StatsdConfig tmpConfig;
+//    ConfigKey cfgKey1(uid, configId);
+//    EXPECT_TRUE(StorageManager::readConfigFromDisk(cfgKey1, &tmpConfig));
+//
+//    // Metric 1 is not active.
+//    // Metric 2 is not active.
+//    // Metric 3 is active.
+//    // {{{---------------------------------------------------------------------------
+//    sp<StatsLogProcessor> processor = service->mProcessor;
+//    EXPECT_EQ(1, processor->mMetricsManagers.size());
+//    auto it = processor->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+//    auto& metricsManager1 = it->second;
+//    EXPECT_TRUE(metricsManager1->isActive());
+//    EXPECT_EQ(3, metricsManager1->mAllMetricProducers.size());
+//
+//    auto& metricProducer1 = metricsManager1->mAllMetricProducers[0];
+//    EXPECT_EQ(metricId1, metricProducer1->getMetricId());
+//    EXPECT_FALSE(metricProducer1->isActive());
+//
+//    auto& metricProducer2 = metricsManager1->mAllMetricProducers[1];
+//    EXPECT_EQ(metricId2, metricProducer2->getMetricId());
+//    EXPECT_FALSE(metricProducer2->isActive());
+//
+//    auto& metricProducer3 = metricsManager1->mAllMetricProducers[2];
+//    EXPECT_EQ(metricId3, metricProducer3->getMetricId());
+//    EXPECT_TRUE(metricProducer3->isActive());
+//
+//    // Check event activations.
+//    EXPECT_EQ(metricsManager1->mAllAtomMatchers.size(), 4);
+//    EXPECT_EQ(metricsManager1->mAllAtomMatchers[0]->getId(),
+//              metric1ActivationTrigger1->atom_matcher_id());
+//    const auto& activation1 = metricProducer1->mEventActivationMap.at(0);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1->ttl_ns);
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kNotActive, activation1->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1->activationType);
+//
+//    EXPECT_EQ(metricsManager1->mAllAtomMatchers[1]->getId(),
+//              metric1ActivationTrigger2->atom_matcher_id());
+//    const auto& activation2 = metricProducer1->mEventActivationMap.at(1);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation2->ttl_ns);
+//    EXPECT_EQ(0, activation2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation2->activationType);
+//
+//    EXPECT_EQ(metricsManager1->mAllAtomMatchers[2]->getId(),
+//              metric2ActivationTrigger1->atom_matcher_id());
+//    const auto& activation3 = metricProducer2->mEventActivationMap.at(2);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation3->ttl_ns);
+//    EXPECT_EQ(0, activation3->start_ns);
+//    EXPECT_EQ(kNotActive, activation3->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation3->activationType);
+//
+//    EXPECT_EQ(metricsManager1->mAllAtomMatchers[3]->getId(),
+//              metric2ActivationTrigger2->atom_matcher_id());
+//    const auto& activation4 = metricProducer2->mEventActivationMap.at(3);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation4->ttl_ns);
+//    EXPECT_EQ(0, activation4->start_ns);
+//    EXPECT_EQ(kNotActive, activation4->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation4->activationType);
+//    // }}}------------------------------------------------------------------------------
+//
+//    // Trigger Activation 1 for Metric 1. Should activate on boot.
+//    // Trigger Activation 4 for Metric 2. Should activate immediately.
+//    long configAddedTimeNs = metricsManager1->mLastReportTimeNs;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", 1 + configAddedTimeNs);
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateFinishScheduledJobEvent(attributions1, "finish1", 2 + configAddedTimeNs);
+//    processor->OnLogEvent(event.get());
+//
+//    // Metric 1 is not active; Activation 1 set to kActiveOnBoot
+//    // Metric 2 is active. Activation 4 set to kActive
+//    // Metric 3 is active.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_FALSE(metricProducer1->isActive());
+//    EXPECT_EQ(0, activation1->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1->state);
+//    EXPECT_EQ(0, activation2->start_ns);
+//    EXPECT_EQ(kNotActive, activation2->state);
+//
+//    EXPECT_TRUE(metricProducer2->isActive());
+//    EXPECT_EQ(0, activation3->start_ns);
+//    EXPECT_EQ(kNotActive, activation3->state);
+//    EXPECT_EQ(2 + configAddedTimeNs, activation4->start_ns);
+//    EXPECT_EQ(kActive, activation4->state);
+//
+//    EXPECT_TRUE(metricProducer3->isActive());
+//    // }}}-----------------------------------------------------------------------------
+//
+//    // Can't fake time with StatsService.
+//    // Lets get a time close to the system server death time and make sure it's sane.
+//    int64_t approximateSystemServerDeath = getElapsedRealtimeNs();
+//    EXPECT_TRUE(approximateSystemServerDeath > 2 + configAddedTimeNs);
+//    EXPECT_TRUE(approximateSystemServerDeath < NS_PER_SEC + configAddedTimeNs);
+//
+//    // System server dies.
+//    service->statsCompanionServiceDiedImpl();
+//
+//    // We should have a new metrics manager. Lets get it and ensure activation status is restored.
+//    // {{{---------------------------------------------------------------------------
+//    EXPECT_EQ(1, processor->mMetricsManagers.size());
+//    it = processor->mMetricsManagers.find(cfgKey1);
+//    EXPECT_TRUE(it != processor->mMetricsManagers.end());
+//    auto& metricsManager2 = it->second;
+//    EXPECT_TRUE(metricsManager2->isActive());
+//    EXPECT_EQ(3, metricsManager2->mAllMetricProducers.size());
+//
+//    auto& metricProducer1001 = metricsManager2->mAllMetricProducers[0];
+//    EXPECT_EQ(metricId1, metricProducer1001->getMetricId());
+//    EXPECT_FALSE(metricProducer1001->isActive());
+//
+//    auto& metricProducer1002 = metricsManager2->mAllMetricProducers[1];
+//    EXPECT_EQ(metricId2, metricProducer1002->getMetricId());
+//    EXPECT_TRUE(metricProducer1002->isActive());
+//
+//    auto& metricProducer1003 = metricsManager2->mAllMetricProducers[2];
+//    EXPECT_EQ(metricId3, metricProducer1003->getMetricId());
+//    EXPECT_TRUE(metricProducer1003->isActive());
+//
+//    // Check event activations.
+//    // Activation 1 is kActiveOnBoot.
+//    // Activation 2 and 3 are not active.
+//    // Activation 4 is active.
+//    EXPECT_EQ(metricsManager2->mAllAtomMatchers.size(), 4);
+//    EXPECT_EQ(metricsManager2->mAllAtomMatchers[0]->getId(),
+//              metric1ActivationTrigger1->atom_matcher_id());
+//    const auto& activation1001 = metricProducer1001->mEventActivationMap.at(0);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1001->ttl_ns);
+//    EXPECT_EQ(0, activation1001->start_ns);
+//    EXPECT_EQ(kActiveOnBoot, activation1001->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1001->activationType);
+//
+//    EXPECT_EQ(metricsManager2->mAllAtomMatchers[1]->getId(),
+//              metric1ActivationTrigger2->atom_matcher_id());
+//    const auto& activation1002 = metricProducer1001->mEventActivationMap.at(1);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation1002->ttl_ns);
+//    EXPECT_EQ(0, activation1002->start_ns);
+//    EXPECT_EQ(kNotActive, activation1002->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1002->activationType);
+//
+//    EXPECT_EQ(metricsManager2->mAllAtomMatchers[2]->getId(),
+//              metric2ActivationTrigger1->atom_matcher_id());
+//    const auto& activation1003 = metricProducer1002->mEventActivationMap.at(2);
+//    EXPECT_EQ(100 * NS_PER_SEC, activation1003->ttl_ns);
+//    EXPECT_EQ(0, activation1003->start_ns);
+//    EXPECT_EQ(kNotActive, activation1003->state);
+//    EXPECT_EQ(ACTIVATE_ON_BOOT, activation1003->activationType);
+//
+//    EXPECT_EQ(metricsManager2->mAllAtomMatchers[3]->getId(),
+//              metric2ActivationTrigger2->atom_matcher_id());
+//    const auto& activation1004 = metricProducer1002->mEventActivationMap.at(3);
+//    EXPECT_EQ(200 * NS_PER_SEC, activation1004->ttl_ns);
+//    EXPECT_EQ(2 + configAddedTimeNs, activation1004->start_ns);
+//    EXPECT_EQ(kActive, activation1004->state);
+//    EXPECT_EQ(ACTIVATE_IMMEDIATELY, activation1004->activationType);
+//    // }}}------------------------------------------------------------------------------
+//
+//    // Clear the data stored on disk as a result of the system server death.
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey1, configAddedTimeNs + NS_PER_SEC, false, true,
+//                                ADB_DUMP, FAST, &buffer);
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/UidMap_test.cpp b/cmds/statsd/tests/UidMap_test.cpp
index d9fa4e9..af6de06 100644
--- a/cmds/statsd/tests/UidMap_test.cpp
+++ b/cmds/statsd/tests/UidMap_test.cpp
@@ -39,34 +39,35 @@
 const string kApp1 = "app1.sharing.1";
 const string kApp2 = "app2.sharing.1";
 
-TEST(UidMapTest, TestIsolatedUID) {
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    // Construct the processor with a dummy sendBroadcast function that does nothing.
-    StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
-                        [](const ConfigKey& key) { return true; },
-                        [](const int&, const vector<int64_t>&) {return true;});
-    LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
-    addEvent.write(100);  // parent UID
-    addEvent.write(101);  // isolated UID
-    addEvent.write(1);    // Indicates creation.
-    addEvent.init();
-
-    EXPECT_EQ(101, m->getHostUidOrSelf(101));
-
-    p.OnLogEvent(&addEvent);
-    EXPECT_EQ(100, m->getHostUidOrSelf(101));
-
-    LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
-    removeEvent.write(100);  // parent UID
-    removeEvent.write(101);  // isolated UID
-    removeEvent.write(0);    // Indicates removal.
-    removeEvent.init();
-    p.OnLogEvent(&removeEvent);
-    EXPECT_EQ(101, m->getHostUidOrSelf(101));
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(UidMapTest, TestIsolatedUID) {
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    // Construct the processor with a dummy sendBroadcast function that does nothing.
+//    StatsLogProcessor p(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor, 0,
+//                        [](const ConfigKey& key) { return true; },
+//                        [](const int&, const vector<int64_t>&) {return true;});
+//    LogEvent addEvent(android::util::ISOLATED_UID_CHANGED, 1);
+//    addEvent.write(100);  // parent UID
+//    addEvent.write(101);  // isolated UID
+//    addEvent.write(1);    // Indicates creation.
+//    addEvent.init();
+//
+//    EXPECT_EQ(101, m->getHostUidOrSelf(101));
+//
+//    p.OnLogEvent(&addEvent);
+//    EXPECT_EQ(100, m->getHostUidOrSelf(101));
+//
+//    LogEvent removeEvent(android::util::ISOLATED_UID_CHANGED, 1);
+//    removeEvent.write(100);  // parent UID
+//    removeEvent.write(101);  // isolated UID
+//    removeEvent.write(0);    // Indicates removal.
+//    removeEvent.init();
+//    p.OnLogEvent(&removeEvent);
+//    EXPECT_EQ(101, m->getHostUidOrSelf(101));
+//}
 
 TEST(UidMapTest, TestMatching) {
     UidMap m;
diff --git a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
index 6eaa231..36094b2 100644
--- a/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/SimpleConditionTracker_test.cpp
@@ -67,13 +67,14 @@
     event->write(nodes);  // attribution chain.
 }
 
-void makeWakeLockEvent(
-        LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
-    writeAttributionNodesToEvent(event, uids);
-    event->write(wl);
-    event->write(acquire);
-    event->init();
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//void makeWakeLockEvent(
+//        LogEvent* event, const std::vector<int> &uids, const string& wl, int acquire) {
+//    writeAttributionNodesToEvent(event, uids);
+//    event->write(wl);
+//    event->write(acquire);
+//    event->init();
+//}
 
 std::map<int64_t, HashableDimensionKey> getWakeLockQueryKey(
     const Position position,
@@ -264,377 +265,378 @@
     EXPECT_TRUE(changedCache[0]);
 }
 
-TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
-    std::vector<sp<ConditionTracker>> allConditions;
-    for (Position position :
-            { Position::FIRST, Position::LAST}) {
-
-        SimplePredicate simplePredicate = getWakeLockHeldCondition(
-                true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
-                position);
-        string conditionName = "WL_HELD_BY_UID2";
-
-        unordered_map<int64_t, int> trackerNameIndexMap;
-        trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
-        trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
-        trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
-        SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
-                                                0 /*condition tracker index*/, simplePredicate,
-                                                trackerNameIndexMap);
-
-        std::vector<int> uids = {111, 222, 333};
-
-        LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event, uids, "wl1", 1);
-
-        // one matched start
-        vector<MatchingState> matcherState;
-        matcherState.push_back(MatchingState::kMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        vector<sp<ConditionTracker>> allPredicates;
-        vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-        vector<bool> changedCache(1, false);
-
-        conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-        } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-        }
-        EXPECT_TRUE(changedCache[0]);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
-            EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-        } else {
-            EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
-        }
-
-        // Now test query
-        const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
-        // another wake lock acquired by this uid
-        LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event2, uids, "wl2", 1);
-        matcherState.clear();
-        matcherState.push_back(MatchingState::kMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        changedCache[0] = false;
-        conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        EXPECT_FALSE(changedCache[0]);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-        } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-        }
-        EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-        EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-
-
-        // wake lock 1 release
-        LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event3, uids, "wl1", 0);  // now release it.
-        matcherState.clear();
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kMatched);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        changedCache[0] = false;
-        conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        // nothing changes, because wake lock 2 is still held for this uid
-        EXPECT_FALSE(changedCache[0]);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-        } else {
-            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
-        }
-        EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-        EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-
-        LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event4, uids, "wl2", 0);  // now release it.
-        matcherState.clear();
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kMatched);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        changedCache[0] = false;
-        conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
-        EXPECT_TRUE(changedCache[0]);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
-            EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-        } else {
-            EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
-        }
-
-        // query again
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-    }
-
-}
-
-TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
-    std::vector<sp<ConditionTracker>> allConditions;
-
-    SimplePredicate simplePredicate = getWakeLockHeldCondition(
-            true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
-            Position::ANY /* position */);
-    string conditionName = "WL_HELD";
-
-    unordered_map<int64_t, int> trackerNameIndexMap;
-    trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
-    trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
-    trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
-    SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
-                                            0 /*condition tracker index*/, simplePredicate,
-                                            trackerNameIndexMap);
-
-    EXPECT_FALSE(conditionTracker.isSliced());
-
-    std::vector<int> uid_list1 = {111, 1111, 11111};
-    string uid1_wl1 = "wl1_1";
-    std::vector<int> uid_list2 = {222, 2222, 22222};
-    string uid2_wl1 = "wl2_1";
-
-    LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
-    makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
-
-    // one matched start for uid1
-    vector<MatchingState> matcherState;
-    matcherState.push_back(MatchingState::kMatched);
-    matcherState.push_back(MatchingState::kNotMatched);
-    matcherState.push_back(MatchingState::kNotMatched);
-    vector<sp<ConditionTracker>> allPredicates;
-    vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-    vector<bool> changedCache(1, false);
-
-    conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
-                                       changedCache);
-
-    EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-    EXPECT_TRUE(changedCache[0]);
-
-    // Now test query
-    ConditionKey queryKey;
-    conditionCache[0] = ConditionState::kNotEvaluated;
-
-    conditionTracker.isConditionMet(queryKey, allPredicates,
-                                    true,
-                                    conditionCache);
-    EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
-    // another wake lock acquired by this uid
-    LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
-    makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
-    matcherState.clear();
-    matcherState.push_back(MatchingState::kMatched);
-    matcherState.push_back(MatchingState::kNotMatched);
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    changedCache[0] = false;
-    conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
-                                       changedCache);
-    EXPECT_FALSE(changedCache[0]);
-
-    // uid1 wake lock 1 release
-    LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
-    makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0);  // now release it.
-    matcherState.clear();
-    matcherState.push_back(MatchingState::kNotMatched);
-    matcherState.push_back(MatchingState::kMatched);
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    changedCache[0] = false;
-    conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
-                                       changedCache);
-    // nothing changes, because uid2 is still holding wl.
-    EXPECT_FALSE(changedCache[0]);
-
-    LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
-    makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0);  // now release it.
-    matcherState.clear();
-    matcherState.push_back(MatchingState::kNotMatched);
-    matcherState.push_back(MatchingState::kMatched);
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    changedCache[0] = false;
-    conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
-                                       changedCache);
-    EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
-    EXPECT_TRUE(changedCache[0]);
-
-    // query again
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    conditionTracker.isConditionMet(queryKey, allPredicates,
-                                    true,
-                                    conditionCache);
-    EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-}
-
-TEST(SimpleConditionTrackerTest, TestStopAll) {
-    std::vector<sp<ConditionTracker>> allConditions;
-    for (Position position :
-            { Position::FIRST, Position::LAST }) {
-        SimplePredicate simplePredicate = getWakeLockHeldCondition(
-                true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
-                position);
-        string conditionName = "WL_HELD_BY_UID3";
-
-        unordered_map<int64_t, int> trackerNameIndexMap;
-        trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
-        trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
-        trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
-
-        SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
-                                                0 /*condition tracker index*/, simplePredicate,
-                                                trackerNameIndexMap);
-
-        std::vector<int> uid_list1 = {111, 1111, 11111};
-        std::vector<int> uid_list2 = {222, 2222, 22222};
-
-        LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event, uid_list1, "wl1", 1);
-
-        // one matched start
-        vector<MatchingState> matcherState;
-        matcherState.push_back(MatchingState::kMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        vector<sp<ConditionTracker>> allPredicates;
-        vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-        vector<bool> changedCache(1, false);
-
-        conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
-        } else {
-            EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
-        }
-        EXPECT_TRUE(changedCache[0]);
-        {
-            if (position == Position::FIRST ||
-                position == Position::LAST) {
-                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-            } else {
-                EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-            }
-        }
-
-        // Now test query
-        const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
-        // another wake lock acquired by uid2
-        LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
-        makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
-        matcherState.clear();
-        matcherState.push_back(MatchingState::kMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        changedCache[0] = false;
-        conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        if (position == Position::FIRST ||
-            position == Position::LAST) {
-            EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
-        } else {
-            EXPECT_EQ(uid_list1.size() + uid_list2.size(),
-                      conditionTracker.mSlicedConditionState.size());
-        }
-        EXPECT_TRUE(changedCache[0]);
-        {
-            if (position == Position::FIRST ||
-                position == Position::LAST) {
-                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-            } else {
-                EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
-            }
-        }
-
-
-        // TEST QUERY
-        const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-
-        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
-
-
-        // stop all event
-        LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
-        matcherState.clear();
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kNotMatched);
-        matcherState.push_back(MatchingState::kMatched);
-
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        changedCache[0] = false;
-        conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
-                                           changedCache);
-        EXPECT_TRUE(changedCache[0]);
-        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
-        {
-            if (position == Position::FIRST || position == Position::LAST) {
-                EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-            } else {
-                EXPECT_EQ(uid_list1.size() + uid_list2.size(),
-                          conditionTracker.getChangedToFalseDimensions(allConditions)->size());
-                EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
-            }
-        }
-
-        // TEST QUERY
-        const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-
-        // TEST QUERY
-        const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
-        conditionCache[0] = ConditionState::kNotEvaluated;
-        conditionTracker.isConditionMet(queryKey, allPredicates,
-                                        false,
-                                        conditionCache);
-        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
-    }
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(SimpleConditionTrackerTest, TestSlicedCondition) {
+//    std::vector<sp<ConditionTracker>> allConditions;
+//    for (Position position :
+//            { Position::FIRST, Position::LAST}) {
+//
+//        SimplePredicate simplePredicate = getWakeLockHeldCondition(
+//                true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
+//                position);
+//        string conditionName = "WL_HELD_BY_UID2";
+//
+//        unordered_map<int64_t, int> trackerNameIndexMap;
+//        trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+//        trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+//        trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+//        SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+//                                                0 /*condition tracker index*/, simplePredicate,
+//                                                trackerNameIndexMap);
+//
+//        std::vector<int> uids = {111, 222, 333};
+//
+//        LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event, uids, "wl1", 1);
+//
+//        // one matched start
+//        vector<MatchingState> matcherState;
+//        matcherState.push_back(MatchingState::kMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        vector<sp<ConditionTracker>> allPredicates;
+//        vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+//        vector<bool> changedCache(1, false);
+//
+//        conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+//        } else {
+//            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+//        }
+//        EXPECT_TRUE(changedCache[0]);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), 1u);
+//            EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//        } else {
+//            EXPECT_EQ(conditionTracker.getChangedToTrueDimensions(allConditions)->size(), uids.size());
+//        }
+//
+//        // Now test query
+//        const auto queryKey = getWakeLockQueryKey(position, uids, conditionName);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+//        // another wake lock acquired by this uid
+//        LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event2, uids, "wl2", 1);
+//        matcherState.clear();
+//        matcherState.push_back(MatchingState::kMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        changedCache[0] = false;
+//        conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        EXPECT_FALSE(changedCache[0]);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+//        } else {
+//            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+//        }
+//        EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+//        EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//
+//
+//        // wake lock 1 release
+//        LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event3, uids, "wl1", 0);  // now release it.
+//        matcherState.clear();
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kMatched);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        changedCache[0] = false;
+//        conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        // nothing changes, because wake lock 2 is still held for this uid
+//        EXPECT_FALSE(changedCache[0]);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+//        } else {
+//            EXPECT_EQ(uids.size(), conditionTracker.mSlicedConditionState.size());
+//        }
+//        EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+//        EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//
+//        LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event4, uids, "wl2", 0);  // now release it.
+//        matcherState.clear();
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kMatched);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        changedCache[0] = false;
+//        conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+//        EXPECT_TRUE(changedCache[0]);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), 1u);
+//            EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+//        } else {
+//            EXPECT_EQ(conditionTracker.getChangedToFalseDimensions(allConditions)->size(), uids.size());
+//        }
+//
+//        // query again
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//    }
+//
+//}
+//
+//TEST(SimpleConditionTrackerTest, TestSlicedWithNoOutputDim) {
+//    std::vector<sp<ConditionTracker>> allConditions;
+//
+//    SimplePredicate simplePredicate = getWakeLockHeldCondition(
+//            true /*nesting*/, true /*default to false*/, false /*slice output by uid*/,
+//            Position::ANY /* position */);
+//    string conditionName = "WL_HELD";
+//
+//    unordered_map<int64_t, int> trackerNameIndexMap;
+//    trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+//    trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+//    trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+//    SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+//                                            0 /*condition tracker index*/, simplePredicate,
+//                                            trackerNameIndexMap);
+//
+//    EXPECT_FALSE(conditionTracker.isSliced());
+//
+//    std::vector<int> uid_list1 = {111, 1111, 11111};
+//    string uid1_wl1 = "wl1_1";
+//    std::vector<int> uid_list2 = {222, 2222, 22222};
+//    string uid2_wl1 = "wl2_1";
+//
+//    LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+//    makeWakeLockEvent(&event, uid_list1, uid1_wl1, 1);
+//
+//    // one matched start for uid1
+//    vector<MatchingState> matcherState;
+//    matcherState.push_back(MatchingState::kMatched);
+//    matcherState.push_back(MatchingState::kNotMatched);
+//    matcherState.push_back(MatchingState::kNotMatched);
+//    vector<sp<ConditionTracker>> allPredicates;
+//    vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+//    vector<bool> changedCache(1, false);
+//
+//    conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+//                                       changedCache);
+//
+//    EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+//    EXPECT_TRUE(changedCache[0]);
+//
+//    // Now test query
+//    ConditionKey queryKey;
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//
+//    conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                    true,
+//                                    conditionCache);
+//    EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+//    // another wake lock acquired by this uid
+//    LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+//    makeWakeLockEvent(&event2, uid_list2, uid2_wl1, 1);
+//    matcherState.clear();
+//    matcherState.push_back(MatchingState::kMatched);
+//    matcherState.push_back(MatchingState::kNotMatched);
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    changedCache[0] = false;
+//    conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+//                                       changedCache);
+//    EXPECT_FALSE(changedCache[0]);
+//
+//    // uid1 wake lock 1 release
+//    LogEvent event3(1 /*tagId*/, 0 /*timestamp*/);
+//    makeWakeLockEvent(&event3, uid_list1, uid1_wl1, 0);  // now release it.
+//    matcherState.clear();
+//    matcherState.push_back(MatchingState::kNotMatched);
+//    matcherState.push_back(MatchingState::kMatched);
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    changedCache[0] = false;
+//    conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+//                                       changedCache);
+//    // nothing changes, because uid2 is still holding wl.
+//    EXPECT_FALSE(changedCache[0]);
+//
+//    LogEvent event4(1 /*tagId*/, 0 /*timestamp*/);
+//    makeWakeLockEvent(&event4, uid_list2, uid2_wl1, 0);  // now release it.
+//    matcherState.clear();
+//    matcherState.push_back(MatchingState::kNotMatched);
+//    matcherState.push_back(MatchingState::kMatched);
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    changedCache[0] = false;
+//    conditionTracker.evaluateCondition(event4, matcherState, allPredicates, conditionCache,
+//                                       changedCache);
+//    EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+//    EXPECT_TRUE(changedCache[0]);
+//
+//    // query again
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                    true,
+//                                    conditionCache);
+//    EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//}
+//
+//TEST(SimpleConditionTrackerTest, TestStopAll) {
+//    std::vector<sp<ConditionTracker>> allConditions;
+//    for (Position position :
+//            { Position::FIRST, Position::LAST }) {
+//        SimplePredicate simplePredicate = getWakeLockHeldCondition(
+//                true /*nesting*/, true /*default to false*/, true /*output slice by uid*/,
+//                position);
+//        string conditionName = "WL_HELD_BY_UID3";
+//
+//        unordered_map<int64_t, int> trackerNameIndexMap;
+//        trackerNameIndexMap[StringToId("WAKE_LOCK_ACQUIRE")] = 0;
+//        trackerNameIndexMap[StringToId("WAKE_LOCK_RELEASE")] = 1;
+//        trackerNameIndexMap[StringToId("RELEASE_ALL")] = 2;
+//
+//        SimpleConditionTracker conditionTracker(kConfigKey, StringToId(conditionName),
+//                                                0 /*condition tracker index*/, simplePredicate,
+//                                                trackerNameIndexMap);
+//
+//        std::vector<int> uid_list1 = {111, 1111, 11111};
+//        std::vector<int> uid_list2 = {222, 2222, 22222};
+//
+//        LogEvent event(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event, uid_list1, "wl1", 1);
+//
+//        // one matched start
+//        vector<MatchingState> matcherState;
+//        matcherState.push_back(MatchingState::kMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        vector<sp<ConditionTracker>> allPredicates;
+//        vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+//        vector<bool> changedCache(1, false);
+//
+//        conditionTracker.evaluateCondition(event, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(1UL, conditionTracker.mSlicedConditionState.size());
+//        } else {
+//            EXPECT_EQ(uid_list1.size(), conditionTracker.mSlicedConditionState.size());
+//        }
+//        EXPECT_TRUE(changedCache[0]);
+//        {
+//            if (position == Position::FIRST ||
+//                position == Position::LAST) {
+//                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//            } else {
+//                EXPECT_EQ(uid_list1.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//            }
+//        }
+//
+//        // Now test query
+//        const auto queryKey = getWakeLockQueryKey(position, uid_list1, conditionName);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+//        // another wake lock acquired by uid2
+//        LogEvent event2(1 /*tagId*/, 0 /*timestamp*/);
+//        makeWakeLockEvent(&event2, uid_list2, "wl2", 1);
+//        matcherState.clear();
+//        matcherState.push_back(MatchingState::kMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        changedCache[0] = false;
+//        conditionTracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        if (position == Position::FIRST ||
+//            position == Position::LAST) {
+//            EXPECT_EQ(2UL, conditionTracker.mSlicedConditionState.size());
+//        } else {
+//            EXPECT_EQ(uid_list1.size() + uid_list2.size(),
+//                      conditionTracker.mSlicedConditionState.size());
+//        }
+//        EXPECT_TRUE(changedCache[0]);
+//        {
+//            if (position == Position::FIRST ||
+//                position == Position::LAST) {
+//                EXPECT_EQ(1UL, conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//            } else {
+//                EXPECT_EQ(uid_list2.size(), conditionTracker.getChangedToTrueDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToFalseDimensions(allConditions)->empty());
+//            }
+//        }
+//
+//
+//        // TEST QUERY
+//        const auto queryKey2 = getWakeLockQueryKey(position, uid_list2, conditionName);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//
+//        EXPECT_EQ(ConditionState::kTrue, conditionCache[0]);
+//
+//
+//        // stop all event
+//        LogEvent event3(2 /*tagId*/, 0 /*timestamp*/);
+//        matcherState.clear();
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kNotMatched);
+//        matcherState.push_back(MatchingState::kMatched);
+//
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        changedCache[0] = false;
+//        conditionTracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache,
+//                                           changedCache);
+//        EXPECT_TRUE(changedCache[0]);
+//        EXPECT_EQ(0UL, conditionTracker.mSlicedConditionState.size());
+//        {
+//            if (position == Position::FIRST || position == Position::LAST) {
+//                EXPECT_EQ(2UL, conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+//            } else {
+//                EXPECT_EQ(uid_list1.size() + uid_list2.size(),
+//                          conditionTracker.getChangedToFalseDimensions(allConditions)->size());
+//                EXPECT_TRUE(conditionTracker.getChangedToTrueDimensions(allConditions)->empty());
+//            }
+//        }
+//
+//        // TEST QUERY
+//        const auto queryKey3 = getWakeLockQueryKey(position, uid_list1, conditionName);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//
+//        // TEST QUERY
+//        const auto queryKey4 = getWakeLockQueryKey(position, uid_list2, conditionName);
+//        conditionCache[0] = ConditionState::kNotEvaluated;
+//        conditionTracker.isConditionMet(queryKey, allPredicates,
+//                                        false,
+//                                        conditionCache);
+//        EXPECT_EQ(ConditionState::kFalse, conditionCache[0]);
+//    }
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
index fbf6efd..86b50ae8 100644
--- a/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
+++ b/cmds/statsd/tests/condition/StateConditionTracker_test.cpp
@@ -44,65 +44,66 @@
     return simplePredicate;
 }
 
-void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
-    event->write(uid);
-    event->write(state);
-    event->init();
-}
-
-TEST(StateConditionTrackerTest, TestStateChange) {
-    int uid1 = 111;
-    int uid2 = 222;
-
-    int state1 = 1001;
-    int state2 = 1002;
-    unordered_map<int64_t, int> trackerNameIndexMap;
-    trackerNameIndexMap[StringToId("UidProcState")] = 0;
-    vector<Matcher> primaryFields;
-    primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
-    StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
-                         trackerNameIndexMap, primaryFields);
-
-    LogEvent event(kUidProcTag, 0 /*timestamp*/);
-    makeUidProcStateEvent(uid1, state1, &event);
-
-    vector<MatchingState> matcherState;
-    matcherState.push_back(MatchingState::kMatched);
-    vector<sp<ConditionTracker>> allPredicates;
-    vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
-    vector<bool> changedCache(1, false);
-
-    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
-    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-    EXPECT_TRUE(changedCache[0]);
-
-    changedCache[0] = false;
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
-    EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
-    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-    EXPECT_FALSE(changedCache[0]);
-
-    LogEvent event2(kUidProcTag, 0 /*timestamp*/);
-    makeUidProcStateEvent(uid1, state2, &event2);
-
-    changedCache[0] = false;
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
-    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-    EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
-    EXPECT_TRUE(changedCache[0]);
-
-    LogEvent event3(kUidProcTag, 0 /*timestamp*/);
-    makeUidProcStateEvent(uid2, state1, &event3);
-    changedCache[0] = false;
-    conditionCache[0] = ConditionState::kNotEvaluated;
-    tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
-    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
-    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
-    EXPECT_TRUE(changedCache[0]);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//void makeUidProcStateEvent(int32_t uid, int32_t state, LogEvent* event) {
+//    event->write(uid);
+//    event->write(state);
+//    event->init();
+//}
+//
+//TEST(StateConditionTrackerTest, TestStateChange) {
+//    int uid1 = 111;
+//    int uid2 = 222;
+//
+//    int state1 = 1001;
+//    int state2 = 1002;
+//    unordered_map<int64_t, int> trackerNameIndexMap;
+//    trackerNameIndexMap[StringToId("UidProcState")] = 0;
+//    vector<Matcher> primaryFields;
+//    primaryFields.push_back(getSimpleMatcher(kUidProcTag, 1));
+//    StateConditionTracker tracker(ConfigKey(12, 123), 123, 0, getUidProcStatePredicate(),
+//                         trackerNameIndexMap, primaryFields);
+//
+//    LogEvent event(kUidProcTag, 0 /*timestamp*/);
+//    makeUidProcStateEvent(uid1, state1, &event);
+//
+//    vector<MatchingState> matcherState;
+//    matcherState.push_back(MatchingState::kMatched);
+//    vector<sp<ConditionTracker>> allPredicates;
+//    vector<ConditionState> conditionCache(1, ConditionState::kNotEvaluated);
+//    vector<bool> changedCache(1, false);
+//
+//    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
+//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+//    EXPECT_TRUE(changedCache[0]);
+//
+//    changedCache[0] = false;
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    tracker.evaluateCondition(event, matcherState, allPredicates, conditionCache, changedCache);
+//    EXPECT_EQ(0ULL, tracker.mLastChangedToTrueDimensions.size());
+//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+//    EXPECT_FALSE(changedCache[0]);
+//
+//    LogEvent event2(kUidProcTag, 0 /*timestamp*/);
+//    makeUidProcStateEvent(uid1, state2, &event2);
+//
+//    changedCache[0] = false;
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    tracker.evaluateCondition(event2, matcherState, allPredicates, conditionCache, changedCache);
+//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+//    EXPECT_EQ(1ULL, tracker.mLastChangedToFalseDimensions.size());
+//    EXPECT_TRUE(changedCache[0]);
+//
+//    LogEvent event3(kUidProcTag, 0 /*timestamp*/);
+//    makeUidProcStateEvent(uid2, state1, &event3);
+//    changedCache[0] = false;
+//    conditionCache[0] = ConditionState::kNotEvaluated;
+//    tracker.evaluateCondition(event3, matcherState, allPredicates, conditionCache, changedCache);
+//    EXPECT_EQ(1ULL, tracker.mLastChangedToTrueDimensions.size());
+//    EXPECT_EQ(0ULL, tracker.mLastChangedToFalseDimensions.size());
+//    EXPECT_TRUE(changedCache[0]);
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
index c78d99e..1eaaf08 100644
--- a/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_count_e2e_test.cpp
@@ -53,184 +53,185 @@
 
 }  // namespace
 
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
-    const int num_buckets = 1;
-    const int threshold = 3;
-    auto config = CreateStatsdConfig(num_buckets, threshold);
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
-    sp<AnomalyTracker> anomalyTracker =
-        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    std::vector<AttributionNodeInternal> attributions2 = {
-        CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
-    std::vector<AttributionNodeInternal> attributions3 = {
-        CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions4 = {
-        CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions5 = {
-        CreateAttribution(222, "GMSCoreModule1") };
-
-    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)111));
-    HashableDimensionKey whatKey1({fieldValue1});
-    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
-    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)222));
-    HashableDimensionKey whatKey2({fieldValue2});
-    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    // Fired alarm and refractory period end timestamp updated.
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-}
-
-TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
-    const int num_buckets = 3;
-    const int threshold = 3;
-    auto config = CreateStatsdConfig(num_buckets, threshold);
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
-    sp<AnomalyTracker> anomalyTracker =
-        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-    std::vector<AttributionNodeInternal> attributions2 = {
-        CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
-    std::vector<AttributionNodeInternal> attributions3 = {
-        CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions4 = {
-        CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions5 = {
-        CreateAttribution(222, "GMSCoreModule1") };
-
-    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)111));
-    HashableDimensionKey whatKey1({fieldValue1});
-    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
-    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)222));
-    HashableDimensionKey whatKey2({fieldValue2});
-    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    // Fired alarm and refractory period end timestamp updated.
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-
-    event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
-    processor->OnLogEvent(event.get());
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_single_bucket) {
+//    const int num_buckets = 1;
+//    const int threshold = 3;
+//    auto config = CreateStatsdConfig(num_buckets, threshold);
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+//    sp<AnomalyTracker> anomalyTracker =
+//        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    std::vector<AttributionNodeInternal> attributions2 = {
+//        CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
+//    std::vector<AttributionNodeInternal> attributions3 = {
+//        CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions4 = {
+//        CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions5 = {
+//        CreateAttribution(222, "GMSCoreModule1") };
+//
+//    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)111));
+//    HashableDimensionKey whatKey1({fieldValue1});
+//    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+//    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)222));
+//    HashableDimensionKey whatKey2({fieldValue2});
+//    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 3);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    event = CreateAcquireWakelockEvent(attributions3, "wl1", bucketStartTimeNs + 4);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + 4);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    // Fired alarm and refractory period end timestamp updated.
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 5);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 100);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + bucketStartTimeNs / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs - 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions4, "wl2", bucketStartTimeNs + bucketSizeNs + 1);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 3);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    event = CreateAcquireWakelockEvent(attributions5, "wl2", bucketStartTimeNs + bucketSizeNs + 4);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 4) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//}
+//
+//TEST(AnomalyDetectionE2eTest, TestSlicedCountMetric_multiple_buckets) {
+//    const int num_buckets = 3;
+//    const int threshold = 3;
+//    auto config = CreateStatsdConfig(num_buckets, threshold);
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+//    sp<AnomalyTracker> anomalyTracker =
+//        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//    std::vector<AttributionNodeInternal> attributions2 = {
+//        CreateAttribution(111, "App1"), CreateAttribution(222, "GMSCoreModule1")};
+//    std::vector<AttributionNodeInternal> attributions3 = {
+//        CreateAttribution(111, "App1"), CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions4 = {
+//        CreateAttribution(222, "GMSCoreModule1"), CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions5 = {
+//        CreateAttribution(222, "GMSCoreModule1") };
+//
+//    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)111));
+//    HashableDimensionKey whatKey1({fieldValue1});
+//    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+//    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)222));
+//    HashableDimensionKey whatKey2({fieldValue2});
+//    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 3);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    // Fired alarm and refractory period end timestamp updated.
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 4);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 1);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + bucketSizeNs + 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//
+//    event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 3 * bucketSizeNs + 2);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + 3 * bucketSizeNs + 2) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey1));
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
index 50da9e2..03a209a 100644
--- a/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Anomaly_duration_sum_e2e_test.cpp
@@ -89,393 +89,394 @@
                                            (int32_t)0x02010101), Value((int32_t)222))}),
     DEFAULT_DIMENSION_KEY);
 
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
-    const int num_buckets = 1;
-    const uint64_t threshold_ns = NS_PER_SEC;
-    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
-    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
-    sp<AnomalyTracker> anomalyTracker =
-        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
-    auto screen_on_event = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
-    auto screen_off_event = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
-    processor->OnLogEvent(screen_on_event.get());
-    processor->OnLogEvent(screen_off_event.get());
-
-    // Acquire wakelock wl1.
-    auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
-    auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire wakelock wl1 within bucket #0.
-    acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Release wakelock wl1. One anomaly detected.
-    release_event = CreateReleaseWakelockEvent(
-            attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire wakelock wl1.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
-    processor->OnLogEvent(acquire_event.get());
-    // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
-    // end of the refractory period.
-    const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
-    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
-              (uint32_t)alarmFiredTimestampSec0);
-
-    // Anomaly alarm fired.
-    auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
-            static_cast<uint32_t>(alarmFiredTimestampSec0));
-    EXPECT_EQ(1u, alarmSet.size());
-    processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Release wakelock wl1.
-    release_event = CreateReleaseWakelockEvent(
-            attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    // Within refractory period. No more anomaly detected.
-    EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire wakelock wl1.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs -  5 * NS_PER_SEC - 11);
-    processor->OnLogEvent(acquire_event.get());
-    const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
-              (uint64_t)alarmFiredTimestampSec1);
-
-    // Release wakelock wl1.
-    release_event = CreateReleaseWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
-                static_cast<uint32_t>(alarmFiredTimestampSec1));
-    EXPECT_EQ(0u, alarmSet.size());
-
-    // Acquire wakelock wl1 near the end of bucket #0.
-    acquire_event = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
-               anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    // Release the event at early bucket #1.
-    release_event = CreateReleaseWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    // Anomaly detected when stopping the alarm. The refractory period does not change.
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Condition changes to false.
-    screen_on_event = CreateScreenStateChangedEvent(
-        android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-        bucketStartTimeNs + 2 * bucketSizeNs + 20);
-    processor->OnLogEvent(screen_on_event.get());
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
-    processor->OnLogEvent(acquire_event.get());
-    // The condition is false. Do not start the alarm.
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Condition turns true.
-    screen_off_event = CreateScreenStateChangedEvent(
-        android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-        bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
-    processor->OnLogEvent(screen_off_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    // Condition turns to false.
-    screen_on_event = CreateScreenStateChangedEvent(
-        android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-        bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
-    processor->OnLogEvent(screen_on_event.get());
-    // Condition turns to false. Cancelled the alarm.
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    //  Detected one anomaly.
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Condition turns to true again.
-    screen_off_event = CreateScreenStateChangedEvent(
-        android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-        bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
-    processor->OnLogEvent(screen_off_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    release_event = CreateReleaseWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(refractory_period_sec +
-                    (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-}
-
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
-    const int num_buckets = 3;
-    const uint64_t threshold_ns = NS_PER_SEC;
-    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
-    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
-    sp<AnomalyTracker> anomalyTracker =
-        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
-    auto screen_off_event = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
-    processor->OnLogEvent(screen_off_event.get());
-
-    // Acquire wakelock "wc1" in bucket #0.
-    auto acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs -  NS_PER_SEC / 2 - 1);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Release wakelock "wc1" in bucket #0.
-    auto release_event = CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire wakelock "wc1" in bucket #1.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    release_event = CreateReleaseWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire wakelock "wc2" in bucket #2.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 2 *  bucketSizeNs) / NS_PER_SEC + 2,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey2));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    // Release wakelock "wc2" in bucket #2.
-    release_event = CreateReleaseWakelockEvent(
-        attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
-    EXPECT_EQ(refractory_period_sec +
-                   (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
-
-    // Acquire wakelock "wc1" in bucket #2.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Release wakelock "wc1" in bucket #2.
-    release_event = CreateReleaseWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec +
-                   (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
-    processor->OnLogEvent(acquire_event.get());
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey2));
-
-    release_event = CreateReleaseWakelockEvent(
-        attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
-    processor->OnLogEvent(release_event.get());
-    release_event = CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
-    // The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
-    EXPECT_EQ(refractory_period_sec +
-                   (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-}
-
-TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
-    const int num_buckets = 2;
-    const uint64_t threshold_ns = 3 * NS_PER_SEC;
-    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
-    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
-
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
-    config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
-
-    sp<AnomalyTracker> anomalyTracker =
-        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
-
-    auto screen_off_event = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
-    processor->OnLogEvent(screen_off_event.get());
-
-    // Acquire wakelock "wc1" in bucket #0.
-    auto acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Acquire the wakelock "wc1" again.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
-    processor->OnLogEvent(acquire_event.get());
-    // The alarm does not change.
-    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // Anomaly alarm fired late.
-    const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
-    auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
-            static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
-    EXPECT_EQ(1u, alarmSet.size());
-    processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    auto release_event = CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-    // Within the refractory period. No anomaly.
-    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    // A new wakelock, but still within refractory period.
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    release_event = CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
-    // Still in the refractory period. No anomaly.
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
-              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
-
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    release_event = CreateReleaseWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
-    processor->OnLogEvent(release_event.get());
-    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
-
-    acquire_event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
-    processor->OnLogEvent(acquire_event.get());
-    EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
-              anomalyTracker->getAlarmTimestampSec(dimensionKey));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_single_bucket) {
+//    const int num_buckets = 1;
+//    const uint64_t threshold_ns = NS_PER_SEC;
+//    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+//    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+//    sp<AnomalyTracker> anomalyTracker =
+//        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+//    auto screen_on_event = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
+//    auto screen_off_event = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 10);
+//    processor->OnLogEvent(screen_on_event.get());
+//    processor->OnLogEvent(screen_off_event.get());
+//
+//    // Acquire wakelock wl1.
+//    auto acquire_event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 11);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 11 + threshold_ns) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Release wakelock wl1. No anomaly detected. Alarm cancelled at the "release" event.
+//    auto release_event = CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 101);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire wakelock wl1 within bucket #0.
+//    acquire_event = CreateAcquireWakelockEvent(attributions2, "wl1", bucketStartTimeNs + 110);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 110 + threshold_ns - 90) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Release wakelock wl1. One anomaly detected.
+//    release_event = CreateReleaseWakelockEvent(
+//            attributions2, "wl1", bucketStartTimeNs + NS_PER_SEC + 109);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire wakelock wl1.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + NS_PER_SEC + 112);
+//    processor->OnLogEvent(acquire_event.get());
+//    // Wakelock has been hold longer than the threshold in bucket #0. The alarm is set at the
+//    // end of the refractory period.
+//    const int64_t alarmFiredTimestampSec0 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
+//    EXPECT_EQ(refractory_period_sec + (bucketStartTimeNs + NS_PER_SEC + 109) / NS_PER_SEC + 1,
+//              (uint32_t)alarmFiredTimestampSec0);
+//
+//    // Anomaly alarm fired.
+//    auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+//            static_cast<uint32_t>(alarmFiredTimestampSec0));
+//    EXPECT_EQ(1u, alarmSet.size());
+//    processor->onAnomalyAlarmFired(alarmFiredTimestampSec0 * NS_PER_SEC, alarmSet);
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Release wakelock wl1.
+//    release_event = CreateReleaseWakelockEvent(
+//            attributions1, "wl1", alarmFiredTimestampSec0 * NS_PER_SEC + NS_PER_SEC + 1);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    // Within refractory period. No more anomaly detected.
+//    EXPECT_EQ(refractory_period_sec + alarmFiredTimestampSec0,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire wakelock wl1.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs -  5 * NS_PER_SEC - 11);
+//    processor->OnLogEvent(acquire_event.get());
+//    const int64_t alarmFiredTimestampSec1 = anomalyTracker->getAlarmTimestampSec(dimensionKey);
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs - 5 * NS_PER_SEC) / NS_PER_SEC,
+//              (uint64_t)alarmFiredTimestampSec1);
+//
+//    // Release wakelock wl1.
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + bucketSizeNs - 4 * NS_PER_SEC - 10) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+//                static_cast<uint32_t>(alarmFiredTimestampSec1));
+//    EXPECT_EQ(0u, alarmSet.size());
+//
+//    // Acquire wakelock wl1 near the end of bucket #0.
+//    acquire_event = CreateAcquireWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 2);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC,
+//               anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    // Release the event at early bucket #1.
+//    release_event = CreateReleaseWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + NS_PER_SEC - 1);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    // Anomaly detected when stopping the alarm. The refractory period does not change.
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Condition changes to false.
+//    screen_on_event = CreateScreenStateChangedEvent(
+//        android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//        bucketStartTimeNs + 2 * bucketSizeNs + 20);
+//    processor->OnLogEvent(screen_on_event.get());
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 30);
+//    processor->OnLogEvent(acquire_event.get());
+//    // The condition is false. Do not start the alarm.
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + bucketSizeNs + NS_PER_SEC) / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Condition turns true.
+//    screen_off_event = CreateScreenStateChangedEvent(
+//        android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//        bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC);
+//    processor->OnLogEvent(screen_off_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs + NS_PER_SEC + threshold_ns) / NS_PER_SEC,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    // Condition turns to false.
+//    screen_on_event = CreateScreenStateChangedEvent(
+//        android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//        bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1);
+//    processor->OnLogEvent(screen_on_event.get());
+//    // Condition turns to false. Cancelled the alarm.
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    //  Detected one anomaly.
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 1) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Condition turns to true again.
+//    screen_off_event = CreateScreenStateChangedEvent(
+//        android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//        bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC + 2);
+//    processor->OnLogEvent(screen_off_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 2 + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(refractory_period_sec +
+//                    (bucketStartTimeNs + 2 * bucketSizeNs + 5 * NS_PER_SEC) / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//}
+//
+//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_multiple_buckets) {
+//    const int num_buckets = 3;
+//    const uint64_t threshold_ns = NS_PER_SEC;
+//    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, true);
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+//    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+//    sp<AnomalyTracker> anomalyTracker =
+//        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+//    auto screen_off_event = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
+//    processor->OnLogEvent(screen_off_event.get());
+//
+//    // Acquire wakelock "wc1" in bucket #0.
+//    auto acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs -  NS_PER_SEC / 2 - 1);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Release wakelock "wc1" in bucket #0.
+//    auto release_event = CreateReleaseWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 1);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire wakelock "wc1" in bucket #1.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 1);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + bucketSizeNs + 100);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire wakelock "wc2" in bucket #2.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 2 *  bucketSizeNs) / NS_PER_SEC + 2,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    // Release wakelock "wc2" in bucket #2.
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions3, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+//    EXPECT_EQ(refractory_period_sec +
+//                   (bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC) / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey2));
+//
+//    // Acquire wakelock "wc1" in bucket #2.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2 * NS_PER_SEC);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 2 * bucketSizeNs) / NS_PER_SEC + 2 + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Release wakelock "wc1" in bucket #2.
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec +
+//                   (int64_t)(bucketStartTimeNs + 2 * bucketSizeNs + 2.5 * NS_PER_SEC) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 4);
+//    processor->OnLogEvent(acquire_event.get());
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs - NS_PER_SEC + 5);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ((bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+//
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions3, "wl2", bucketStartTimeNs + 6 * bucketSizeNs + 2);
+//    processor->OnLogEvent(release_event.get());
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 6 * bucketSizeNs + 6);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey2));
+//    // The buckets are not messed up across dimensions. Only one dimension has anomaly triggered.
+//    EXPECT_EQ(refractory_period_sec +
+//                   (int64_t)(bucketStartTimeNs + 6 * bucketSizeNs) / NS_PER_SEC + 1,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//}
+//
+//TEST(AnomalyDetectionE2eTest, TestDurationMetric_SUM_long_refractory_period) {
+//    const int num_buckets = 2;
+//    const uint64_t threshold_ns = 3 * NS_PER_SEC;
+//    auto config = CreateStatsdConfig(num_buckets, threshold_ns, DurationMetric::SUM, false);
+//    int64_t bucketStartTimeNs = 10 * NS_PER_SEC;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000;
+//
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = 3 * bucketSizeNs / NS_PER_SEC;
+//    config.mutable_alert(0)->set_refractory_period_secs(refractory_period_sec);
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    EXPECT_EQ(1u, processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers.size());
+//
+//    sp<AnomalyTracker> anomalyTracker =
+//        processor->mMetricsManagers.begin()->second->mAllAnomalyTrackers[0];
+//
+//    auto screen_off_event = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 1);
+//    processor->OnLogEvent(screen_off_event.get());
+//
+//    // Acquire wakelock "wc1" in bucket #0.
+//    auto acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs - 100);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Acquire the wakelock "wc1" again.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2 * NS_PER_SEC + 1);
+//    processor->OnLogEvent(acquire_event.get());
+//    // The alarm does not change.
+//    EXPECT_EQ((bucketStartTimeNs + bucketSizeNs) / NS_PER_SEC + 3,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(0u, anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // Anomaly alarm fired late.
+//    const int64_t firedAlarmTimestampNs = bucketStartTimeNs + 2 * bucketSizeNs - NS_PER_SEC;
+//    auto alarmSet = processor->getAnomalyAlarmMonitor()->popSoonerThan(
+//            static_cast<uint32_t>(firedAlarmTimestampNs / NS_PER_SEC));
+//    EXPECT_EQ(1u, alarmSet.size());
+//    processor->onAnomalyAlarmFired(firedAlarmTimestampNs, alarmSet);
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs - 100);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    auto release_event = CreateReleaseWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//    // Within the refractory period. No anomaly.
+//    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    // A new wakelock, but still within refractory period.
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 2 * bucketSizeNs + 10 * NS_PER_SEC);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 3 * bucketSizeNs - NS_PER_SEC);
+//    // Still in the refractory period. No anomaly.
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(refractory_period_sec + firedAlarmTimestampNs / NS_PER_SEC,
+//              anomalyTracker->getRefractoryPeriodEndsSec(dimensionKey));
+//
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 5);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    release_event = CreateReleaseWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 4);
+//    processor->OnLogEvent(release_event.get());
+//    EXPECT_EQ(0u, anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//
+//    acquire_event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 5 * bucketSizeNs - 3 * NS_PER_SEC - 3);
+//    processor->OnLogEvent(acquire_event.get());
+//    EXPECT_EQ((bucketStartTimeNs + 5 * bucketSizeNs) / NS_PER_SEC,
+//              anomalyTracker->getAlarmTimestampSec(dimensionKey));
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
index 3382525..6051174 100644
--- a/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/Attribution_e2e_test.cpp
@@ -55,364 +55,365 @@
 
 }  // namespace
 
-TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
-    auto config = CreateStatsdConfig(Position::FIRST);
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    // Here it assumes that GMS core has two uids.
-    processor->getUidMap()->updateMap(
-            1, {222, 444, 111, 333}, {1, 1, 2, 2},
-            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
-            {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")},
-            {String16(""), String16(""), String16(""), String16("")});
-
-    // GMS core node is in the middle.
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(222, "GMSCoreModule1"),
-                                                          CreateAttribution(333, "App3")};
-
-    // GMS core node is the last one.
-    std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(333, "App3"),
-                                                          CreateAttribution(222, "GMSCoreModule1")};
-
-    // GMS core node is the first one.
-    std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
-                                                          CreateAttribution(333, "App3")};
-
-    // Single GMS core node.
-    std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
-
-    // GMS core has another uid.
-    std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(444, "GMSCoreModule2"),
-                                                          CreateAttribution(333, "App3")};
-
-    // Multiple GMS core nodes.
-    std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
-                                                          CreateAttribution(222, "GMSCoreModule1")};
-
-    // No GMS core nodes.
-    std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
-
-    // GMS core node with isolated uid.
-    const int isolatedUid = 666;
-    std::vector<AttributionNodeInternal> attributions9 = {
-            CreateAttribution(isolatedUid, "GMSCoreModule3")};
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-    // Events 1~4 are in the 1st bucket.
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 2));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 200));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
-
-    // Events 5~8 are in the 3rd bucket.
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
-    events.push_back(CreateIsolatedUidChangedEvent(
-        isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
-    events.push_back(CreateIsolatedUidChangedEvent(
-        isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(countMetrics.data_size(), 4);
-
-    auto data = countMetrics.data(0);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
-            "App1");
-    EXPECT_EQ(data.bucket_info_size(), 2);
-    EXPECT_EQ(data.bucket_info(0).count(), 2);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-
-    data = countMetrics.data(1);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
-            "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 2);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).count(), 1);
-    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-
-    data = countMetrics.data(2);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
-            "GMSCoreModule3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
-
-    data = countMetrics.data(3);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
-            "GMSCoreModule2");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
-}
-
-TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
-    auto config = CreateStatsdConfig(Position::ALL);
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    // Here it assumes that GMS core has two uids.
-    processor->getUidMap()->updateMap(
-            1, {222, 444, 111, 333}, {1, 1, 2, 2},
-            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
-            {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
-             String16("APP3")},
-            {String16(""), String16(""), String16(""), String16("")});
-
-    // GMS core node is in the middle.
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(222, "GMSCoreModule1"),
-                                                          CreateAttribution(333, "App3")};
-
-    // GMS core node is the last one.
-    std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(333, "App3"),
-                                                          CreateAttribution(222, "GMSCoreModule1")};
-
-    // GMS core node is the first one.
-    std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
-                                                          CreateAttribution(333, "App3")};
-
-    // Single GMS core node.
-    std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
-
-    // GMS core has another uid.
-    std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(444, "GMSCoreModule2"),
-                                                          CreateAttribution(333, "App3")};
-
-    // Multiple GMS core nodes.
-    std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
-                                                          CreateAttribution(222, "GMSCoreModule1")};
-
-    // No GMS core nodes.
-    std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
-                                                          CreateAttribution(333, "App3")};
-    std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
-
-    // GMS core node with isolated uid.
-    const int isolatedUid = 666;
-    std::vector<AttributionNodeInternal> attributions9 = {
-            CreateAttribution(isolatedUid, "GMSCoreModule1")};
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-    // Events 1~4 are in the 1st bucket.
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 2));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions2, "wl1", bucketStartTimeNs + 200));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
-
-    // Events 5~8 are in the 3rd bucket.
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
-    events.push_back(CreateAcquireWakelockEvent(
-        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
-    events.push_back(CreateIsolatedUidChangedEvent(
-        isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
-    events.push_back(CreateIsolatedUidChangedEvent(
-        isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(countMetrics.data_size(), 6);
-
-    auto data = countMetrics.data(0);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(1).count());
-    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-              data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
-              data.bucket_info(1).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    ValidateUidDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
-    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
-
-    data = countMetrics.data(2);
-    ValidateUidDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    ValidateUidDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(bucketStartTimeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(4);
-    ValidateUidDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(bucketStartTimeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(5);
-    ValidateUidDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
-    ValidateUidDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
-    ValidateAttributionUidAndTagDimension(
-        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
-    EXPECT_EQ(data.bucket_info_size(), 1);
-    EXPECT_EQ(data.bucket_info(0).count(), 1);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByFirstUid) {
+//    auto config = CreateStatsdConfig(Position::FIRST);
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//    // Here it assumes that GMS core has two uids.
+//    processor->getUidMap()->updateMap(
+//            1, {222, 444, 111, 333}, {1, 1, 2, 2},
+//            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
+//            {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+//             String16("APP3")},
+//            {String16(""), String16(""), String16(""), String16("")});
+//
+//    // GMS core node is in the middle.
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(222, "GMSCoreModule1"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // GMS core node is the last one.
+//    std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(333, "App3"),
+//                                                          CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // GMS core node is the first one.
+//    std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // Single GMS core node.
+//    std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // GMS core has another uid.
+//    std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(444, "GMSCoreModule2"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // Multiple GMS core nodes.
+//    std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
+//                                                          CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // No GMS core nodes.
+//    std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
+//
+//    // GMS core node with isolated uid.
+//    const int isolatedUid = 666;
+//    std::vector<AttributionNodeInternal> attributions9 = {
+//            CreateAttribution(isolatedUid, "GMSCoreModule3")};
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    // Events 1~4 are in the 1st bucket.
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 2));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 200));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+//
+//    // Events 5~8 are in the 3rd bucket.
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+//    events.push_back(CreateIsolatedUidChangedEvent(
+//        isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+//    events.push_back(CreateIsolatedUidChangedEvent(
+//        isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+//
+//    sortLogEventsByTimestamp(&events);
+//
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(countMetrics.data_size(), 4);
+//
+//    auto data = countMetrics.data(0);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 111,
+//            "App1");
+//    EXPECT_EQ(data.bucket_info_size(), 2);
+//    EXPECT_EQ(data.bucket_info(0).count(), 2);
+//    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+//    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(1).count(), 1);
+//    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+//
+//    data = countMetrics.data(1);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+//            "GMSCoreModule1");
+//    EXPECT_EQ(data.bucket_info_size(), 2);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+//    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(1).count(), 1);
+//    EXPECT_EQ(data.bucket_info(1).start_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(1).end_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+//
+//    data = countMetrics.data(2);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222,
+//            "GMSCoreModule3");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 4 * bucketSizeNs);
+//
+//    data = countMetrics.data(3);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 444,
+//            "GMSCoreModule2");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs + 2 * bucketSizeNs);
+//    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + 3 * bucketSizeNs);
+//}
+//
+//TEST(AttributionE2eTest, TestAttributionMatchAndSliceByChain) {
+//    auto config = CreateStatsdConfig(Position::ALL);
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//    // Here it assumes that GMS core has two uids.
+//    processor->getUidMap()->updateMap(
+//            1, {222, 444, 111, 333}, {1, 1, 2, 2},
+//            {String16("v1"), String16("v1"), String16("v2"), String16("v2")},
+//            {String16("com.android.gmscore"), String16("com.android.gmscore"), String16("app1"),
+//             String16("APP3")},
+//            {String16(""), String16(""), String16(""), String16("")});
+//
+//    // GMS core node is in the middle.
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(222, "GMSCoreModule1"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // GMS core node is the last one.
+//    std::vector<AttributionNodeInternal> attributions2 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(333, "App3"),
+//                                                          CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // GMS core node is the first one.
+//    std::vector<AttributionNodeInternal> attributions3 = {CreateAttribution(222, "GMSCoreModule1"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // Single GMS core node.
+//    std::vector<AttributionNodeInternal> attributions4 = {CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // GMS core has another uid.
+//    std::vector<AttributionNodeInternal> attributions5 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(444, "GMSCoreModule2"),
+//                                                          CreateAttribution(333, "App3")};
+//
+//    // Multiple GMS core nodes.
+//    std::vector<AttributionNodeInternal> attributions6 = {CreateAttribution(444, "GMSCoreModule2"),
+//                                                          CreateAttribution(222, "GMSCoreModule1")};
+//
+//    // No GMS core nodes.
+//    std::vector<AttributionNodeInternal> attributions7 = {CreateAttribution(111, "App1"),
+//                                                          CreateAttribution(333, "App3")};
+//    std::vector<AttributionNodeInternal> attributions8 = {CreateAttribution(111, "App1")};
+//
+//    // GMS core node with isolated uid.
+//    const int isolatedUid = 666;
+//    std::vector<AttributionNodeInternal> attributions9 = {
+//            CreateAttribution(isolatedUid, "GMSCoreModule1")};
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    // Events 1~4 are in the 1st bucket.
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 2));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions2, "wl1", bucketStartTimeNs + 200));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions3, "wl1", bucketStartTimeNs + bucketSizeNs - 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions4, "wl1", bucketStartTimeNs + bucketSizeNs));
+//
+//    // Events 5~8 are in the 3rd bucket.
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions5, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions6, "wl2", bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions7, "wl2", bucketStartTimeNs + 3 * bucketSizeNs - 2));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions8, "wl2", bucketStartTimeNs + 3 * bucketSizeNs));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 1));
+//    events.push_back(CreateAcquireWakelockEvent(
+//        attributions9, "wl2", bucketStartTimeNs + 3 * bucketSizeNs + 100));
+//    events.push_back(CreateIsolatedUidChangedEvent(
+//        isolatedUid, 222, true/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs - 1));
+//    events.push_back(CreateIsolatedUidChangedEvent(
+//        isolatedUid, 222, false/* is_create*/, bucketStartTimeNs + 3 * bucketSizeNs + 10));
+//
+//    sortLogEventsByTimestamp(&events);
+//
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 4 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(countMetrics.data_size(), 6);
+//
+//    auto data = countMetrics.data(0);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(1).count());
+//    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//              data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + 4 * bucketSizeNs,
+//              data.bucket_info(1).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(data.bucket_info(0).start_bucket_elapsed_nanos(), bucketStartTimeNs);
+//    EXPECT_EQ(data.bucket_info(0).end_bucket_elapsed_nanos(), bucketStartTimeNs + bucketSizeNs);
+//
+//    data = countMetrics.data(2);
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(bucketStartTimeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(4);
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 222, "GMSCoreModule1");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(bucketStartTimeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(5);
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 0, android::util::WAKELOCK_STATE_CHANGED, 111, "App1");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 1, android::util::WAKELOCK_STATE_CHANGED, 444, "GMSCoreModule2");
+//    ValidateUidDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333);
+//    ValidateAttributionUidAndTagDimension(
+//        data.dimensions_in_what(), 2, android::util::WAKELOCK_STATE_CHANGED, 333, "App3");
+//    EXPECT_EQ(data.bucket_info_size(), 1);
+//    EXPECT_EQ(data.bucket_info(0).count(), 1);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
index 325e869..f8edee5 100644
--- a/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ConfigTtl_e2e_test.cpp
@@ -56,52 +56,53 @@
 
 }  // namespace
 
-TEST(ConfigTtlE2eTest, TestCountMetric) {
-    const int num_buckets = 1;
-    const int threshold = 3;
-    auto config = CreateStatsdConfig(num_buckets, threshold);
-    const uint64_t alert_id = config.alert(0).id();
-    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
-
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
-
-    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)111));
-    HashableDimensionKey whatKey1({fieldValue1});
-    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
-
-    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
-                           Value((int32_t)222));
-    HashableDimensionKey whatKey2({fieldValue2});
-    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
-
-    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
-    processor->OnLogEvent(event.get());
-
-    event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
-    processor->OnLogEvent(event.get());
-
-    event = CreateAcquireWakelockEvent(
-        attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
-    processor->OnLogEvent(event.get());
-
-    EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
-              processor->mMetricsManagers.begin()->second->getTtlEndNs());
-
-    // Clear the data stored on disk as a result of the ttl.
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
-                                ADB_DUMP, FAST, &buffer);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ConfigTtlE2eTest, TestCountMetric) {
+//    const int num_buckets = 1;
+//    const int threshold = 3;
+//    auto config = CreateStatsdConfig(num_buckets, threshold);
+//    const uint64_t alert_id = config.alert(0).id();
+//    const uint32_t refractory_period_sec = config.alert(0).refractory_period_secs();
+//
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(111, "App1")};
+//
+//    FieldValue fieldValue1(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)111));
+//    HashableDimensionKey whatKey1({fieldValue1});
+//    MetricDimensionKey dimensionKey1(whatKey1, DEFAULT_DIMENSION_KEY);
+//
+//    FieldValue fieldValue2(Field(android::util::WAKELOCK_STATE_CHANGED, (int32_t)0x02010101),
+//                           Value((int32_t)222));
+//    HashableDimensionKey whatKey2({fieldValue2});
+//    MetricDimensionKey dimensionKey2(whatKey2, DEFAULT_DIMENSION_KEY);
+//
+//    auto event = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateAcquireWakelockEvent(attributions1, "wl2", bucketStartTimeNs + bucketSizeNs + 2);
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateAcquireWakelockEvent(
+//        attributions1, "wl1", bucketStartTimeNs + 25 * bucketSizeNs + 2);
+//    processor->OnLogEvent(event.get());
+//
+//    EXPECT_EQ((int64_t)(bucketStartTimeNs + 25 * bucketSizeNs + 2 + 2 * 3600 * NS_PER_SEC),
+//              processor->mMetricsManagers.begin()->second->getTtlEndNs());
+//
+//    // Clear the data stored on disk as a result of the ttl.
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 25 * bucketSizeNs + 3, false, true,
+//                                ADB_DUMP, FAST, &buffer);
+//}
 
 
 #else
diff --git a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
index 15fc468..a1f74a6 100644
--- a/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/CountMetric_e2e_test.cpp
@@ -27,772 +27,773 @@
 
 #ifdef __ANDROID__
 
-/**
- * Test a count metric that has one slice_by_state with no primary fields.
- *
- * Once the CountMetricProducer is initialized, it has one atom id in
- * mSlicedStateAtoms and no entries in mStateGroupMap.
-
- * One StateTracker tracks the state atom, and it has one listener which is the
- * CountMetricProducer that was initialized.
- */
-TEST(CountMetricE2eTest, TestSlicedState) {
-    // Initialize config.
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-
-    auto syncStartMatcher = CreateSyncStartAtomMatcher();
-    *config.add_atom_matcher() = syncStartMatcher;
-
-    auto state = CreateScreenState();
-    *config.add_state() = state;
-
-    // Create count metric that slices by screen state.
-    int64_t metricId = 123456;
-    auto countMetric = config.add_count_metric();
-    countMetric->set_id(metricId);
-    countMetric->set_what(syncStartMatcher.id());
-    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
-    countMetric->add_slice_by_state(state.id());
-
-    // Initialize StatsLogProcessor.
-    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
-    const uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
-    // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
-
-    // Check that StateTrackers were initialized correctly.
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
-    /*
-               bucket #1                      bucket #2
-    |     1     2     3     4     5     6     7     8     9     10 (minutes)
-    |-----------------------------|-----------------------------|--
-            x                x         x    x        x      x       (syncStartEvents)
-          |                                       |                 (ScreenIsOnEvent)
-                   |     |                                          (ScreenIsOffEvent)
-                                                        |           (ScreenUnknownEvent)
-    */
-    // Initialize log events - first bucket.
-    int appUid = 123;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 50 * NS_PER_SEC));  // 1:00
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 75 * NS_PER_SEC));  // 1:25
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
-
-    // Initialize log events - second bucket.
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 350 * NS_PER_SEC));  // 6:00
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 400 * NS_PER_SEC));  // 6:50
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 450 * NS_PER_SEC));  // 7:40
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 475 * NS_PER_SEC));  // 8:05
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
-                                          bucketStartTimeNs + 500 * NS_PER_SEC));  // 8:30
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 520 * NS_PER_SEC));  // 8:50
-
-    // Send log events to StatsLogProcessor.
-    for (auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    // Check dump report.
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
-                            FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
-    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    // For each CountMetricData, check StateValue info is correct and buckets
-    // have correct counts.
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(1, data.bucket_info(1).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(2, data.bucket_info(1).count());
-}
-
-/**
- * Test a count metric that has one slice_by_state with a mapping and no
- * primary fields.
- *
- * Once the CountMetricProducer is initialized, it has one atom id in
- * mSlicedStateAtoms and has one entry per state value in mStateGroupMap.
- *
- * One StateTracker tracks the state atom, and it has one listener which is the
- * CountMetricProducer that was initialized.
- */
-TEST(CountMetricE2eTest, TestSlicedStateWithMap) {
-    // Initialize config.
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-
-    auto syncStartMatcher = CreateSyncStartAtomMatcher();
-    *config.add_atom_matcher() = syncStartMatcher;
-
-    auto state = CreateScreenStateWithOnOffMap();
-    *config.add_state() = state;
-
-    // Create count metric that slices by screen state with on/off map.
-    int64_t metricId = 123456;
-    auto countMetric = config.add_count_metric();
-    countMetric->set_id(metricId);
-    countMetric->set_what(syncStartMatcher.id());
-    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
-    countMetric->add_slice_by_state(state.id());
-
-    // Initialize StatsLogProcessor.
-    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
-    const uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
-    // Check that StateTrackers were initialized correctly.
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
-    // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
-
-    StateMap map = state.map();
-    for (auto group : map.group()) {
-        for (auto value : group.value()) {
-            EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
-                      group.group_id());
-        }
-    }
-
-    /*
-               bucket #1                      bucket #2
-    |     1     2     3     4     5     6     7     8     9     10 (minutes)
-    |-----------------------------|-----------------------------|--
-      x   x     x       x    x   x      x         x         x       (syncStartEvents)
-     -----------------------------------------------------------SCREEN_OFF events
-       |                                                            (ScreenStateUnknownEvent = 0)
-             |                  |                                   (ScreenStateOffEvent = 1)
-                          |                                         (ScreenStateDozeEvent = 3)
-                                                |                   (ScreenStateDozeSuspendEvent = 4)
-     -----------------------------------------------------------SCREEN_ON events
-                   |                                       |        (ScreenStateOnEvent = 2)
-                      |                                             (ScreenStateVrEvent = 5)
-                                            |                       (ScreenStateOnSuspendEvent = 6)
-    */
-    // Initialize log events - first bucket.
-    int appUid = 123;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
-                                          bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
-                                          bucketStartTimeNs + 180 * NS_PER_SEC));  // 3:10
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
-                                          bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
-
-    // Initialize log events - second bucket.
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
-                                          bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
-    events.push_back(CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND,
-            bucketStartTimeNs + 430 * NS_PER_SEC));  // 7:20
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
-    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
-                                          bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
-
-    // Send log events to StatsLogProcessor.
-    for (auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    // Check dump report.
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
-                            FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
-    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    // For each CountMetricData, check StateValue info is correct and buckets
-    // have correct counts.
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(4, data.bucket_info(0).count());
-    EXPECT_EQ(2, data.bucket_info(1).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(1, data.bucket_info(1).count());
-}
-
-/**
- * Test a count metric that has one slice_by_state with a primary field.
-
- * Once the CountMetricProducer is initialized, it should have one
- * MetricStateLink stored. State querying using a non-empty primary key
- * should also work as intended.
- */
-TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
-    // Initialize config.
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-
-    auto appCrashMatcher =
-            CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
-    *config.add_atom_matcher() = appCrashMatcher;
-
-    auto state = CreateUidProcessState();
-    *config.add_state() = state;
-
-    // Create count metric that slices by uid process state.
-    int64_t metricId = 123456;
-    auto countMetric = config.add_count_metric();
-    countMetric->set_id(metricId);
-    countMetric->set_what(appCrashMatcher.id());
-    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
-    countMetric->add_slice_by_state(state.id());
-    MetricStateLink* stateLink = countMetric->add_state_link();
-    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
-    auto fieldsInWhat = stateLink->mutable_fields_in_what();
-    *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
-    auto fieldsInState = stateLink->mutable_fields_in_state();
-    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
-    // Initialize StatsLogProcessor.
-    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
-    const uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
-    // Check that StateTrackers were initialized correctly.
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
-    // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
-    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
-
-    /*
-    NOTE: "1" or "2" represents the uid associated with the state/app crash event
-               bucket #1                      bucket #2
-    |     1     2     3     4     5     6     7     8     9     10
-    |-----------------------------|-----------------------------|--
-      1   1     1       1    1   2      1         1          2      (AppCrashEvents)
-     -----------------------------------------------------------PROCESS STATE events
-             1                  2                                   (ProcessStateTopEvent = 1002)
-                          1                 1                       (ProcessStateForegroundServiceEvent = 1003)
-                                                2                   (ProcessStateImportantBackgroundEvent = 1006)
-        1          1                                       1        (ProcessStateImportantForegroundEvent = 1005)
-
-    Based on the diagram above, an AppCrashEvent querying for process state value would return:
-    - StateTracker::kStateUnknown
-    - Important foreground
-    - Top
-    - Important foreground
-    - Foreground service
-    - Top (both the app crash and state still have matching uid = 2)
-
-    - Foreground service
-    - Foreground service
-    - Important background
-    */
-    // Initialize log events - first bucket.
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(
-            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
-    events.push_back(
-            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-            bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
-            bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
-    events.push_back(CreateUidProcessStateChangedEvent(
-            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-            bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
-    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
-                                                 bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
-
-    // Initialize log events - second bucket.
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
-            bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
-    events.push_back(CreateUidProcessStateChangedEvent(
-            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
-            bucketStartTimeNs + 430 * NS_PER_SEC));  // 7:20
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
-    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
-                                                 bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
-
-    // Send log events to StatsLogProcessor.
-    for (auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    // Check dump report.
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
-                            FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
-    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    // For each CountMetricData, check StateValue info is correct and buckets
-    // have correct counts.
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(1);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(2);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(2, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(3);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(2, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(4);
-    EXPECT_EQ(1, data.slice_by_state_size());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(2, data.bucket_info(1).count());
-}
-
-TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
-    // Initialize config.
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
-
-    auto appCrashMatcher =
-            CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
-    *config.add_atom_matcher() = appCrashMatcher;
-
-    auto state1 = CreateScreenStateWithOnOffMap();
-    *config.add_state() = state1;
-    auto state2 = CreateUidProcessState();
-    *config.add_state() = state2;
-
-    // Create count metric that slices by screen state with on/off map and
-    // slices by uid process state.
-    int64_t metricId = 123456;
-    auto countMetric = config.add_count_metric();
-    countMetric->set_id(metricId);
-    countMetric->set_what(appCrashMatcher.id());
-    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
-    countMetric->add_slice_by_state(state1.id());
-    countMetric->add_slice_by_state(state2.id());
-    MetricStateLink* stateLink = countMetric->add_state_link();
-    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
-    auto fieldsInWhat = stateLink->mutable_fields_in_what();
-    *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
-    auto fieldsInState = stateLink->mutable_fields_in_state();
-    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
-    // Initialize StatsLogProcessor.
-    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
-    const uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-
-    // Check that StateTrackers were properly initialized.
-    EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
-    // Check that CountMetricProducer was initialized correctly.
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
-    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
-    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
-
-    StateMap map = state1.map();
-    for (auto group : map.group()) {
-        for (auto value : group.value()) {
-            EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
-                      group.group_id());
-        }
-    }
-
-    /*
-               bucket #1                      bucket #2
-    |     1     2     3     4     5     6     7     8     9     10 (minutes)
-    |-----------------------------|-----------------------------|--
-      1   1     1       1    1   2      1         1           2     (AppCrashEvents)
-     -----------------------------------------------------------SCREEN_OFF events
-       |                                                            (ScreenStateUnknownEvent = 0)
-             |                                  |                   (ScreenStateOffEvent = 1)
-                          |                                         (ScreenStateDozeEvent = 3)
-     -----------------------------------------------------------SCREEN_ON events
-                    |                                    |          (ScreenStateOnEvent = 2)
-                                            |                       (ScreenStateOnSuspendEvent = 6)
-     -----------------------------------------------------------PROCESS STATE events
-             1                  2                                   (ProcessStateTopEvent = 1002)
-                                          1                         (ProcessStateForegroundServiceEvent = 1003)
-                                               2                    (ProcessStateImportantBackgroundEvent = 1006)
-     1             1                                       1        (ProcessStateImportantForegroundEvent = 1005)
-
-     Based on the diagram above, Screen State / Process State pairs for each
-     AppCrashEvent are:
-     - StateTracker::kStateUnknown / important foreground
-     - off / important foreground
-     - off / Top
-     - on / important foreground
-     - off / important foreground
-     - off / top
-
-     - off / important foreground
-     - off / foreground service
-     - on / important background
-
-    */
-    // Initialize log events - first bucket.
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 5 * NS_PER_SEC));  // 0:15
-    events.push_back(
-            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
-                                          bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
-    events.push_back(
-            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-            bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 160 * NS_PER_SEC));  // 2:50
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
-                                          bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
-    events.push_back(CreateUidProcessStateChangedEvent(
-            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-            bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
-    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
-                                                 bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
-
-    // Initialize log events - second bucket.
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
-            bucketStartTimeNs + 380 * NS_PER_SEC));  // 6:30
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
-                                          bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
-    events.push_back(CreateUidProcessStateChangedEvent(
-            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
-            bucketStartTimeNs + 420 * NS_PER_SEC));  // 7:10
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
-    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
-                                                 bucketStartTimeNs + 450 * NS_PER_SEC));  // 7:40
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 520 * NS_PER_SEC));  // 8:50
-    events.push_back(CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-            bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
-    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
-                                                 bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
-
-    // Send log events to StatsLogProcessor.
-    for (auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    // Check dump report.
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
-                            FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
-    EXPECT_EQ(6, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    // For each CountMetricData, check StateValue info is correct and buckets
-    // have correct counts.
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(1);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(-1, data.slice_by_state(0).value());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(2);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
-    EXPECT_EQ(2, data.bucket_info_size());
-    EXPECT_EQ(2, data.bucket_info(0).count());
-    EXPECT_EQ(1, data.bucket_info(1).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(3);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(4);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-
-    data = reports.reports(0).metrics(0).count_metrics().data(5);
-    EXPECT_EQ(2, data.slice_by_state_size());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
-    EXPECT_TRUE(data.slice_by_state(1).has_value());
-    EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(2, data.bucket_info(0).count());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+///**
+// * Test a count metric that has one slice_by_state with no primary fields.
+// *
+// * Once the CountMetricProducer is initialized, it has one atom id in
+// * mSlicedStateAtoms and no entries in mStateGroupMap.
+//
+// * One StateTracker tracks the state atom, and it has one listener which is the
+// * CountMetricProducer that was initialized.
+// */
+//TEST(CountMetricE2eTest, TestSlicedState) {
+//    // Initialize config.
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//
+//    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+//    *config.add_atom_matcher() = syncStartMatcher;
+//
+//    auto state = CreateScreenState();
+//    *config.add_state() = state;
+//
+//    // Create count metric that slices by screen state.
+//    int64_t metricId = 123456;
+//    auto countMetric = config.add_count_metric();
+//    countMetric->set_id(metricId);
+//    countMetric->set_what(syncStartMatcher.id());
+//    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+//    countMetric->add_slice_by_state(state.id());
+//
+//    // Initialize StatsLogProcessor.
+//    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+//    const uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+//    // Check that CountMetricProducer was initialized correctly.
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+//    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+//
+//    // Check that StateTrackers were initialized correctly.
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+//    /*
+//               bucket #1                      bucket #2
+//    |     1     2     3     4     5     6     7     8     9     10 (minutes)
+//    |-----------------------------|-----------------------------|--
+//            x                x         x    x        x      x       (syncStartEvents)
+//          |                                       |                 (ScreenIsOnEvent)
+//                   |     |                                          (ScreenIsOffEvent)
+//                                                        |           (ScreenUnknownEvent)
+//    */
+//    // Initialize log events - first bucket.
+//    int appUid = 123;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 50 * NS_PER_SEC));  // 1:00
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 75 * NS_PER_SEC));  // 1:25
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
+//
+//    // Initialize log events - second bucket.
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 350 * NS_PER_SEC));  // 6:00
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 400 * NS_PER_SEC));  // 6:50
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 450 * NS_PER_SEC));  // 7:40
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 475 * NS_PER_SEC));  // 8:05
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+//                                          bucketStartTimeNs + 500 * NS_PER_SEC));  // 8:30
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 520 * NS_PER_SEC));  // 8:50
+//
+//    // Send log events to StatsLogProcessor.
+//    for (auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    // Check dump report.
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+//                            FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+//    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    // For each CountMetricData, check StateValue info is correct and buckets
+//    // have correct counts.
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(1, data.bucket_info(1).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(1);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(2);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(2, data.bucket_info(1).count());
+//}
+//
+///**
+// * Test a count metric that has one slice_by_state with a mapping and no
+// * primary fields.
+// *
+// * Once the CountMetricProducer is initialized, it has one atom id in
+// * mSlicedStateAtoms and has one entry per state value in mStateGroupMap.
+// *
+// * One StateTracker tracks the state atom, and it has one listener which is the
+// * CountMetricProducer that was initialized.
+// */
+//TEST(CountMetricE2eTest, TestSlicedStateWithMap) {
+//    // Initialize config.
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//
+//    auto syncStartMatcher = CreateSyncStartAtomMatcher();
+//    *config.add_atom_matcher() = syncStartMatcher;
+//
+//    auto state = CreateScreenStateWithOnOffMap();
+//    *config.add_state() = state;
+//
+//    // Create count metric that slices by screen state with on/off map.
+//    int64_t metricId = 123456;
+//    auto countMetric = config.add_count_metric();
+//    countMetric->set_id(metricId);
+//    countMetric->set_what(syncStartMatcher.id());
+//    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+//    countMetric->add_slice_by_state(state.id());
+//
+//    // Initialize StatsLogProcessor.
+//    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+//    const uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+//    // Check that StateTrackers were initialized correctly.
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+//    // Check that CountMetricProducer was initialized correctly.
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+//    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+//
+//    StateMap map = state.map();
+//    for (auto group : map.group()) {
+//        for (auto value : group.value()) {
+//            EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
+//                      group.group_id());
+//        }
+//    }
+//
+//    /*
+//               bucket #1                      bucket #2
+//    |     1     2     3     4     5     6     7     8     9     10 (minutes)
+//    |-----------------------------|-----------------------------|--
+//      x   x     x       x    x   x      x         x         x       (syncStartEvents)
+//     -----------------------------------------------------------SCREEN_OFF events
+//       |                                                            (ScreenStateUnknownEvent = 0)
+//             |                  |                                   (ScreenStateOffEvent = 1)
+//                          |                                         (ScreenStateDozeEvent = 3)
+//                                                |                   (ScreenStateDozeSuspendEvent = 4)
+//     -----------------------------------------------------------SCREEN_ON events
+//                   |                                       |        (ScreenStateOnEvent = 2)
+//                      |                                             (ScreenStateVrEvent = 5)
+//                                            |                       (ScreenStateOnSuspendEvent = 6)
+//    */
+//    // Initialize log events - first bucket.
+//    int appUid = 123;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+//                                          bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+//                                          bucketStartTimeNs + 180 * NS_PER_SEC));  // 3:10
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
+//                                          bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
+//
+//    // Initialize log events - second bucket.
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
+//                                          bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
+//    events.push_back(CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_DOZE_SUSPEND,
+//            bucketStartTimeNs + 430 * NS_PER_SEC));  // 7:20
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
+//    events.push_back(CreateSyncStartEvent(attributions1, "sync_name",
+//                                          bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
+//
+//    // Send log events to StatsLogProcessor.
+//    for (auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    // Check dump report.
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+//                            FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+//    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    // For each CountMetricData, check StateValue info is correct and buckets
+//    // have correct counts.
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(1);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(4, data.bucket_info(0).count());
+//    EXPECT_EQ(2, data.bucket_info(1).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(2);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(1, data.bucket_info(1).count());
+//}
+//
+///**
+// * Test a count metric that has one slice_by_state with a primary field.
+//
+// * Once the CountMetricProducer is initialized, it should have one
+// * MetricStateLink stored. State querying using a non-empty primary key
+// * should also work as intended.
+// */
+//TEST(CountMetricE2eTest, TestSlicedStateWithPrimaryFields) {
+//    // Initialize config.
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//
+//    auto appCrashMatcher =
+//            CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+//    *config.add_atom_matcher() = appCrashMatcher;
+//
+//    auto state = CreateUidProcessState();
+//    *config.add_state() = state;
+//
+//    // Create count metric that slices by uid process state.
+//    int64_t metricId = 123456;
+//    auto countMetric = config.add_count_metric();
+//    countMetric->set_id(metricId);
+//    countMetric->set_what(appCrashMatcher.id());
+//    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+//    countMetric->add_slice_by_state(state.id());
+//    MetricStateLink* stateLink = countMetric->add_state_link();
+//    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+//    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+//    *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
+//    auto fieldsInState = stateLink->mutable_fields_in_state();
+//    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+//    // Initialize StatsLogProcessor.
+//    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+//    const uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+//    // Check that StateTrackers were initialized correctly.
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+//    // Check that CountMetricProducer was initialized correctly.
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 1);
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), UID_PROCESS_STATE_ATOM_ID);
+//    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 0);
+//    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+//
+//    /*
+//    NOTE: "1" or "2" represents the uid associated with the state/app crash event
+//               bucket #1                      bucket #2
+//    |     1     2     3     4     5     6     7     8     9     10
+//    |-----------------------------|-----------------------------|--
+//      1   1     1       1    1   2      1         1          2      (AppCrashEvents)
+//     -----------------------------------------------------------PROCESS STATE events
+//             1                  2                                   (ProcessStateTopEvent = 1002)
+//                          1                 1                       (ProcessStateForegroundServiceEvent = 1003)
+//                                                2                   (ProcessStateImportantBackgroundEvent = 1006)
+//        1          1                                       1        (ProcessStateImportantForegroundEvent = 1005)
+//
+//    Based on the diagram above, an AppCrashEvent querying for process state value would return:
+//    - StateTracker::kStateUnknown
+//    - Important foreground
+//    - Top
+//    - Important foreground
+//    - Foreground service
+//    - Top (both the app crash and state still have matching uid = 2)
+//
+//    - Foreground service
+//    - Foreground service
+//    - Important background
+//    */
+//    // Initialize log events - first bucket.
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(
+//            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
+//    events.push_back(
+//            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//            bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+//            bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//            bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+//    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+//                                                 bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
+//
+//    // Initialize log events - second bucket.
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+//            bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+//            bucketStartTimeNs + 430 * NS_PER_SEC));  // 7:20
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
+//    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+//                                                 bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
+//
+//    // Send log events to StatsLogProcessor.
+//    for (auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    // Check dump report.
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+//                            FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+//    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    // For each CountMetricData, check StateValue info is correct and buckets
+//    // have correct counts.
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(1);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(-1 /* StateTracker::kStateUnknown */, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(2);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(2, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(3);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(0).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(2, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(4);
+//    EXPECT_EQ(1, data.slice_by_state_size());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(0).value());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(2, data.bucket_info(1).count());
+//}
+//
+//TEST(CountMetricE2eTest, TestMultipleSlicedStates) {
+//    // Initialize config.
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT");  // LogEvent defaults to UID of root.
+//
+//    auto appCrashMatcher =
+//            CreateSimpleAtomMatcher("APP_CRASH_OCCURRED", android::util::APP_CRASH_OCCURRED);
+//    *config.add_atom_matcher() = appCrashMatcher;
+//
+//    auto state1 = CreateScreenStateWithOnOffMap();
+//    *config.add_state() = state1;
+//    auto state2 = CreateUidProcessState();
+//    *config.add_state() = state2;
+//
+//    // Create count metric that slices by screen state with on/off map and
+//    // slices by uid process state.
+//    int64_t metricId = 123456;
+//    auto countMetric = config.add_count_metric();
+//    countMetric->set_id(metricId);
+//    countMetric->set_what(appCrashMatcher.id());
+//    countMetric->set_bucket(TimeUnit::FIVE_MINUTES);
+//    countMetric->add_slice_by_state(state1.id());
+//    countMetric->add_slice_by_state(state2.id());
+//    MetricStateLink* stateLink = countMetric->add_state_link();
+//    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+//    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+//    *fieldsInWhat = CreateDimensions(android::util::APP_CRASH_OCCURRED, {1 /* uid */});
+//    auto fieldsInState = stateLink->mutable_fields_in_state();
+//    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+//    // Initialize StatsLogProcessor.
+//    const uint64_t bucketStartTimeNs = 10000000000;  // 0:10
+//    const uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//
+//    // Check that StateTrackers were properly initialized.
+//    EXPECT_EQ(2, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+//    // Check that CountMetricProducer was initialized correctly.
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.size(), 2);
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(0), SCREEN_STATE_ATOM_ID);
+//    EXPECT_EQ(metricProducer->mSlicedStateAtoms.at(1), UID_PROCESS_STATE_ATOM_ID);
+//    EXPECT_EQ(metricProducer->mStateGroupMap.size(), 1);
+//    EXPECT_EQ(metricProducer->mMetric2StateLinks.size(), 1);
+//
+//    StateMap map = state1.map();
+//    for (auto group : map.group()) {
+//        for (auto value : group.value()) {
+//            EXPECT_EQ(metricProducer->mStateGroupMap[SCREEN_STATE_ATOM_ID][value],
+//                      group.group_id());
+//        }
+//    }
+//
+//    /*
+//               bucket #1                      bucket #2
+//    |     1     2     3     4     5     6     7     8     9     10 (minutes)
+//    |-----------------------------|-----------------------------|--
+//      1   1     1       1    1   2      1         1           2     (AppCrashEvents)
+//     -----------------------------------------------------------SCREEN_OFF events
+//       |                                                            (ScreenStateUnknownEvent = 0)
+//             |                                  |                   (ScreenStateOffEvent = 1)
+//                          |                                         (ScreenStateDozeEvent = 3)
+//     -----------------------------------------------------------SCREEN_ON events
+//                    |                                    |          (ScreenStateOnEvent = 2)
+//                                            |                       (ScreenStateOnSuspendEvent = 6)
+//     -----------------------------------------------------------PROCESS STATE events
+//             1                  2                                   (ProcessStateTopEvent = 1002)
+//                                          1                         (ProcessStateForegroundServiceEvent = 1003)
+//                                               2                    (ProcessStateImportantBackgroundEvent = 1006)
+//     1             1                                       1        (ProcessStateImportantForegroundEvent = 1005)
+//
+//     Based on the diagram above, Screen State / Process State pairs for each
+//     AppCrashEvent are:
+//     - StateTracker::kStateUnknown / important foreground
+//     - off / important foreground
+//     - off / Top
+//     - on / important foreground
+//     - off / important foreground
+//     - off / top
+//
+//     - off / important foreground
+//     - off / foreground service
+//     - on / important background
+//
+//    */
+//    // Initialize log events - first bucket.
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 5 * NS_PER_SEC));  // 0:15
+//    events.push_back(
+//            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 20 * NS_PER_SEC));  // 0:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_UNKNOWN,
+//                                          bucketStartTimeNs + 30 * NS_PER_SEC));  // 0:40
+//    events.push_back(
+//            CreateAppCrashOccurredEvent(1 /* uid */, bucketStartTimeNs + 60 * NS_PER_SEC));  // 1:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//            bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 90 * NS_PER_SEC));  // 1:40
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 120 * NS_PER_SEC));  // 2:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 150 * NS_PER_SEC));  // 2:40
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 160 * NS_PER_SEC));  // 2:50
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 200 * NS_PER_SEC));  // 3:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_DOZE,
+//                                          bucketStartTimeNs + 210 * NS_PER_SEC));  // 3:40
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 250 * NS_PER_SEC));  // 4:20
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//            bucketStartTimeNs + 280 * NS_PER_SEC));  // 4:50
+//    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+//                                                 bucketStartTimeNs + 285 * NS_PER_SEC));  // 4:55
+//
+//    // Initialize log events - second bucket.
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 360 * NS_PER_SEC));  // 6:10
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+//            bucketStartTimeNs + 380 * NS_PER_SEC));  // 6:30
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON_SUSPEND,
+//                                          bucketStartTimeNs + 390 * NS_PER_SEC));  // 6:40
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            2 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+//            bucketStartTimeNs + 420 * NS_PER_SEC));  // 7:10
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 440 * NS_PER_SEC));  // 7:30
+//    events.push_back(CreateAppCrashOccurredEvent(1 /* uid */,
+//                                                 bucketStartTimeNs + 450 * NS_PER_SEC));  // 7:40
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 520 * NS_PER_SEC));  // 8:50
+//    events.push_back(CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//            bucketStartTimeNs + 540 * NS_PER_SEC));  // 9:10
+//    events.push_back(CreateAppCrashOccurredEvent(2 /* uid */,
+//                                                 bucketStartTimeNs + 570 * NS_PER_SEC));  // 9:40
+//
+//    // Send log events to StatsLogProcessor.
+//    for (auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    // Check dump report.
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs * 2 + 1, false, true, ADB_DUMP,
+//                            FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_count_metrics());
+//    EXPECT_EQ(6, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    // For each CountMetricData, check StateValue info is correct and buckets
+//    // have correct counts.
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_FOREGROUND_SERVICE, data.slice_by_state(1).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(1);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(-1, data.slice_by_state(0).value());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(2);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+//    EXPECT_EQ(2, data.bucket_info_size());
+//    EXPECT_EQ(2, data.bucket_info(0).count());
+//    EXPECT_EQ(1, data.bucket_info(1).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(3);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, data.slice_by_state(1).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(4);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_ON"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, data.slice_by_state(1).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//
+//    data = reports.reports(0).metrics(0).count_metrics().data(5);
+//    EXPECT_EQ(2, data.slice_by_state_size());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(StringToId("SCREEN_OFF"), data.slice_by_state(0).group_id());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(1).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(1).has_value());
+//    EXPECT_EQ(android::app::PROCESS_STATE_TOP, data.slice_by_state(1).value());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(2, data.bucket_info(0).count());
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
index 9093155..8eb5f69 100644
--- a/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/DurationMetric_e2e_test.cpp
@@ -26,687 +26,688 @@
 
 #ifdef __ANDROID__
 
-TEST(DurationMetricE2eTest, TestOneBucket) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
-    *config.add_atom_matcher() = screenOnMatcher;
-    *config.add_atom_matcher() = screenOffMatcher;
-
-    auto durationPredicate = CreateScreenIsOnPredicate();
-    *config.add_predicate() = durationPredicate;
-
-    int64_t metricId = 123456;
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(metricId);
-    durationMetric->set_what(durationPredicate.id());
-    durationMetric->set_bucket(FIVE_MINUTES);
-    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-
-    const int64_t baseTimeNs = 0; // 0:00
-    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
-    const int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
-
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-
-    std::unique_ptr<LogEvent> event;
-
-    // Screen is off at start of bucket.
-    event = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
-    processor->OnLogEvent(event.get());
-
-    // Turn screen on.
-    const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
-    processor->OnLogEvent(event.get());
-
-    // Turn off screen 30 seconds after turning on.
-    const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
-    processor->OnLogEvent(event.get());
-
-    event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
-    processor->OnLogEvent(event.get());
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
-                            ADB_DUMP, FAST, &buffer); // 5:01
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
-    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
-            reports.reports(0).metrics(0).duration_metrics();
-    EXPECT_EQ(1, durationMetrics.data_size());
-
-    auto data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
-    EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestTwoBuckets) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
-    *config.add_atom_matcher() = screenOnMatcher;
-    *config.add_atom_matcher() = screenOffMatcher;
-
-    auto durationPredicate = CreateScreenIsOnPredicate();
-    *config.add_predicate() = durationPredicate;
-
-    int64_t metricId = 123456;
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(metricId);
-    durationMetric->set_what(durationPredicate.id());
-    durationMetric->set_bucket(FIVE_MINUTES);
-    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-
-    const int64_t baseTimeNs = 0; // 0:00
-    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
-    const int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
-
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-
-    std::unique_ptr<LogEvent> event;
-
-    // Screen is off at start of bucket.
-    event = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
-    processor->OnLogEvent(event.get());
-
-    // Turn screen on.
-    const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
-    processor->OnLogEvent(event.get());
-
-    // Turn off screen 30 seconds after turning on.
-    const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
-    processor->OnLogEvent(event.get());
-
-    event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
-    processor->OnLogEvent(event.get());
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false, true,
-                            ADB_DUMP, FAST, &buffer); // 10:01
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
-    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
-            reports.reports(0).metrics(0).duration_metrics();
-    EXPECT_EQ(1, durationMetrics.data_size());
-
-    auto data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(0, bucketInfo.bucket_num());
-    EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
-    EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithActivation) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
-    auto crashMatcher = CreateProcessCrashAtomMatcher();
-    *config.add_atom_matcher() = screenOnMatcher;
-    *config.add_atom_matcher() = screenOffMatcher;
-    *config.add_atom_matcher() = crashMatcher;
-
-    auto durationPredicate = CreateScreenIsOnPredicate();
-    *config.add_predicate() = durationPredicate;
-
-    int64_t metricId = 123456;
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(metricId);
-    durationMetric->set_what(durationPredicate.id());
-    durationMetric->set_bucket(FIVE_MINUTES);
-    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-    auto metric_activation1 = config.add_metric_activation();
-    metric_activation1->set_metric_id(metricId);
-    auto event_activation1 = metric_activation1->add_event_activation();
-    event_activation1->set_atom_matcher_id(crashMatcher.id());
-    event_activation1->set_ttl_seconds(30); // 30 secs.
-
-    const int64_t bucketStartTimeNs = 10000000000;
-    const int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    std::unique_ptr<LogEvent> event;
-
-    // Turn screen off.
-    event = CreateScreenStateChangedEvent(
-            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
-
-    // Turn screen on.
-    const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
-    processor.OnLogEvent(event.get(), durationStartNs);
-
-    // Activate metric.
-    const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
-    const int64_t activationEndNs =
-            activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
-    event = CreateAppCrashEvent(111, activationStartNs);
-    processor.OnLogEvent(event.get(), activationStartNs);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    // Expire activation.
-    const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
-    event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
-    processor.OnLogEvent(event.get(), expirationNs);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    // Turn off screen 10 seconds after activation expiration.
-    const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
-    processor.OnLogEvent(event.get(),durationEndNs);
-
-    // Turn screen on.
-    const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
-    processor.OnLogEvent(event.get(), duration2StartNs);
-
-    // Turn off screen.
-    const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
-    processor.OnLogEvent(event.get(), duration2EndNs);
-
-    // Activate metric.
-    const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
-    const int64_t activation2EndNs =
-            activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
-    event = CreateAppCrashEvent(211, activation2StartNs);
-    processor.OnLogEvent(event.get(), activation2StartNs);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
-                            ADB_DUMP, FAST, &buffer); // 5:01
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
-    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
-
-    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
-            reports.reports(0).metrics(0).duration_metrics();
-    EXPECT_EQ(1, durationMetrics.data_size());
-
-    auto data = durationMetrics.data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(0, bucketInfo.bucket_num());
-    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithCondition) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-
-    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
-    *config.add_predicate() = holdingWakelockPredicate;
-
-    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
-    *config.add_predicate() = isInBackgroundPredicate;
-
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(StringToId("WakelockDuration"));
-    durationMetric->set_what(holdingWakelockPredicate.id());
-    durationMetric->set_condition(isInBackgroundPredicate.id());
-    durationMetric->set_aggregation_type(DurationMetric::SUM);
-    durationMetric->set_bucket(FIVE_MINUTES);
-
-    ConfigKey cfgKey;
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_TRUE(eventActivationMap.empty());
-
-    int appUid = 123;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
-    auto event = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
-    processor->OnLogEvent(event.get());
-
-    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
-    processor->OnLogEvent(event.get());
-
-    event = CreateMoveToForegroundEvent(
-            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
-    processor->OnLogEvent(event.get());
-
-    event = CreateReleaseWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
-    processor->OnLogEvent(event.get());
-
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-
-    // Validate bucket info.
-    EXPECT_EQ(1, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-
-    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
-    // The predicate is dimensioning by first attribution node by uid.
-    FieldMatcher dimensions = CreateAttributionUidDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
-    *config.add_predicate() = holdingWakelockPredicate;
-
-    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
-    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
-    *config.add_predicate() = isInBackgroundPredicate;
-
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(StringToId("WakelockDuration"));
-    durationMetric->set_what(holdingWakelockPredicate.id());
-    durationMetric->set_condition(isInBackgroundPredicate.id());
-    durationMetric->set_aggregation_type(DurationMetric::SUM);
-    // The metric is dimensioning by first attribution node and only by uid.
-    *durationMetric->mutable_dimensions_in_what() =
-        CreateAttributionUidDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    durationMetric->set_bucket(FIVE_MINUTES);
-
-    // Links between wakelock state atom and condition of app is in background.
-    auto links = durationMetric->add_links();
-    links->set_condition(isInBackgroundPredicate.id());
-    auto dimensionWhat = links->mutable_fields_in_what();
-    dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
-    dimensionWhat->add_child()->set_field(1);  // uid field.
-    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
-            android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
-
-    ConfigKey cfgKey;
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_TRUE(eventActivationMap.empty());
-
-    int appUid = 123;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
-    auto event = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
-    processor->OnLogEvent(event.get());
-
-    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
-    processor->OnLogEvent(event.get());
-
-    event = CreateReleaseWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
-    processor->OnLogEvent(event.get());
-
-
-    event = CreateMoveToForegroundEvent(
-            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
-    processor->OnLogEvent(event.get());
-
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // Validate dimension value.
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, appUid);
-    // Validate bucket info.
-    EXPECT_EQ(1, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
-}
-
-TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
-    StatsdConfig config;
-    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
-    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
-    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
-    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
-    *config.add_atom_matcher() = screenOnMatcher;
-
-    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
-    // The predicate is dimensioning by first attribution node by uid.
-    FieldMatcher dimensions = CreateAttributionUidDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
-    *config.add_predicate() = holdingWakelockPredicate;
-
-    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
-    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
-        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
-    *config.add_predicate() = isInBackgroundPredicate;
-
-    auto durationMetric = config.add_duration_metric();
-    durationMetric->set_id(StringToId("WakelockDuration"));
-    durationMetric->set_what(holdingWakelockPredicate.id());
-    durationMetric->set_condition(isInBackgroundPredicate.id());
-    durationMetric->set_aggregation_type(DurationMetric::SUM);
-    // The metric is dimensioning by first attribution node and only by uid.
-    *durationMetric->mutable_dimensions_in_what() =
-        CreateAttributionUidDimensions(
-            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
-    durationMetric->set_bucket(FIVE_MINUTES);
-
-    // Links between wakelock state atom and condition of app is in background.
-    auto links = durationMetric->add_links();
-    links->set_condition(isInBackgroundPredicate.id());
-    auto dimensionWhat = links->mutable_fields_in_what();
-    dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
-    dimensionWhat->add_child()->set_field(1);  // uid field.
-    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
-            android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
-
-    auto metric_activation1 = config.add_metric_activation();
-    metric_activation1->set_metric_id(durationMetric->id());
-    auto event_activation1 = metric_activation1->add_event_activation();
-    event_activation1->set_atom_matcher_id(screenOnMatcher.id());
-    event_activation1->set_ttl_seconds(60 * 2);  // 2 minutes.
-
-    ConfigKey cfgKey;
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap.size(), 1u);
-    EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    int appUid = 123;
-    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
-
-    auto event = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
-    processor->OnLogEvent(event.get());
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
-    processor->OnLogEvent(event.get());
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
-    processor->OnLogEvent(event.get());
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    const int64_t durationEndNs =
-            durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
-    event = CreateAppCrashEvent(333, durationEndNs);
-    processor->OnLogEvent(event.get());
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    event = CreateMoveToForegroundEvent(
-            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
-    processor->OnLogEvent(event.get());
-
-    event = CreateReleaseWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
-    processor->OnLogEvent(event.get());
-
-    event = CreateMoveToBackgroundEvent(
-            appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
-    processor->OnLogEvent(event.get());
-
-    event = CreateAcquireWakelockEvent(
-            attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
-    processor->OnLogEvent(event.get());
-
-    const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
-    processor->OnLogEvent(event.get());
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
-    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
-
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_GT(buffer.size(), 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
-
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // Validate dimension value.
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, appUid);
-    // Validate bucket info.
-    EXPECT_EQ(2, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
-
-    bucketInfo = data.bucket_info(1);
-    EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(DurationMetricE2eTest, TestOneBucket) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+//    *config.add_atom_matcher() = screenOnMatcher;
+//    *config.add_atom_matcher() = screenOffMatcher;
+//
+//    auto durationPredicate = CreateScreenIsOnPredicate();
+//    *config.add_predicate() = durationPredicate;
+//
+//    int64_t metricId = 123456;
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(metricId);
+//    durationMetric->set_what(durationPredicate.id());
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//
+//    const int64_t baseTimeNs = 0; // 0:00
+//    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+//    const int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+//
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    // Screen is off at start of bucket.
+//    event = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+//    processor->OnLogEvent(event.get());
+//
+//    // Turn screen on.
+//    const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+//    processor->OnLogEvent(event.get());
+//
+//    // Turn off screen 30 seconds after turning on.
+//    const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+//    processor->OnLogEvent(event.get());
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+//                            ADB_DUMP, FAST, &buffer); // 5:01
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+//    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+//            reports.reports(0).metrics(0).duration_metrics();
+//    EXPECT_EQ(1, durationMetrics.data_size());
+//
+//    auto data = durationMetrics.data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(durationEndNs - durationStartNs, data.bucket_info(0).duration_nanos());
+//    EXPECT_EQ(configAddedTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestTwoBuckets) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+//    *config.add_atom_matcher() = screenOnMatcher;
+//    *config.add_atom_matcher() = screenOffMatcher;
+//
+//    auto durationPredicate = CreateScreenIsOnPredicate();
+//    *config.add_predicate() = durationPredicate;
+//
+//    int64_t metricId = 123456;
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(metricId);
+//    durationMetric->set_what(durationPredicate.id());
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//
+//    const int64_t baseTimeNs = 0; // 0:00
+//    const int64_t configAddedTimeNs = baseTimeNs + 1 * NS_PER_SEC; // 0:01
+//    const int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey);
+//
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    // Screen is off at start of bucket.
+//    event = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_OFF, configAddedTimeNs); // 0:01
+//    processor->OnLogEvent(event.get());
+//
+//    // Turn screen on.
+//    const int64_t durationStartNs = configAddedTimeNs + 10 * NS_PER_SEC; // 0:11
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+//    processor->OnLogEvent(event.get());
+//
+//    // Turn off screen 30 seconds after turning on.
+//    const int64_t durationEndNs = durationStartNs + 30 * NS_PER_SEC; // 0:41
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateScreenBrightnessChangedEvent(64, durationEndNs + 1 * NS_PER_SEC); // 0:42
+//    processor->OnLogEvent(event.get());
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC, false, true,
+//                            ADB_DUMP, FAST, &buffer); // 10:01
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+//    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+//            reports.reports(0).metrics(0).duration_metrics();
+//    EXPECT_EQ(1, durationMetrics.data_size());
+//
+//    auto data = durationMetrics.data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(0, bucketInfo.bucket_num());
+//    EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+//    EXPECT_EQ(configAddedTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithActivation) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    auto screenOffMatcher = CreateScreenTurnedOffAtomMatcher();
+//    auto crashMatcher = CreateProcessCrashAtomMatcher();
+//    *config.add_atom_matcher() = screenOnMatcher;
+//    *config.add_atom_matcher() = screenOffMatcher;
+//    *config.add_atom_matcher() = crashMatcher;
+//
+//    auto durationPredicate = CreateScreenIsOnPredicate();
+//    *config.add_predicate() = durationPredicate;
+//
+//    int64_t metricId = 123456;
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(metricId);
+//    durationMetric->set_what(durationPredicate.id());
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//    durationMetric->set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//    auto metric_activation1 = config.add_metric_activation();
+//    metric_activation1->set_metric_id(metricId);
+//    auto event_activation1 = metric_activation1->add_event_activation();
+//    event_activation1->set_atom_matcher_id(crashMatcher.id());
+//    event_activation1->set_ttl_seconds(30); // 30 secs.
+//
+//    const int64_t bucketStartTimeNs = 10000000000;
+//    const int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config); // 0:00
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap.size(), 1u);
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    // Turn screen off.
+//    event = CreateScreenStateChangedEvent(
+//            android::view::DISPLAY_STATE_OFF, bucketStartTimeNs + 2 * NS_PER_SEC); // 0:02
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 2 * NS_PER_SEC);
+//
+//    // Turn screen on.
+//    const int64_t durationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:05
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+//    processor.OnLogEvent(event.get(), durationStartNs);
+//
+//    // Activate metric.
+//    const int64_t activationStartNs = bucketStartTimeNs + 5 * NS_PER_SEC; // 0:10
+//    const int64_t activationEndNs =
+//            activationStartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 0:40
+//    event = CreateAppCrashEvent(111, activationStartNs);
+//    processor.OnLogEvent(event.get(), activationStartNs);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    // Expire activation.
+//    const int64_t expirationNs = activationEndNs + 7 * NS_PER_SEC;
+//    event = CreateScreenBrightnessChangedEvent(64, expirationNs); // 0:47
+//    processor.OnLogEvent(event.get(), expirationNs);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap.size(), 1u);
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, activationStartNs);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    // Turn off screen 10 seconds after activation expiration.
+//    const int64_t durationEndNs = activationEndNs + 10 * NS_PER_SEC; // 0:50
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, durationEndNs);
+//    processor.OnLogEvent(event.get(),durationEndNs);
+//
+//    // Turn screen on.
+//    const int64_t duration2StartNs = durationEndNs + 5 * NS_PER_SEC; // 0:55
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+//    processor.OnLogEvent(event.get(), duration2StartNs);
+//
+//    // Turn off screen.
+//    const int64_t duration2EndNs = duration2StartNs + 10 * NS_PER_SEC; // 1:05
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF, duration2EndNs);
+//    processor.OnLogEvent(event.get(), duration2EndNs);
+//
+//    // Activate metric.
+//    const int64_t activation2StartNs = duration2EndNs + 5 * NS_PER_SEC; // 1:10
+//    const int64_t activation2EndNs =
+//            activation2StartNs + event_activation1->ttl_seconds() * NS_PER_SEC; // 1:40
+//    event = CreateAppCrashEvent(211, activation2StartNs);
+//    processor.OnLogEvent(event.get(), activation2StartNs);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, activation2StartNs);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1 * NS_PER_SEC, false, true,
+//                            ADB_DUMP, FAST, &buffer); // 5:01
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(metricId, reports.reports(0).metrics(0).metric_id());
+//    EXPECT_TRUE(reports.reports(0).metrics(0).has_duration_metrics());
+//
+//    const StatsLogReport::DurationMetricDataWrapper& durationMetrics =
+//            reports.reports(0).metrics(0).duration_metrics();
+//    EXPECT_EQ(1, durationMetrics.data_size());
+//
+//    auto data = durationMetrics.data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(0, bucketInfo.bucket_num());
+//    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(expirationNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(expirationNs - durationStartNs, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithCondition) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+//
+//    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+//    *config.add_predicate() = holdingWakelockPredicate;
+//
+//    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+//    *config.add_predicate() = isInBackgroundPredicate;
+//
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(StringToId("WakelockDuration"));
+//    durationMetric->set_what(holdingWakelockPredicate.id());
+//    durationMetric->set_condition(isInBackgroundPredicate.id());
+//    durationMetric->set_aggregation_type(DurationMetric::SUM);
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//
+//    ConfigKey cfgKey;
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_TRUE(eventActivationMap.empty());
+//
+//    int appUid = 123;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+//    auto event = CreateAcquireWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateMoveToForegroundEvent(
+//            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateReleaseWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + 4 * 60 * NS_PER_SEC); // 4:00
+//    processor->OnLogEvent(event.get());
+//
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//
+//    // Validate bucket info.
+//    EXPECT_EQ(1, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ((2 * 60 + 53) * NS_PER_SEC, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithSlicedCondition) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+//
+//    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+//    // The predicate is dimensioning by first attribution node by uid.
+//    FieldMatcher dimensions = CreateAttributionUidDimensions(
+//            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+//    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+//    *config.add_predicate() = holdingWakelockPredicate;
+//
+//    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+//    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+//        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+//    *config.add_predicate() = isInBackgroundPredicate;
+//
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(StringToId("WakelockDuration"));
+//    durationMetric->set_what(holdingWakelockPredicate.id());
+//    durationMetric->set_condition(isInBackgroundPredicate.id());
+//    durationMetric->set_aggregation_type(DurationMetric::SUM);
+//    // The metric is dimensioning by first attribution node and only by uid.
+//    *durationMetric->mutable_dimensions_in_what() =
+//        CreateAttributionUidDimensions(
+//            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//
+//    // Links between wakelock state atom and condition of app is in background.
+//    auto links = durationMetric->add_links();
+//    links->set_condition(isInBackgroundPredicate.id());
+//    auto dimensionWhat = links->mutable_fields_in_what();
+//    dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+//    dimensionWhat->add_child()->set_field(1);  // uid field.
+//    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+//            android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+//
+//    ConfigKey cfgKey;
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_TRUE(eventActivationMap.empty());
+//
+//    int appUid = 123;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+//    auto event = CreateAcquireWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateReleaseWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + 60 * NS_PER_SEC); // 1:00
+//    processor->OnLogEvent(event.get());
+//
+//
+//    event = CreateMoveToForegroundEvent(
+//            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+//    processor->OnLogEvent(event.get());
+//
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // Validate dimension value.
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, appUid);
+//    // Validate bucket info.
+//    EXPECT_EQ(1, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(38 * NS_PER_SEC, bucketInfo.duration_nanos());
+//}
+//
+//TEST(DurationMetricE2eTest, TestWithActivationAndSlicedCondition) {
+//    StatsdConfig config;
+//    config.add_allowed_log_source("AID_ROOT"); // LogEvent defaults to UID of root.
+//    auto screenOnMatcher = CreateScreenTurnedOnAtomMatcher();
+//    *config.add_atom_matcher() = CreateAcquireWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateReleaseWakelockAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToBackgroundAtomMatcher();
+//    *config.add_atom_matcher() = CreateMoveToForegroundAtomMatcher();
+//    *config.add_atom_matcher() = screenOnMatcher;
+//
+//    auto holdingWakelockPredicate = CreateHoldingWakelockPredicate();
+//    // The predicate is dimensioning by first attribution node by uid.
+//    FieldMatcher dimensions = CreateAttributionUidDimensions(
+//            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+//    *holdingWakelockPredicate.mutable_simple_predicate()->mutable_dimensions() = dimensions;
+//    *config.add_predicate() = holdingWakelockPredicate;
+//
+//    auto isInBackgroundPredicate = CreateIsInBackgroundPredicate();
+//    *isInBackgroundPredicate.mutable_simple_predicate()->mutable_dimensions() =
+//        CreateDimensions(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, {Position::FIRST});
+//    *config.add_predicate() = isInBackgroundPredicate;
+//
+//    auto durationMetric = config.add_duration_metric();
+//    durationMetric->set_id(StringToId("WakelockDuration"));
+//    durationMetric->set_what(holdingWakelockPredicate.id());
+//    durationMetric->set_condition(isInBackgroundPredicate.id());
+//    durationMetric->set_aggregation_type(DurationMetric::SUM);
+//    // The metric is dimensioning by first attribution node and only by uid.
+//    *durationMetric->mutable_dimensions_in_what() =
+//        CreateAttributionUidDimensions(
+//            android::util::WAKELOCK_STATE_CHANGED, {Position::FIRST});
+//    durationMetric->set_bucket(FIVE_MINUTES);
+//
+//    // Links between wakelock state atom and condition of app is in background.
+//    auto links = durationMetric->add_links();
+//    links->set_condition(isInBackgroundPredicate.id());
+//    auto dimensionWhat = links->mutable_fields_in_what();
+//    dimensionWhat->set_field(android::util::WAKELOCK_STATE_CHANGED);
+//    dimensionWhat->add_child()->set_field(1);  // uid field.
+//    *links->mutable_fields_in_condition() = CreateAttributionUidDimensions(
+//            android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, { Position::FIRST });
+//
+//    auto metric_activation1 = config.add_metric_activation();
+//    metric_activation1->set_metric_id(durationMetric->id());
+//    auto event_activation1 = metric_activation1->add_event_activation();
+//    event_activation1->set_atom_matcher_id(screenOnMatcher.id());
+//    event_activation1->set_ttl_seconds(60 * 2);  // 2 minutes.
+//
+//    ConfigKey cfgKey;
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor->mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap.size(), 1u);
+//    EXPECT_TRUE(eventActivationMap.find(4) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    int appUid = 123;
+//    std::vector<AttributionNodeInternal> attributions1 = {CreateAttribution(appUid, "App1")};
+//
+//    auto event = CreateAcquireWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + 10 * NS_PER_SEC); // 0:10
+//    processor->OnLogEvent(event.get());
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    event = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 22 * NS_PER_SEC); // 0:22
+//    processor->OnLogEvent(event.get());
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    const int64_t durationStartNs = bucketStartTimeNs + 30 * NS_PER_SEC; // 0:30
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, durationStartNs);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    const int64_t durationEndNs =
+//            durationStartNs + (event_activation1->ttl_seconds() + 30) * NS_PER_SEC; // 3:00
+//    event = CreateAppCrashEvent(333, durationEndNs);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, durationStartNs);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    event = CreateMoveToForegroundEvent(
+//            appUid, bucketStartTimeNs + (3 * 60 + 15) * NS_PER_SEC); // 3:15
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateReleaseWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 17) * NS_PER_SEC); // 4:17
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateMoveToBackgroundEvent(
+//            appUid, bucketStartTimeNs + (4 * 60 + 20) * NS_PER_SEC); // 4:20
+//    processor->OnLogEvent(event.get());
+//
+//    event = CreateAcquireWakelockEvent(
+//            attributions1, "wl1", bucketStartTimeNs + (4 * 60 + 25) * NS_PER_SEC); // 4:25
+//    processor->OnLogEvent(event.get());
+//
+//    const int64_t duration2StartNs = bucketStartTimeNs + (4 * 60 + 30) * NS_PER_SEC; // 4:30
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, duration2StartNs);
+//    processor->OnLogEvent(event.get());
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[4]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[4]->start_ns, duration2StartNs);
+//    EXPECT_EQ(eventActivationMap[4]->ttl_ns, event_activation1->ttl_seconds() * NS_PER_SEC);
+//
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_GT(buffer.size(), 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics(0).duration_metrics().data_size());
+//
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // Validate dimension value.
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, appUid);
+//    // Validate bucket info.
+//    EXPECT_EQ(2, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(bucketStartTimeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(durationEndNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(durationEndNs - durationStartNs, bucketInfo.duration_nanos());
+//
+//    bucketInfo = data.bucket_info(1);
+//    EXPECT_EQ(durationEndNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - duration2StartNs, bucketInfo.duration_nanos());
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
index 9127be8..7f651d4 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_pull_test.cpp
@@ -63,483 +63,484 @@
     return config;
 }
 
-}  // namespace
+}  // namespaces
 
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
-    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-
-    // When creating the config, the gauge metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& nextPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
-    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                        configAddedTimeNs + 55);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    // Pulling alarm arrives on time and reset the sequential pulling alarm.
-    processor->informPullAlarmFired(nextPullTimeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
-
-    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + bucketSizeNs + 10);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + bucketSizeNs + 100);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    processor->informPullAlarmFired(nextPullTimeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
-              nextPullTimeNs);
-
-    processor->informPullAlarmFired(nextPullTimeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
-
-    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                  configAddedTimeNs + 3 * bucketSizeNs + 2);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    processor->informPullAlarmFired(nextPullTimeNs + 3);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                  configAddedTimeNs + 5 * bucketSizeNs + 1);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    processor->informPullAlarmFired(nextPullTimeNs + 2);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
-
-    processor->informPullAlarmFired(nextPullTimeNs + 2);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
-    auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(6, data.bucket_info_size());
-
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
-              data.bucket_info(1).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(2).atom_size());
-    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
-              data.bucket_info(2).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(3).atom_size());
-    EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
-              data.bucket_info(3).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(4).atom_size());
-    EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
-              data.bucket_info(4).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(5).atom_size());
-    EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
-              data.bucket_info(5).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
-}
-
-TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
-    auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-
-    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                        configAddedTimeNs + 55);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + bucketSizeNs + 10);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + bucketSizeNs + 100);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                  configAddedTimeNs + 3 * bucketSizeNs + 2);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                  configAddedTimeNs + 5 * bucketSizeNs + 1);
-    processor->OnLogEvent(screenOffEvent.get());
-    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                  configAddedTimeNs + 5 * bucketSizeNs + 3);
-    processor->OnLogEvent(screenOnEvent.get());
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                  configAddedTimeNs + 5 * bucketSizeNs + 10);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
-    auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
-
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
-              data.bucket_info(1).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(2, data.bucket_info(2).atom_size());
-    EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
-              data.bucket_info(2).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
-              data.bucket_info(2).elapsed_timestamp_nanos(1));
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
-    EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
-}
-
-
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
-    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-
-    // When creating the config, the gauge metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& nextPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
-    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                        configAddedTimeNs + 55);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + bucketSizeNs + 10);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    // Pulling alarm arrives one bucket size late.
-    processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + 3 * bucketSizeNs + 11);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    // Pulling alarm arrives more than one bucket size late.
-    processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
-
-    auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
-
-    EXPECT_EQ(1, data.bucket_info(0).atom_size());
-    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(1).atom_size());
-    EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
-              data.bucket_info(1).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    EXPECT_EQ(1, data.bucket_info(2).atom_size());
-    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
-              data.bucket_info(2).elapsed_timestamp_nanos(0));
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
-}
-
-TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
-    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
-
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-    auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
-    *config.add_atom_matcher() = batterySaverStartMatcher;
-    const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
-    auto metric_activation = config.add_metric_activation();
-    metric_activation->set_metric_id(metricId);
-    metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
-    auto event_activation = metric_activation->add_event_activation();
-    event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
-    event_activation->set_ttl_seconds(ttlNs / 1000000000);
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             ATOM_TAG);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // When creating the config, the gauge metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& nextPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
-
-    // Pulling alarm arrives on time and reset the sequential pulling alarm.
-    // Event should not be kept.
-    processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // Activate the metric. A pull occurs upon activation.
-    const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
-    auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
-    processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // This event should be kept. 2 total.
-    processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
-              nextPullTimeNs);
-
-    // This event should be kept. 3 total.
-    processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
-
-    // Create random event to deactivate metric.
-    auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
-    processor->OnLogEvent(deactivationEvent.get());
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // Event should not be kept. 3 total.
-    processor->informPullAlarmFired(nextPullTimeNs + 3);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
-
-    processor->informPullAlarmFired(nextPullTimeNs + 2);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-    EXPECT_GT((int)gaugeMetrics.data_size(), 0);
-
-    auto data = gaugeMetrics.data(0);
-    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
-    EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    bucketInfo = data.bucket_info(1);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-
-    bucketInfo = data.bucket_info(2);
-    EXPECT_EQ(1, bucketInfo.atom_size());
-    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
-    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
-    EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
-            bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
-            bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
-    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvents) {
+//    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             ATOM_TAG);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//
+//    // When creating the config, the gauge metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& nextPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+//    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                        configAddedTimeNs + 55);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    // Pulling alarm arrives on time and reset the sequential pulling alarm.
+//    processor->informPullAlarmFired(nextPullTimeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
+//
+//    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + bucketSizeNs + 10);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + bucketSizeNs + 100);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
+//              nextPullTimeNs);
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
+//
+//    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                  configAddedTimeNs + 3 * bucketSizeNs + 2);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 3);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                  configAddedTimeNs + 5 * bucketSizeNs + 1);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 2);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, nextPullTimeNs);
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 2);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+//    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+//    auto data = gaugeMetrics.data(0);
+//    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    EXPECT_EQ(6, data.bucket_info_size());
+//
+//    EXPECT_EQ(1, data.bucket_info(0).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1,
+//              data.bucket_info(1).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 1, data.bucket_info(1).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(2).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1,
+//              data.bucket_info(2).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(3).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(3).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 1,
+//              data.bucket_info(3).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(3).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(3).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(4).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(4).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
+//              data.bucket_info(4).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(4).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(4).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(4).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(4).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(5).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(5).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs + 2,
+//              data.bucket_info(5).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(5).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(5).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(5).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(5).atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//TEST(GaugeMetricE2eTest, TestConditionChangeToTrueSamplePulledEvents) {
+//    auto config = CreateStatsdConfig(GaugeMetric::CONDITION_CHANGE_TO_TRUE);
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             ATOM_TAG);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//
+//    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                        configAddedTimeNs + 55);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + bucketSizeNs + 10);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + bucketSizeNs + 100);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                  configAddedTimeNs + 3 * bucketSizeNs + 2);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                  configAddedTimeNs + 5 * bucketSizeNs + 1);
+//    processor->OnLogEvent(screenOffEvent.get());
+//    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                  configAddedTimeNs + 5 * bucketSizeNs + 3);
+//    processor->OnLogEvent(screenOnEvent.get());
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                  configAddedTimeNs + 5 * bucketSizeNs + 10);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 8 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+//    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+//    auto data = gaugeMetrics.data(0);
+//    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    EXPECT_EQ(3, data.bucket_info_size());
+//
+//    EXPECT_EQ(1, data.bucket_info(0).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs + 100,
+//              data.bucket_info(1).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(2, data.bucket_info(2).atom_size());
+//    EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 1,
+//              data.bucket_info(2).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs + 10,
+//              data.bucket_info(2).elapsed_timestamp_nanos(1));
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+//    EXPECT_TRUE(data.bucket_info(2).atom(1).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(2).atom(1).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEvent_LateAlarm) {
+//    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE);
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             ATOM_TAG);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//
+//    // When creating the config, the gauge metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& nextPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+//    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                        configAddedTimeNs + 55);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + bucketSizeNs + 10);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    // Pulling alarm arrives one bucket size late.
+//    processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, nextPullTimeNs);
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + 3 * bucketSizeNs + 11);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    // Pulling alarm arrives more than one bucket size late.
+//    processor->informPullAlarmFired(nextPullTimeNs + bucketSizeNs + 12);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+//    EXPECT_GT((int)gaugeMetrics.data_size(), 1);
+//
+//    auto data = gaugeMetrics.data(0);
+//    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    EXPECT_EQ(3, data.bucket_info_size());
+//
+//    EXPECT_EQ(1, data.bucket_info(0).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(0).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(0).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(1).atom_size());
+//    EXPECT_EQ(configAddedTimeNs + 3 * bucketSizeNs + 11,
+//              data.bucket_info(1).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(configAddedTimeNs + 55, data.bucket_info(0).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(1).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(1).atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    EXPECT_EQ(1, data.bucket_info(2).atom_size());
+//    EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs + 12,
+//              data.bucket_info(2).elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(data.bucket_info(2).atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(data.bucket_info(2).atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
+//
+//TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsWithActivation) {
+//    auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
+//
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+//    auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
+//    *config.add_atom_matcher() = batterySaverStartMatcher;
+//    const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
+//    auto metric_activation = config.add_metric_activation();
+//    metric_activation->set_metric_id(metricId);
+//    metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+//    auto event_activation = metric_activation->add_event_activation();
+//    event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
+//    event_activation->set_ttl_seconds(ttlNs / 1000000000);
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             ATOM_TAG);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // When creating the config, the gauge metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& nextPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, nextPullTimeNs);
+//
+//    // Pulling alarm arrives on time and reset the sequential pulling alarm.
+//    // Event should not be kept.
+//    processor->informPullAlarmFired(nextPullTimeNs + 1); // 15 mins + 1 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, nextPullTimeNs);
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // Activate the metric. A pull occurs upon activation.
+//    const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
+//    auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
+//    processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // This event should be kept. 2 total.
+//    processor->informPullAlarmFired(nextPullTimeNs + 1); // 20 mins + 1 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs,
+//              nextPullTimeNs);
+//
+//    // This event should be kept. 3 total.
+//    processor->informPullAlarmFired(nextPullTimeNs + 2); // 25 mins + 2 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, nextPullTimeNs);
+//
+//    // Create random event to deactivate metric.
+//    auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
+//    processor->OnLogEvent(deactivationEvent.get());
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // Event should not be kept. 3 total.
+//    processor->informPullAlarmFired(nextPullTimeNs + 3);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, nextPullTimeNs);
+//
+//    processor->informPullAlarmFired(nextPullTimeNs + 2);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+//    EXPECT_GT((int)gaugeMetrics.data_size(), 0);
+//
+//    auto data = gaugeMetrics.data(0);
+//    EXPECT_EQ(ATOM_TAG, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    EXPECT_EQ(3, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(1, bucketInfo.atom_size());
+//    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(activationNs, bucketInfo.elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    bucketInfo = data.bucket_info(1);
+//    EXPECT_EQ(1, bucketInfo.atom_size());
+//    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs + 1, bucketInfo.elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//
+//    bucketInfo = data.bucket_info(2);
+//    EXPECT_EQ(1, bucketInfo.atom_size());
+//    EXPECT_EQ(1, bucketInfo.elapsed_timestamp_nanos_size());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs + 2, bucketInfo.elapsed_timestamp_nanos(0));
+//    EXPECT_EQ(0, bucketInfo.wall_clock_timestamp_nanos_size());
+//    EXPECT_EQ(MillisToNano(NanoToMillis(baseTimeNs + 5 * bucketSizeNs)),
+//            bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(MillisToNano(NanoToMillis(activationNs + ttlNs + 1)),
+//            bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_TRUE(bucketInfo.atom(0).subsystem_sleep_state().subsystem_name().empty());
+//    EXPECT_GT(bucketInfo.atom(0).subsystem_sleep_state().time_millis(), 0);
+//}
 
 TEST(GaugeMetricE2eTest, TestRandomSamplePulledEventsNoCondition) {
     auto config = CreateStatsdConfig(GaugeMetric::RANDOM_ONE_SAMPLE, /*useCondition=*/false);
diff --git a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
index cd80310..ef6e753 100644
--- a/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
+++ b/cmds/statsd/tests/e2e/GaugeMetric_e2e_push_test.cpp
@@ -68,219 +68,221 @@
     return config;
 }
 
-std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
-    const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
-    const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
-    int64_t activity_start_msec, uint64_t timestampNs) {
-    auto logEvent = std::make_unique<LogEvent>(
-        android::util::APP_START_OCCURRED, timestampNs);
-    logEvent->write(uid);
-    logEvent->write(pkg_name);
-    logEvent->write(type);
-    logEvent->write(activity_name);
-    logEvent->write(calling_pkg_name);
-    logEvent->write(is_instant_app);
-    logEvent->write(activity_start_msec);
-    logEvent->init();
-    return logEvent;
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//std::unique_ptr<LogEvent> CreateAppStartOccurredEvent(
+//    const int uid, const string& pkg_name, AppStartOccurred::TransitionType type,
+//    const string& activity_name, const string& calling_pkg_name, const bool is_instant_app,
+//    int64_t activity_start_msec, uint64_t timestampNs) {
+//    auto logEvent = std::make_unique<LogEvent>(
+//        android::util::APP_START_OCCURRED, timestampNs);
+//    logEvent->write(uid);
+//    logEvent->write(pkg_name);
+//    logEvent->write(type);
+//    logEvent->write(activity_name);
+//    logEvent->write(calling_pkg_name);
+//    logEvent->write(is_instant_app);
+//    logEvent->write(activity_start_msec);
+//    logEvent->init();
+//    return logEvent;
+//}
 
 }  // namespace
 
-TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
-    for (const auto& sampling_type :
-            { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
-        auto config = CreateStatsdConfigForPushedEvent(sampling_type);
-        int64_t bucketStartTimeNs = 10000000000;
-        int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
-
-        ConfigKey cfgKey;
-        auto processor = CreateStatsLogProcessor(
-                bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-        EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-        EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-        int appUid1 = 123;
-        int appUid2 = 456;
-        std::vector<std::unique_ptr<LogEvent>> events;
-        events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
-        events.push_back(CreateMoveToForegroundEvent(
-                appUid1, bucketStartTimeNs + bucketSizeNs + 250));
-        events.push_back(CreateMoveToBackgroundEvent(
-                appUid1, bucketStartTimeNs + bucketSizeNs + 350));
-        events.push_back(CreateMoveToForegroundEvent(
-            appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
-
-
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
-            true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
-            true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
-            true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
-            true /*is_instant_app*/, 104 /*activity_start_msec*/,
-            bucketStartTimeNs + bucketSizeNs + 30));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
-            true /*is_instant_app*/, 105 /*activity_start_msec*/,
-            bucketStartTimeNs + 2 * bucketSizeNs));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
-            false /*is_instant_app*/, 106 /*activity_start_msec*/,
-            bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
-        events.push_back(CreateMoveToBackgroundEvent(
-                appUid2, bucketStartTimeNs + bucketSizeNs + 10));
-        events.push_back(CreateAppStartOccurredEvent(
-            appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
-            true /*is_instant_app*/, 201 /*activity_start_msec*/,
-            bucketStartTimeNs + 2 * bucketSizeNs + 10));
-
-        sortLogEventsByTimestamp(&events);
-
-        for (const auto& event : events) {
-            processor->OnLogEvent(event.get());
-        }
-        ConfigMetricsReportList reports;
-        vector<uint8_t> buffer;
-        processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
-                                ADB_DUMP, FAST, &buffer);
-        EXPECT_TRUE(buffer.size() > 0);
-        EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-        backfillDimensionPath(&reports);
-        backfillStringInReport(&reports);
-        backfillStartEndTimestamp(&reports);
-        EXPECT_EQ(1, reports.reports_size());
-        EXPECT_EQ(1, reports.reports(0).metrics_size());
-        StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
-        sortMetricDataByDimensionsValue(
-                reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
-        EXPECT_EQ(2, gaugeMetrics.data_size());
-
-        auto data = gaugeMetrics.data(0);
-        EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
-        EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-        EXPECT_EQ(1 /* uid field */,
-                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-        EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-        EXPECT_EQ(3, data.bucket_info_size());
-        if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
-            EXPECT_EQ(2, data.bucket_info(0).atom_size());
-            EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-                      data.bucket_info(0).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::HOT,
-                      data.bucket_info(0).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name2",
-                      data.bucket_info(0).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(102L,
-                      data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
-            EXPECT_EQ(AppStartOccurred::COLD,
-                      data.bucket_info(0).atom(1).app_start_occurred().type());
-            EXPECT_EQ("activity_name3",
-                      data.bucket_info(0).atom(1).app_start_occurred().activity_name());
-            EXPECT_EQ(103L,
-                      data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
-
-            EXPECT_EQ(1, data.bucket_info(1).atom_size());
-            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-                      data.bucket_info(1).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-                      data.bucket_info(1).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::WARM,
-                      data.bucket_info(1).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name4",
-                      data.bucket_info(1).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(104L,
-                      data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
-
-            EXPECT_EQ(2, data.bucket_info(2).atom_size());
-            EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-                      data.bucket_info(2).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-                      data.bucket_info(2).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::COLD,
-                      data.bucket_info(2).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name5",
-                      data.bucket_info(2).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(105L,
-                      data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
-            EXPECT_EQ(AppStartOccurred::HOT,
-                      data.bucket_info(2).atom(1).app_start_occurred().type());
-            EXPECT_EQ("activity_name6",
-                      data.bucket_info(2).atom(1).app_start_occurred().activity_name());
-            EXPECT_EQ(106L,
-                      data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
-        } else {
-            EXPECT_EQ(1, data.bucket_info(0).atom_size());
-            EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-                      data.bucket_info(0).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::HOT,
-                      data.bucket_info(0).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name2",
-                      data.bucket_info(0).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(102L,
-                      data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
-
-            EXPECT_EQ(1, data.bucket_info(1).atom_size());
-            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-                      data.bucket_info(1).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-                      data.bucket_info(1).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::WARM,
-                      data.bucket_info(1).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name4",
-                      data.bucket_info(1).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(104L,
-                      data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
-
-            EXPECT_EQ(1, data.bucket_info(2).atom_size());
-            EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
-            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-                      data.bucket_info(2).start_bucket_elapsed_nanos());
-            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-                      data.bucket_info(2).end_bucket_elapsed_nanos());
-            EXPECT_EQ(AppStartOccurred::COLD,
-                      data.bucket_info(2).atom(0).app_start_occurred().type());
-            EXPECT_EQ("activity_name5",
-                      data.bucket_info(2).atom(0).app_start_occurred().activity_name());
-            EXPECT_EQ(105L,
-                      data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
-        }
-
-        data = gaugeMetrics.data(1);
-
-        EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
-        EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
-        EXPECT_EQ(1 /* uid field */,
-                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-        EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-        EXPECT_EQ(1, data.bucket_info_size());
-        EXPECT_EQ(1, data.bucket_info(0).atom_size());
-        EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
-        EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-                  data.bucket_info(0).start_bucket_elapsed_nanos());
-        EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-                  data.bucket_info(0).end_bucket_elapsed_nanos());
-        EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
-        EXPECT_EQ("activity_name7",
-                  data.bucket_info(0).atom(0).app_start_occurred().activity_name());
-        EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
-    }
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(GaugeMetricE2eTest, TestMultipleFieldsForPushedEvent) {
+//    for (const auto& sampling_type :
+//            { GaugeMetric::FIRST_N_SAMPLES, GaugeMetric:: RANDOM_ONE_SAMPLE }) {
+//        auto config = CreateStatsdConfigForPushedEvent(sampling_type);
+//        int64_t bucketStartTimeNs = 10000000000;
+//        int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.gauge_metric(0).bucket()) * 1000000;
+//
+//        ConfigKey cfgKey;
+//        auto processor = CreateStatsLogProcessor(
+//                bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//        EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//        EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//        int appUid1 = 123;
+//        int appUid2 = 456;
+//        std::vector<std::unique_ptr<LogEvent>> events;
+//        events.push_back(CreateMoveToBackgroundEvent(appUid1, bucketStartTimeNs + 15));
+//        events.push_back(CreateMoveToForegroundEvent(
+//                appUid1, bucketStartTimeNs + bucketSizeNs + 250));
+//        events.push_back(CreateMoveToBackgroundEvent(
+//                appUid1, bucketStartTimeNs + bucketSizeNs + 350));
+//        events.push_back(CreateMoveToForegroundEvent(
+//            appUid1, bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//
+//
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::WARM, "activity_name1", "calling_pkg_name1",
+//            true /*is_instant_app*/, 101 /*activity_start_msec*/, bucketStartTimeNs + 10));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::HOT, "activity_name2", "calling_pkg_name2",
+//            true /*is_instant_app*/, 102 /*activity_start_msec*/, bucketStartTimeNs + 20));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::COLD, "activity_name3", "calling_pkg_name3",
+//            true /*is_instant_app*/, 103 /*activity_start_msec*/, bucketStartTimeNs + 30));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::WARM, "activity_name4", "calling_pkg_name4",
+//            true /*is_instant_app*/, 104 /*activity_start_msec*/,
+//            bucketStartTimeNs + bucketSizeNs + 30));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::COLD, "activity_name5", "calling_pkg_name5",
+//            true /*is_instant_app*/, 105 /*activity_start_msec*/,
+//            bucketStartTimeNs + 2 * bucketSizeNs));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid1, "app1", AppStartOccurred::HOT, "activity_name6", "calling_pkg_name6",
+//            false /*is_instant_app*/, 106 /*activity_start_msec*/,
+//            bucketStartTimeNs + 2 * bucketSizeNs + 10));
+//
+//        events.push_back(CreateMoveToBackgroundEvent(
+//                appUid2, bucketStartTimeNs + bucketSizeNs + 10));
+//        events.push_back(CreateAppStartOccurredEvent(
+//            appUid2, "app2", AppStartOccurred::COLD, "activity_name7", "calling_pkg_name7",
+//            true /*is_instant_app*/, 201 /*activity_start_msec*/,
+//            bucketStartTimeNs + 2 * bucketSizeNs + 10));
+//
+//        sortLogEventsByTimestamp(&events);
+//
+//        for (const auto& event : events) {
+//            processor->OnLogEvent(event.get());
+//        }
+//        ConfigMetricsReportList reports;
+//        vector<uint8_t> buffer;
+//        processor->onDumpReport(cfgKey, bucketStartTimeNs + 3 * bucketSizeNs, false, true,
+//                                ADB_DUMP, FAST, &buffer);
+//        EXPECT_TRUE(buffer.size() > 0);
+//        EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//        backfillDimensionPath(&reports);
+//        backfillStringInReport(&reports);
+//        backfillStartEndTimestamp(&reports);
+//        EXPECT_EQ(1, reports.reports_size());
+//        EXPECT_EQ(1, reports.reports(0).metrics_size());
+//        StatsLogReport::GaugeMetricDataWrapper gaugeMetrics;
+//        sortMetricDataByDimensionsValue(
+//                reports.reports(0).metrics(0).gauge_metrics(), &gaugeMetrics);
+//        EXPECT_EQ(2, gaugeMetrics.data_size());
+//
+//        auto data = gaugeMetrics.data(0);
+//        EXPECT_EQ(android::util::APP_START_OCCURRED, data.dimensions_in_what().field());
+//        EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//        EXPECT_EQ(1 /* uid field */,
+//                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//        EXPECT_EQ(appUid1, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//        EXPECT_EQ(3, data.bucket_info_size());
+//        if (sampling_type == GaugeMetric::FIRST_N_SAMPLES) {
+//            EXPECT_EQ(2, data.bucket_info(0).atom_size());
+//            EXPECT_EQ(2, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(0, data.bucket_info(0).wall_clock_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//                      data.bucket_info(0).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::HOT,
+//                      data.bucket_info(0).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name2",
+//                      data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(102L,
+//                      data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+//            EXPECT_EQ(AppStartOccurred::COLD,
+//                      data.bucket_info(0).atom(1).app_start_occurred().type());
+//            EXPECT_EQ("activity_name3",
+//                      data.bucket_info(0).atom(1).app_start_occurred().activity_name());
+//            EXPECT_EQ(103L,
+//                      data.bucket_info(0).atom(1).app_start_occurred().activity_start_millis());
+//
+//            EXPECT_EQ(1, data.bucket_info(1).atom_size());
+//            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//                      data.bucket_info(1).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//                      data.bucket_info(1).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::WARM,
+//                      data.bucket_info(1).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name4",
+//                      data.bucket_info(1).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(104L,
+//                      data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
+//
+//            EXPECT_EQ(2, data.bucket_info(2).atom_size());
+//            EXPECT_EQ(2, data.bucket_info(2).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//                      data.bucket_info(2).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//                      data.bucket_info(2).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::COLD,
+//                      data.bucket_info(2).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name5",
+//                      data.bucket_info(2).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(105L,
+//                      data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
+//            EXPECT_EQ(AppStartOccurred::HOT,
+//                      data.bucket_info(2).atom(1).app_start_occurred().type());
+//            EXPECT_EQ("activity_name6",
+//                      data.bucket_info(2).atom(1).app_start_occurred().activity_name());
+//            EXPECT_EQ(106L,
+//                      data.bucket_info(2).atom(1).app_start_occurred().activity_start_millis());
+//        } else {
+//            EXPECT_EQ(1, data.bucket_info(0).atom_size());
+//            EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//                      data.bucket_info(0).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::HOT,
+//                      data.bucket_info(0).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name2",
+//                      data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(102L,
+//                      data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+//
+//            EXPECT_EQ(1, data.bucket_info(1).atom_size());
+//            EXPECT_EQ(1, data.bucket_info(1).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//                      data.bucket_info(1).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//                      data.bucket_info(1).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::WARM,
+//                      data.bucket_info(1).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name4",
+//                      data.bucket_info(1).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(104L,
+//                      data.bucket_info(1).atom(0).app_start_occurred().activity_start_millis());
+//
+//            EXPECT_EQ(1, data.bucket_info(2).atom_size());
+//            EXPECT_EQ(1, data.bucket_info(2).elapsed_timestamp_nanos_size());
+//            EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//                      data.bucket_info(2).start_bucket_elapsed_nanos());
+//            EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//                      data.bucket_info(2).end_bucket_elapsed_nanos());
+//            EXPECT_EQ(AppStartOccurred::COLD,
+//                      data.bucket_info(2).atom(0).app_start_occurred().type());
+//            EXPECT_EQ("activity_name5",
+//                      data.bucket_info(2).atom(0).app_start_occurred().activity_name());
+//            EXPECT_EQ(105L,
+//                      data.bucket_info(2).atom(0).app_start_occurred().activity_start_millis());
+//        }
+//
+//        data = gaugeMetrics.data(1);
+//
+//        EXPECT_EQ(data.dimensions_in_what().field(), android::util::APP_START_OCCURRED);
+//        EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+//        EXPECT_EQ(1 /* uid field */,
+//                  data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//        EXPECT_EQ(appUid2, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//        EXPECT_EQ(1, data.bucket_info_size());
+//        EXPECT_EQ(1, data.bucket_info(0).atom_size());
+//        EXPECT_EQ(1, data.bucket_info(0).elapsed_timestamp_nanos_size());
+//        EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//                  data.bucket_info(0).start_bucket_elapsed_nanos());
+//        EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//                  data.bucket_info(0).end_bucket_elapsed_nanos());
+//        EXPECT_EQ(AppStartOccurred::COLD, data.bucket_info(0).atom(0).app_start_occurred().type());
+//        EXPECT_EQ("activity_name7",
+//                  data.bucket_info(0).atom(0).app_start_occurred().activity_name());
+//        EXPECT_EQ(201L, data.bucket_info(0).atom(0).app_start_occurred().activity_start_millis());
+//    }
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
index b6a6492..f3f7df77 100644
--- a/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricActivation_e2e_test.cpp
@@ -233,1608 +233,1609 @@
 
 }  // namespace
 
-TEST(MetricActivationE2eTest, TestCountMetric) {
-    auto config = CreateStatsdConfig();
-
-    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
-    int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
-    // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
-    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
-    std::unique_ptr<LogEvent> event;
-
-    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 0);
-
-    // Activated by battery save mode.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
-    // First processed event.
-    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
-    // Activated by screen on event.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 20);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
-    // 2nd processed event.
-    // The activation by screen_on event expires, but the one by battery save mode is still active.
-    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    // No new broadcast since the config should still be active.
-    EXPECT_EQ(broadcastCount, 1);
-
-    // 3rd processed event.
-    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
-    // All activations expired.
-    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
-    // Re-activate metric via screen on.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-
-    // 4th processed event.
-    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(4, countMetrics.data_size());
-
-    auto data = countMetrics.data(0);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation) {
-    auto config = CreateStatsdConfigWithOneDeactivation();
-
-    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
-    int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
-    // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
-    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 1u);
-    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    std::unique_ptr<LogEvent> event;
-
-    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 0);
-
-    // Activated by battery save mode.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // First processed event.
-    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
-    // Activated by screen on event.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 20);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // 2nd processed event.
-    // The activation by screen_on event expires, but the one by battery save mode is still active.
-    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    // No new broadcast since the config should still be active.
-    EXPECT_EQ(broadcastCount, 1);
-
-    // 3rd processed event.
-    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
-    // All activations expired.
-    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // Re-activate metric via screen on.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // 4th processed event.
-    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // 5th processed event.
-    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
-    // Cancel battery saver mode activation.
-    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // Screen-on activation expired.
-    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    // Cancel battery saver mode activation.
-    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
-
-    auto data = countMetrics.data(0);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(4);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations) {
-    auto config = CreateStatsdConfigWithTwoDeactivations();
-
-    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
-    int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
-    // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
-    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 2u);
-    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    std::unique_ptr<LogEvent> event;
-
-    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 0);
-
-    // Activated by battery save mode.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // First processed event.
-    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
-    // Activated by screen on event.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 20);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // 2nd processed event.
-    // The activation by screen_on event expires, but the one by battery save mode is still active.
-    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    // No new broadcast since the config should still be active.
-    EXPECT_EQ(broadcastCount, 1);
-
-    // 3rd processed event.
-    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
-    // All activations expired.
-    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // Re-activate metric via screen on.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // 4th processed event.
-    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // 5th processed event.
-    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
-    // Cancel battery saver mode and screen on activation.
-    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // Screen-on activation expired.
-    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    // Cancel battery saver mode and screen on activation.
-    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
-
-    auto data = countMetrics.data(0);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(4);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation) {
-    auto config = CreateStatsdConfigWithSameDeactivations();
-
-    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
-    int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
-    // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
-    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 1u);
-    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 2u);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[3][1], eventActivationMap[2]);
-    EXPECT_EQ(broadcastCount, 0);
-
-    std::unique_ptr<LogEvent> event;
-
-    // Event that should be ignored.
-    event = CreateAppCrashEvent(111, bucketStartTimeNs + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 1);
-
-    // Activate metric via screen on for 2 minutes.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
-
-    // 1st processed event.
-    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
-    // Enable battery saver mode activation for 5 minutes.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 + 10);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
-
-    // 2nd processed event.
-    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 + 40);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 40);
-
-    // Cancel battery saver mode and screen on activation.
-    int64_t firstDeactivation = bucketStartTimeNs + NS_PER_SEC * 61;
-    event = CreateScreenBrightnessChangedEvent(64, firstDeactivation);
-    processor.OnLogEvent(event.get(), firstDeactivation);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
-    // Should be ignored
-    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 61 + 80);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 61 + 80);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
-    // 3rd processed event.
-    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
-
-    // Cancel battery saver mode activation.
-    int64_t secondDeactivation = bucketStartTimeNs + NS_PER_SEC * 60 * 13;
-    event = CreateScreenBrightnessChangedEvent(140, secondDeactivation);
-    processor.OnLogEvent(event.get(), secondDeactivation);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-
-    // Should be ignored.
-    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(3, countMetrics.data_size());
-
-    auto data = countMetrics.data(0);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(555, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(secondDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
-}
-
-TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations) {
-    auto config = CreateStatsdConfigWithTwoMetricsTwoDeactivations();
-
-    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
-    int64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
-
-    int uid = 12345;
-    int64_t cfgId = 98765;
-    ConfigKey cfgKey(uid, cfgId);
-
-    sp<UidMap> m = new UidMap();
-    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
-    sp<AlarmMonitor> anomalyAlarmMonitor;
-    sp<AlarmMonitor> subscriberAlarmMonitor;
-    vector<int64_t> activeConfigsBroadcast;
-
-    long timeBase1 = 1;
-    int broadcastCount = 0;
-    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
-            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
-            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
-                    const vector<int64_t>& activeConfigs) {
-                broadcastCount++;
-                EXPECT_EQ(broadcastUid, uid);
-                activeConfigsBroadcast.clear();
-                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
-                        activeConfigs.begin(), activeConfigs.end());
-                return true;
-            });
-
-    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
-
-    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
-    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
-    EXPECT_TRUE(metricsManager->isConfigValid());
-    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 2);
-    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
-    auto& eventActivationMap = metricProducer->mEventActivationMap;
-    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
-    sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
-    auto& eventActivationMap2 = metricProducer2->mEventActivationMap;
-    auto& eventDeactivationMap2 = metricProducer2->mEventDeactivationMap;
-
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
-    // triggered by screen on event (tracker index 2).
-    EXPECT_EQ(eventActivationMap.size(), 2u);
-    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
-    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap.size(), 2u);
-    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
-    EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-
-    EXPECT_EQ(eventActivationMap2.size(), 2u);
-    EXPECT_TRUE(eventActivationMap2.find(0) != eventActivationMap2.end());
-    EXPECT_TRUE(eventActivationMap2.find(2) != eventActivationMap2.end());
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2.size(), 2u);
-    EXPECT_TRUE(eventDeactivationMap2.find(3) != eventDeactivationMap2.end());
-    EXPECT_TRUE(eventDeactivationMap2.find(4) != eventDeactivationMap2.end());
-    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    std::unique_ptr<LogEvent> event;
-
-    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
-    event = CreateMoveToForegroundEvent(1111, bucketStartTimeNs + 5);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    EXPECT_EQ(broadcastCount, 0);
-
-    // Activated by battery save mode.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 1);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // First processed event.
-    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-    event = CreateMoveToForegroundEvent(2222, bucketStartTimeNs + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
-
-    // Activated by screen on event.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 20);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // 2nd processed event.
-    // The activation by screen_on event expires, but the one by battery save mode is still active.
-    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    event = CreateMoveToForegroundEvent(3333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-    // No new broadcast since the config should still be active.
-    EXPECT_EQ(broadcastCount, 1);
-
-    // 3rd processed event.
-    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    event = CreateMoveToForegroundEvent(4444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
-
-    // All activations expired.
-    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    event = CreateMoveToForegroundEvent(5555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
-    EXPECT_FALSE(metricsManager->isActive());
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 2);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // Re-activate metric via screen on.
-    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // 4th processed event.
-    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    event = CreateMoveToForegroundEvent(6666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 3);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // 5th processed event.
-    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-    event = CreateMoveToForegroundEvent(7777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
-
-    // Cancel battery saver mode and screen on activation.
-    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
-    EXPECT_FALSE(metricsManager->isActive());
-    // New broadcast since the config is no longer active.
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // Screen-on activation expired.
-    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    event = CreateMoveToForegroundEvent(8888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 4);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-    event = CreateMoveToForegroundEvent(9999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
-
-    // Re-enable battery saver mode activation.
-    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_TRUE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 5);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
-    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
-    EXPECT_TRUE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_TRUE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    // Cancel battery saver mode and screen on activation.
-    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 16);
-    EXPECT_FALSE(metricsManager->isActive());
-    EXPECT_EQ(broadcastCount, 6);
-    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
-    EXPECT_FALSE(metricProducer->mIsActive);
-    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
-    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
-    EXPECT_FALSE(metricProducer2->mIsActive);
-    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
-    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
-    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
-    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
-    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
-    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
-    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(2, reports.reports(0).metrics_size());
-    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
-    EXPECT_EQ(5, reports.reports(0).metrics(1).count_metrics().data_size());
-
-    StatsLogReport::CountMetricDataWrapper countMetrics;
-
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
-
-    auto data = countMetrics.data(0);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(4);
-    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-
-   countMetrics.clear_data();
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(1).count_metrics(), &countMetrics);
-    EXPECT_EQ(5, countMetrics.data_size());
-
-    data = countMetrics.data(0);
-    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(2222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(1);
-    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(3333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(2);
-    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(4444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    // Partial bucket as metric is deactivated.
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(3);
-    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(6666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-
-    data = countMetrics.data(4);
-    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* uid field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_EQ(7777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(1, data.bucket_info(0).count());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
-              data.bucket_info(0).end_bucket_elapsed_nanos());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(MetricActivationE2eTest, TestCountMetric) {
+//    auto config = CreateStatsdConfig();
+//
+//    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+//    int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+//    // triggered by screen on event (tracker index 2).
+//    EXPECT_EQ(eventActivationMap.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    // Activated by battery save mode.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+//    // First processed event.
+//    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+//    // Activated by screen on event.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 20);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+//    // 2nd processed event.
+//    // The activation by screen_on event expires, but the one by battery save mode is still active.
+//    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    // No new broadcast since the config should still be active.
+//    EXPECT_EQ(broadcastCount, 1);
+//
+//    // 3rd processed event.
+//    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+//    // All activations expired.
+//    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+//    // Re-activate metric via screen on.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//
+//    // 4th processed event.
+//    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(4, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(4, countMetrics.data_size());
+//
+//    auto data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithOneDeactivation) {
+//    auto config = CreateStatsdConfigWithOneDeactivation();
+//
+//    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+//    int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+//    // triggered by screen on event (tracker index 2).
+//    EXPECT_EQ(eventActivationMap.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap.size(), 1u);
+//    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+//    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    // Activated by battery save mode.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // First processed event.
+//    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+//    // Activated by screen on event.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 20);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // 2nd processed event.
+//    // The activation by screen_on event expires, but the one by battery save mode is still active.
+//    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    // No new broadcast since the config should still be active.
+//    EXPECT_EQ(broadcastCount, 1);
+//
+//    // 3rd processed event.
+//    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+//    // All activations expired.
+//    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // Re-activate metric via screen on.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // 4th processed event.
+//    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // 5th processed event.
+//    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+//    // Cancel battery saver mode activation.
+//    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // Screen-on activation expired.
+//    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 5);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    // Cancel battery saver mode activation.
+//    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 6);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(5, countMetrics.data_size());
+//
+//    auto data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(4);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 13,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithTwoDeactivations) {
+//    auto config = CreateStatsdConfigWithTwoDeactivations();
+//
+//    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+//    int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+//    // triggered by screen on event (tracker index 2).
+//    EXPECT_EQ(eventActivationMap.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap.size(), 2u);
+//    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+//    EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
+//    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    // Activated by battery save mode.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // First processed event.
+//    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+//    // Activated by screen on event.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 20);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // 2nd processed event.
+//    // The activation by screen_on event expires, but the one by battery save mode is still active.
+//    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    // No new broadcast since the config should still be active.
+//    EXPECT_EQ(broadcastCount, 1);
+//
+//    // 3rd processed event.
+//    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+//    // All activations expired.
+//    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // Re-activate metric via screen on.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // 4th processed event.
+//    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // 5th processed event.
+//    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+//    // Cancel battery saver mode and screen on activation.
+//    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // Screen-on activation expired.
+//    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 5);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    // Cancel battery saver mode and screen on activation.
+//    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 6);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(5, countMetrics.data_size());
+//
+//    auto data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(4);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithSameDeactivation) {
+//    auto config = CreateStatsdConfigWithSameDeactivations();
+//
+//    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+//    int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 1);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+//    // triggered by screen on event (tracker index 2).
+//    EXPECT_EQ(eventActivationMap.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap.size(), 1u);
+//    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+//    EXPECT_EQ(eventDeactivationMap[3].size(), 2u);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[3][1], eventActivationMap[2]);
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    // Event that should be ignored.
+//    event = CreateAppCrashEvent(111, bucketStartTimeNs + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 1);
+//
+//    // Activate metric via screen on for 2 minutes.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON, bucketStartTimeNs + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
+//
+//    // 1st processed event.
+//    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+//    // Enable battery saver mode activation for 5 minutes.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 10);
+//
+//    // 2nd processed event.
+//    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 + 40);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 + 40);
+//
+//    // Cancel battery saver mode and screen on activation.
+//    int64_t firstDeactivation = bucketStartTimeNs + NS_PER_SEC * 61;
+//    event = CreateScreenBrightnessChangedEvent(64, firstDeactivation);
+//    processor.OnLogEvent(event.get(), firstDeactivation);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+//    // Should be ignored
+//    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 61 + 80);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 61 + 80);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 15);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+//    // 3rd processed event.
+//    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 80);
+//
+//    // Cancel battery saver mode activation.
+//    int64_t secondDeactivation = bucketStartTimeNs + NS_PER_SEC * 60 * 13;
+//    event = CreateScreenBrightnessChangedEvent(140, secondDeactivation);
+//    processor.OnLogEvent(event.get(), secondDeactivation);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//
+//    // Should be ignored.
+//    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13 + 80);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(3, reports.reports(0).metrics(0).count_metrics().data_size());
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(3, countMetrics.data_size());
+//
+//    auto data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(firstDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(555, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(secondDeactivation, data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
+//
+//TEST(MetricActivationE2eTest, TestCountMetricWithTwoMetricsTwoDeactivations) {
+//    auto config = CreateStatsdConfigWithTwoMetricsTwoDeactivations();
+//
+//    int64_t bucketStartTimeNs = NS_PER_SEC * 10; // 10 secs
+//    int64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000LL * 1000LL;
+//
+//    int uid = 12345;
+//    int64_t cfgId = 98765;
+//    ConfigKey cfgKey(uid, cfgId);
+//
+//    sp<UidMap> m = new UidMap();
+//    sp<StatsPullerManager> pullerManager = new StatsPullerManager();
+//    sp<AlarmMonitor> anomalyAlarmMonitor;
+//    sp<AlarmMonitor> subscriberAlarmMonitor;
+//    vector<int64_t> activeConfigsBroadcast;
+//
+//    long timeBase1 = 1;
+//    int broadcastCount = 0;
+//    StatsLogProcessor processor(m, pullerManager, anomalyAlarmMonitor, subscriberAlarmMonitor,
+//            bucketStartTimeNs, [](const ConfigKey& key) { return true; },
+//            [&uid, &broadcastCount, &activeConfigsBroadcast](const int& broadcastUid,
+//                    const vector<int64_t>& activeConfigs) {
+//                broadcastCount++;
+//                EXPECT_EQ(broadcastUid, uid);
+//                activeConfigsBroadcast.clear();
+//                activeConfigsBroadcast.insert(activeConfigsBroadcast.end(),
+//                        activeConfigs.begin(), activeConfigs.end());
+//                return true;
+//            });
+//
+//    processor.OnConfigUpdated(bucketStartTimeNs, cfgKey, config);
+//
+//    EXPECT_EQ(processor.mMetricsManagers.size(), 1u);
+//    sp<MetricsManager> metricsManager = processor.mMetricsManagers.begin()->second;
+//    EXPECT_TRUE(metricsManager->isConfigValid());
+//    EXPECT_EQ(metricsManager->mAllMetricProducers.size(), 2);
+//    sp<MetricProducer> metricProducer = metricsManager->mAllMetricProducers[0];
+//    auto& eventActivationMap = metricProducer->mEventActivationMap;
+//    auto& eventDeactivationMap = metricProducer->mEventDeactivationMap;
+//    sp<MetricProducer> metricProducer2 = metricsManager->mAllMetricProducers[1];
+//    auto& eventActivationMap2 = metricProducer2->mEventActivationMap;
+//    auto& eventDeactivationMap2 = metricProducer2->mEventDeactivationMap;
+//
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    // Two activations: one is triggered by battery saver mode (tracker index 0), the other is
+//    // triggered by screen on event (tracker index 2).
+//    EXPECT_EQ(eventActivationMap.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap.find(0) != eventActivationMap.end());
+//    EXPECT_TRUE(eventActivationMap.find(2) != eventActivationMap.end());
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap.size(), 2u);
+//    EXPECT_TRUE(eventDeactivationMap.find(3) != eventDeactivationMap.end());
+//    EXPECT_TRUE(eventDeactivationMap.find(4) != eventDeactivationMap.end());
+//    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//
+//    EXPECT_EQ(eventActivationMap2.size(), 2u);
+//    EXPECT_TRUE(eventActivationMap2.find(0) != eventActivationMap2.end());
+//    EXPECT_TRUE(eventActivationMap2.find(2) != eventActivationMap2.end());
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2.size(), 2u);
+//    EXPECT_TRUE(eventDeactivationMap2.find(3) != eventDeactivationMap2.end());
+//    EXPECT_TRUE(eventDeactivationMap2.find(4) != eventDeactivationMap2.end());
+//    EXPECT_EQ(eventDeactivationMap[3].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap[4].size(), 1u);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    std::unique_ptr<LogEvent> event;
+//
+//    event = CreateAppCrashEvent(111, bucketStartTimeNs + 5);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+//    event = CreateMoveToForegroundEvent(1111, bucketStartTimeNs + 5);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 5);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    EXPECT_EQ(broadcastCount, 0);
+//
+//    // Activated by battery save mode.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 1);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, 0);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // First processed event.
+//    event = CreateAppCrashEvent(222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//    event = CreateMoveToForegroundEvent(2222, bucketStartTimeNs + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 15);
+//
+//    // Activated by screen on event.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 20);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + 20);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // 2nd processed event.
+//    // The activation by screen_on event expires, but the one by battery save mode is still active.
+//    event = CreateAppCrashEvent(333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    event = CreateMoveToForegroundEvent(3333, bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 2 + 25);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//    // No new broadcast since the config should still be active.
+//    EXPECT_EQ(broadcastCount, 1);
+//
+//    // 3rd processed event.
+//    event = CreateAppCrashEvent(444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    event = CreateMoveToForegroundEvent(4444, bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 5 + 25);
+//
+//    // All activations expired.
+//    event = CreateAppCrashEvent(555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    event = CreateMoveToForegroundEvent(5555, bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 8);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 2);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + 20);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // Re-activate metric via screen on.
+//    event = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + 10);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // 4th processed event.
+//    event = CreateAppCrashEvent(666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    event = CreateMoveToForegroundEvent(6666, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 3);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // 5th processed event.
+//    event = CreateAppCrashEvent(777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//    event = CreateMoveToForegroundEvent(7777, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 40);
+//
+//    // Cancel battery saver mode and screen on activation.
+//    event = CreateScreenBrightnessChangedEvent(64, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 60);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    // New broadcast since the config is no longer active.
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // Screen-on activation expired.
+//    event = CreateAppCrashEvent(888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    event = CreateMoveToForegroundEvent(8888, bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 13);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 4);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 11 + 15);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    event = CreateAppCrashEvent(999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//    event = CreateMoveToForegroundEvent(9999, bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 14 + 1);
+//
+//    // Re-enable battery saver mode activation.
+//    event = CreateBatterySaverOnEvent(bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    processor.OnLogEvent(event.get(), bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_TRUE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 5);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 1);
+//    EXPECT_EQ(activeConfigsBroadcast[0], cfgId);
+//    EXPECT_TRUE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_TRUE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    // Cancel battery saver mode and screen on activation.
+//    event = CreateScreenBrightnessChangedEvent(140, bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    processor.OnLogEvent(event.get(),bucketStartTimeNs + NS_PER_SEC * 60 * 16);
+//    EXPECT_FALSE(metricsManager->isActive());
+//    EXPECT_EQ(broadcastCount, 6);
+//    EXPECT_EQ(activeConfigsBroadcast.size(), 0);
+//    EXPECT_FALSE(metricProducer->mIsActive);
+//    EXPECT_EQ(eventActivationMap[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap[3][0], eventActivationMap[0]);
+//    EXPECT_EQ(eventDeactivationMap[4][0], eventActivationMap[2]);
+//    EXPECT_FALSE(metricProducer2->mIsActive);
+//    EXPECT_EQ(eventActivationMap2[0]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[0]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 15);
+//    EXPECT_EQ(eventActivationMap2[0]->ttl_ns, 60 * 6 * NS_PER_SEC);
+//    EXPECT_EQ(eventActivationMap2[2]->state, ActivationState::kNotActive);
+//    EXPECT_EQ(eventActivationMap2[2]->start_ns, bucketStartTimeNs + NS_PER_SEC * 60 * 10 + 10);
+//    EXPECT_EQ(eventActivationMap2[2]->ttl_ns, 60 * 2 * NS_PER_SEC);
+//    EXPECT_EQ(eventDeactivationMap2[3][0], eventActivationMap2[0]);
+//    EXPECT_EQ(eventDeactivationMap2[4][0], eventActivationMap2[2]);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor.onDumpReport(cfgKey, bucketStartTimeNs + NS_PER_SEC * 60 * 15 + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(2, reports.reports(0).metrics_size());
+//    EXPECT_EQ(5, reports.reports(0).metrics(0).count_metrics().data_size());
+//    EXPECT_EQ(5, reports.reports(0).metrics(1).count_metrics().data_size());
+//
+//    StatsLogReport::CountMetricDataWrapper countMetrics;
+//
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).count_metrics(), &countMetrics);
+//    EXPECT_EQ(5, countMetrics.data_size());
+//
+//    auto data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(4);
+//    EXPECT_EQ(android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//
+//   countMetrics.clear_data();
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(1).count_metrics(), &countMetrics);
+//    EXPECT_EQ(5, countMetrics.data_size());
+//
+//    data = countMetrics.data(0);
+//    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(2222, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(1);
+//    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(3333, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(2);
+//    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(4444, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    // Partial bucket as metric is deactivated.
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 8,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(3);
+//    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(6666, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//
+//    data = countMetrics.data(4);
+//    EXPECT_EQ(android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* uid field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_EQ(7777, data.dimensions_in_what().value_tuple().dimensions_value(0).value_int());
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(1, data.bucket_info(0).count());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(bucketStartTimeNs + NS_PER_SEC * 60 * 11,
+//              data.bucket_info(0).end_bucket_elapsed_nanos());
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
index 78fb391..7d93fcc 100644
--- a/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/MetricConditionLink_e2e_test.cpp
@@ -97,249 +97,250 @@
 }
 }  // namespace
 
-// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
-// we should use the real API which will clear the data after dump data is called.
-TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
-    auto config = CreateStatsdConfig();
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    int appUid = 123;
-    auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
-    auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
-    auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
-
-    auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
-    auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
-    auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
-
-    auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
-    auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
-
-    auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
-    auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
-
-    auto screenTurnedOnEvent =
-        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                      bucketStartTimeNs + 2);
-    auto screenTurnedOffEvent =
-        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                      bucketStartTimeNs + 200);
-    auto screenTurnedOnEvent2 =
-        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                      bucketStartTimeNs + 2 * bucketSizeNs - 100);
-
-    std::vector<AttributionNodeInternal> attributions = {
-            CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
-    auto syncOnEvent1 =
-        CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
-    auto syncOffEvent1 =
-        CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
-    auto syncOnEvent2 =
-        CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
-
-    auto moveToBackgroundEvent1 =
-        CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
-    auto moveToForegroundEvent1 =
-        CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
-
-    auto moveToBackgroundEvent2 =
-        CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
-    auto moveToForegroundEvent2 =
-        CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
-
-    /*
-                    bucket #1                               bucket #2
-
-
-       |      |   |  |                      |   |          |        |   |   |     (crashEvents)
-    |-------------------------------------|-----------------------------------|---------
-
-             |                                           |                        (MoveToBkground)
-
-                                             |                               |    (MoveToForeground)
-
-                |                                                 |                (SyncIsOn)
-                                                  |                                (SyncIsOff)
-          |                                                               |        (ScreenIsOn)
-                   |                                                               (ScreenIsOff)
-    */
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(std::move(crashEvent1));
-    events.push_back(std::move(crashEvent2));
-    events.push_back(std::move(crashEvent3));
-    events.push_back(std::move(crashEvent4));
-    events.push_back(std::move(crashEvent5));
-    events.push_back(std::move(crashEvent6));
-    events.push_back(std::move(crashEvent7));
-    events.push_back(std::move(crashEvent8));
-    events.push_back(std::move(crashEvent9));
-    events.push_back(std::move(crashEvent10));
-    events.push_back(std::move(screenTurnedOnEvent));
-    events.push_back(std::move(screenTurnedOffEvent));
-    events.push_back(std::move(screenTurnedOnEvent2));
-    events.push_back(std::move(syncOnEvent1));
-    events.push_back(std::move(syncOffEvent1));
-    events.push_back(std::move(syncOnEvent2));
-    events.push_back(std::move(moveToBackgroundEvent1));
-    events.push_back(std::move(moveToForegroundEvent1));
-    events.push_back(std::move(moveToBackgroundEvent2));
-    events.push_back(std::move(moveToForegroundEvent2));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    // Validate dimension value.
-    EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
-    // Uid field.
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
-}
-
-TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
-    auto config = CreateStatsdConfig();
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(
-            bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-
-    int appUid = 123;
-    auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
-    auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
-    auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
-
-    auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
-    auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
-    auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
-
-    auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
-    auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
-
-    auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
-    auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
-
-    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
-    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
-    auto screenTurnedOnEvent2 =
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + 2 * bucketSizeNs - 100);
-
-    std::vector<AttributionNodeInternal> attributions = {
-            CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
-    auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
-    auto syncOffEvent1 =
-            CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
-    auto syncOnEvent2 =
-            CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
-
-    auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
-    auto moveToForegroundEvent1 =
-            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
-
-    auto moveToBackgroundEvent2 =
-            CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
-    auto moveToForegroundEvent2 =
-            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
-
-    /*
-                    bucket #1                               bucket #2
-
-
-       |      |   |  |                      |   |          |        |   |   |     (crashEvents)
-    |-------------------------------------|-----------------------------------|---------
-
-             |                                           |                        (MoveToBkground)
-
-                                             |                               |    (MoveToForeground)
-
-                |                                                 |                (SyncIsOn)
-                                                  |                                (SyncIsOff)
-          |                                                               |        (ScreenIsOn)
-                   |                                                               (ScreenIsOff)
-    */
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(std::move(crashEvent1));
-    events.push_back(std::move(crashEvent2));
-    events.push_back(std::move(crashEvent3));
-    events.push_back(std::move(crashEvent4));
-    events.push_back(std::move(crashEvent5));
-    events.push_back(std::move(crashEvent6));
-    events.push_back(std::move(crashEvent7));
-    events.push_back(std::move(crashEvent8));
-    events.push_back(std::move(crashEvent9));
-    events.push_back(std::move(crashEvent10));
-    events.push_back(std::move(screenTurnedOnEvent));
-    events.push_back(std::move(screenTurnedOffEvent));
-    events.push_back(std::move(screenTurnedOnEvent2));
-    events.push_back(std::move(syncOnEvent1));
-    events.push_back(std::move(syncOffEvent1));
-    events.push_back(std::move(syncOnEvent2));
-    events.push_back(std::move(moveToBackgroundEvent1));
-    events.push_back(std::move(moveToForegroundEvent1));
-    events.push_back(std::move(moveToBackgroundEvent2));
-    events.push_back(std::move(moveToForegroundEvent2));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
-    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
-    // Validate dimension value.
-    EXPECT_EQ(data.dimensions_in_what().field(),
-              android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
-    // Uid field.
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
-    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//// If we want to test multiple dump data, we must do it in separate tests, because in the e2e tests,
+//// we should use the real API which will clear the data after dump data is called.
+//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks1) {
+//    auto config = CreateStatsdConfig();
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//    int appUid = 123;
+//    auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
+//    auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
+//    auto crashEvent3= CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
+//
+//    auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
+//    auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
+//    auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
+//
+//    auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
+//    auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
+//
+//    auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
+//    auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
+//
+//    auto screenTurnedOnEvent =
+//        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                      bucketStartTimeNs + 2);
+//    auto screenTurnedOffEvent =
+//        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                      bucketStartTimeNs + 200);
+//    auto screenTurnedOnEvent2 =
+//        CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                      bucketStartTimeNs + 2 * bucketSizeNs - 100);
+//
+//    std::vector<AttributionNodeInternal> attributions = {
+//            CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
+//    auto syncOnEvent1 =
+//        CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
+//    auto syncOffEvent1 =
+//        CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
+//    auto syncOnEvent2 =
+//        CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
+//
+//    auto moveToBackgroundEvent1 =
+//        CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
+//    auto moveToForegroundEvent1 =
+//        CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
+//
+//    auto moveToBackgroundEvent2 =
+//        CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
+//    auto moveToForegroundEvent2 =
+//        CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
+//
+//    /*
+//                    bucket #1                               bucket #2
+//
+//
+//       |      |   |  |                      |   |          |        |   |   |     (crashEvents)
+//    |-------------------------------------|-----------------------------------|---------
+//
+//             |                                           |                        (MoveToBkground)
+//
+//                                             |                               |    (MoveToForeground)
+//
+//                |                                                 |                (SyncIsOn)
+//                                                  |                                (SyncIsOff)
+//          |                                                               |        (ScreenIsOn)
+//                   |                                                               (ScreenIsOff)
+//    */
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(std::move(crashEvent1));
+//    events.push_back(std::move(crashEvent2));
+//    events.push_back(std::move(crashEvent3));
+//    events.push_back(std::move(crashEvent4));
+//    events.push_back(std::move(crashEvent5));
+//    events.push_back(std::move(crashEvent6));
+//    events.push_back(std::move(crashEvent7));
+//    events.push_back(std::move(crashEvent8));
+//    events.push_back(std::move(crashEvent9));
+//    events.push_back(std::move(crashEvent10));
+//    events.push_back(std::move(screenTurnedOnEvent));
+//    events.push_back(std::move(screenTurnedOffEvent));
+//    events.push_back(std::move(screenTurnedOnEvent2));
+//    events.push_back(std::move(syncOnEvent1));
+//    events.push_back(std::move(syncOffEvent1));
+//    events.push_back(std::move(syncOnEvent2));
+//    events.push_back(std::move(moveToBackgroundEvent1));
+//    events.push_back(std::move(moveToForegroundEvent1));
+//    events.push_back(std::move(moveToBackgroundEvent2));
+//    events.push_back(std::move(moveToForegroundEvent2));
+//
+//    sortLogEventsByTimestamp(&events);
+//
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    // Validate dimension value.
+//    EXPECT_EQ(data.dimensions_in_what().field(), android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+//    // Uid field.
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
+//}
+//
+//TEST(MetricConditionLinkE2eTest, TestMultiplePredicatesAndLinks2) {
+//    auto config = CreateStatsdConfig();
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.count_metric(0).bucket()) * 1000000LL;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(
+//            bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//
+//    int appUid = 123;
+//    auto crashEvent1 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 1);
+//    auto crashEvent2 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 201);
+//    auto crashEvent3 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 101);
+//
+//    auto crashEvent4 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 51);
+//    auto crashEvent5 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 299);
+//    auto crashEvent6 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 2001);
+//
+//    auto crashEvent7 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 16);
+//    auto crashEvent8 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 249);
+//
+//    auto crashEvent9 = CreateAppCrashEvent(appUid, bucketStartTimeNs + bucketSizeNs + 351);
+//    auto crashEvent10 = CreateAppCrashEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 2);
+//
+//    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 2);
+//    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+//    auto screenTurnedOnEvent2 =
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + 2 * bucketSizeNs - 100);
+//
+//    std::vector<AttributionNodeInternal> attributions = {
+//            CreateAttribution(appUid, "App1"), CreateAttribution(appUid + 1, "GMSCoreModule1")};
+//    auto syncOnEvent1 = CreateSyncStartEvent(attributions, "ReadEmail", bucketStartTimeNs + 50);
+//    auto syncOffEvent1 =
+//            CreateSyncEndEvent(attributions, "ReadEmail", bucketStartTimeNs + bucketSizeNs + 300);
+//    auto syncOnEvent2 =
+//            CreateSyncStartEvent(attributions, "ReadDoc", bucketStartTimeNs + bucketSizeNs + 2000);
+//
+//    auto moveToBackgroundEvent1 = CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + 15);
+//    auto moveToForegroundEvent1 =
+//            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 250);
+//
+//    auto moveToBackgroundEvent2 =
+//            CreateMoveToBackgroundEvent(appUid, bucketStartTimeNs + bucketSizeNs + 350);
+//    auto moveToForegroundEvent2 =
+//            CreateMoveToForegroundEvent(appUid, bucketStartTimeNs + 2 * bucketSizeNs - 1);
+//
+//    /*
+//                    bucket #1                               bucket #2
+//
+//
+//       |      |   |  |                      |   |          |        |   |   |     (crashEvents)
+//    |-------------------------------------|-----------------------------------|---------
+//
+//             |                                           |                        (MoveToBkground)
+//
+//                                             |                               |    (MoveToForeground)
+//
+//                |                                                 |                (SyncIsOn)
+//                                                  |                                (SyncIsOff)
+//          |                                                               |        (ScreenIsOn)
+//                   |                                                               (ScreenIsOff)
+//    */
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(std::move(crashEvent1));
+//    events.push_back(std::move(crashEvent2));
+//    events.push_back(std::move(crashEvent3));
+//    events.push_back(std::move(crashEvent4));
+//    events.push_back(std::move(crashEvent5));
+//    events.push_back(std::move(crashEvent6));
+//    events.push_back(std::move(crashEvent7));
+//    events.push_back(std::move(crashEvent8));
+//    events.push_back(std::move(crashEvent9));
+//    events.push_back(std::move(crashEvent10));
+//    events.push_back(std::move(screenTurnedOnEvent));
+//    events.push_back(std::move(screenTurnedOffEvent));
+//    events.push_back(std::move(screenTurnedOnEvent2));
+//    events.push_back(std::move(syncOnEvent1));
+//    events.push_back(std::move(syncOffEvent1));
+//    events.push_back(std::move(syncOnEvent2));
+//    events.push_back(std::move(moveToBackgroundEvent1));
+//    events.push_back(std::move(moveToForegroundEvent1));
+//    events.push_back(std::move(moveToBackgroundEvent2));
+//    events.push_back(std::move(moveToForegroundEvent2));
+//
+//    sortLogEventsByTimestamp(&events);
+//
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info_size(), 2);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(0).count(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).count_metrics().data(0).bucket_info(1).count(), 3);
+//    auto data = reports.reports(0).metrics(0).count_metrics().data(0);
+//    // Validate dimension value.
+//    EXPECT_EQ(data.dimensions_in_what().field(),
+//              android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED);
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value_size(), 1);
+//    // Uid field.
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).field(), 1);
+//    EXPECT_EQ(data.dimensions_in_what().value_tuple().dimensions_value(0).value_int(), appUid);
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
index 1eecbe5..9ec831b 100644
--- a/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/PartialBucket_e2e_test.cpp
@@ -113,95 +113,96 @@
 }
 }  // anonymous namespace
 
-TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
-    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
-    SendConfig(service, MakeConfig());
-    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
-                                             // initialized with.
-
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
-
-    ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
-    // Expect no metrics since the bucket has not finished yet.
-    EXPECT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
-    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
-    SendConfig(service, MakeConfig());
-    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
-                                             // initialized with.
-
-    // Force the uidmap to update at timestamp 2.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    // This is a new installation, so there shouldn't be a split (should be same as the without
-    // split case).
-    service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
-                               String16(""));
-    // Goes into the second bucket.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
-    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
-    EXPECT_EQ(1, report.metrics_size());
-    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
-    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
-    SendConfig(service, MakeConfig());
-    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
-                                             // initialized with.
-    service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
-                                {String16("")});
-
-    // Force the uidmap to update at timestamp 2.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
-                               String16(""));
-    // Goes into the second bucket.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
-    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
-    backfillStartEndTimestamp(&report);
-
-    ASSERT_EQ(1, report.metrics_size());
-    ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
-    ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
-    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
-                    has_start_bucket_elapsed_nanos());
-    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
-                    has_end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
-}
-
-TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
-    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
-    SendConfig(service, MakeConfig());
-    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
-                                             // initialized with.
-    service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
-                                {String16("")});
-
-    // Force the uidmap to update at timestamp 2.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
-    service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
-    // Goes into the second bucket.
-    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
-
-    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
-    backfillStartEndTimestamp(&report);
-
-    ASSERT_EQ(1, report.metrics_size());
-    ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
-    ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
-    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
-                    has_start_bucket_elapsed_nanos());
-    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
-                    has_end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(PartialBucketE2eTest, TestCountMetricWithoutSplit) {
+//    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+//    SendConfig(service, MakeConfig());
+//    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
+//                                             // initialized with.
+//
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 2).get());
+//
+//    ConfigMetricsReport report = GetReports(service->mProcessor, start + 3);
+//    // Expect no metrics since the bucket has not finished yet.
+//    EXPECT_EQ(1, report.metrics_size());
+//    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricNoSplitOnNewApp) {
+//    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+//    SendConfig(service, MakeConfig());
+//    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
+//                                             // initialized with.
+//
+//    // Force the uidmap to update at timestamp 2.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+//    // This is a new installation, so there shouldn't be a split (should be same as the without
+//    // split case).
+//    service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+//                               String16(""));
+//    // Goes into the second bucket.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+//    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+//    EXPECT_EQ(1, report.metrics_size());
+//    EXPECT_EQ(0, report.metrics(0).count_metrics().data_size());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricSplitOnUpgrade) {
+//    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+//    SendConfig(service, MakeConfig());
+//    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
+//                                             // initialized with.
+//    service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+//                                {String16("")});
+//
+//    // Force the uidmap to update at timestamp 2.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+//    service->mUidMap->updateApp(start + 2, String16(kApp1.c_str()), 1, 2, String16("v2"),
+//                               String16(""));
+//    // Goes into the second bucket.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+//    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+//    backfillStartEndTimestamp(&report);
+//
+//    ASSERT_EQ(1, report.metrics_size());
+//    ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
+//    ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
+//    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+//                    has_start_bucket_elapsed_nanos());
+//    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+//                    has_end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+//}
+//
+//TEST(PartialBucketE2eTest, TestCountMetricSplitOnRemoval) {
+//    shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
+//    SendConfig(service, MakeConfig());
+//    int64_t start = getElapsedRealtimeNs();  // This is the start-time the metrics producers are
+//                                             // initialized with.
+//    service->mUidMap->updateMap(start, {1}, {1}, {String16("v1")}, {String16(kApp1.c_str())},
+//                                {String16("")});
+//
+//    // Force the uidmap to update at timestamp 2.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 1).get());
+//    service->mUidMap->removeApp(start + 2, String16(kApp1.c_str()), 1);
+//    // Goes into the second bucket.
+//    service->mProcessor->OnLogEvent(CreateAppCrashEvent(100, start + 3).get());
+//
+//    ConfigMetricsReport report = GetReports(service->mProcessor, start + 4);
+//    backfillStartEndTimestamp(&report);
+//
+//    ASSERT_EQ(1, report.metrics_size());
+//    ASSERT_EQ(1, report.metrics(0).count_metrics().data_size());
+//    ASSERT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info_size());
+//    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+//                    has_start_bucket_elapsed_nanos());
+//    EXPECT_TRUE(report.metrics(0).count_metrics().data(0).bucket_info(0).
+//                    has_end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, report.metrics(0).count_metrics().data(0).bucket_info(0).count());
+//}
 
 TEST(PartialBucketE2eTest, TestValueMetricWithoutMinPartialBucket) {
     shared_ptr<StatsService> service = SharedRefBase::make<StatsService>(nullptr, nullptr);
diff --git a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
index 9d39f9c..99dbaf1 100644
--- a/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/ValueMetric_pull_e2e_test.cpp
@@ -64,316 +64,317 @@
 
 }  // namespace
 
-TEST(ValueMetricE2eTest, TestPulledEvents) {
-    auto config = CreateStatsdConfig();
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             android::util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-
-    // When creating the config, the value metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& expectedPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
-    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                        configAddedTimeNs + 55);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + 65);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + 75);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    // Pulling alarm arrives on time and reset the sequential pulling alarm.
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
-    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + 2 * bucketSizeNs + 15);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + 4 * bucketSizeNs + 11);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::ValueMetricDataWrapper valueMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 1);
-
-    auto data = valueMetrics.data(0);
-    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    // We have 4 buckets, the first one was incomplete since the condition was unknown.
-    EXPECT_EQ(4, data.bucket_info_size());
-
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(0).values_size());
-
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(1).values_size());
-
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(2).values_size());
-
-    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(3).values_size());
-}
-
-TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
-    auto config = CreateStatsdConfig();
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    // 10 mins == 2 bucket durations.
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             android::util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-
-    // When creating the config, the value metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& expectedPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
-    // Screen off/on/off events.
-    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                        configAddedTimeNs + 55);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + 65);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + 75);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
-    // future, data will be skipped.
-    processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
-
-    // This screen state change will start a new bucket.
-    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
-                                                       configAddedTimeNs + 4 * bucketSizeNs + 65);
-    processor->OnLogEvent(screenOnEvent.get());
-
-    // The alarm is delayed but we already created a bucket thanks to the screen state condition.
-    // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
-    processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
-
-    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
-                                                   configAddedTimeNs + 6 * bucketSizeNs + 31);
-    processor->OnLogEvent(screenOffEvent.get());
-
-    processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::ValueMetricDataWrapper valueMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 1);
-
-    auto data = valueMetrics.data(0);
-    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    EXPECT_EQ(3, data.bucket_info_size());
-
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(0).values_size());
-
-    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(1).values_size());
-
-    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, data.bucket_info(2).values_size());
-}
-
-TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
-    auto config = CreateStatsdConfig(false);
-    int64_t baseTimeNs = getElapsedRealtimeNs();
-    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
-    int64_t bucketSizeNs =
-        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
-
-    auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
-    *config.add_atom_matcher() = batterySaverStartMatcher;
-    const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
-    auto metric_activation = config.add_metric_activation();
-    metric_activation->set_metric_id(metricId);
-    metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
-    auto event_activation = metric_activation->add_event_activation();
-    event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
-    event_activation->set_ttl_seconds(ttlNs / 1000000000);
-
-    ConfigKey cfgKey;
-    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
-                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
-                                             android::util::SUBSYSTEM_SLEEP_STATE);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    processor->mPullerManager->ForceClearPullerCache();
-
-    int startBucketNum = processor->mMetricsManagers.begin()->second->
-            mAllMetricProducers[0]->getCurrentBucketNum();
-    EXPECT_GT(startBucketNum, (int64_t)0);
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // When creating the config, the value metric producer should register the alarm at the
-    // end of the current bucket.
-    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
-    EXPECT_EQ(bucketSizeNs,
-              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
-    int64_t& expectedPullTimeNs =
-            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
-
-    // Pulling alarm arrives on time and reset the sequential pulling alarm.
-    processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    // Activate the metric. A pull occurs here
-    const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
-    auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
-    processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
-
-    // Create random event to deactivate metric.
-    auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
-    processor->OnLogEvent(deactivationEvent.get());
-    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 3);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
-
-    processor->informPullAlarmFired(expectedPullTimeNs + 4);
-    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
-
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(1, reports.reports_size());
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    StatsLogReport::ValueMetricDataWrapper valueMetrics;
-    sortMetricDataByDimensionsValue(
-            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
-    EXPECT_GT((int)valueMetrics.data_size(), 0);
-
-    auto data = valueMetrics.data(0);
-    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
-    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
-    EXPECT_EQ(1 /* subsystem name field */,
-              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
-    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
-    // We have 2 full buckets, the two surrounding the activation are dropped.
-    EXPECT_EQ(2, data.bucket_info_size());
-
-    auto bucketInfo = data.bucket_info(0);
-    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, bucketInfo.values_size());
-
-    bucketInfo = data.bucket_info(1);
-    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
-    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
-    EXPECT_EQ(1, bucketInfo.values_size());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ValueMetricE2eTest, TestPulledEvents) {
+//    auto config = CreateStatsdConfig();
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             android::util::SUBSYSTEM_SLEEP_STATE);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//
+//    // When creating the config, the value metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& expectedPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+//    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                        configAddedTimeNs + 55);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + 65);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + 75);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    // Pulling alarm arrives on time and reset the sequential pulling alarm.
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+//    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + 2 * bucketSizeNs + 15);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + 4 * bucketSizeNs + 11);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::ValueMetricDataWrapper valueMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+//    EXPECT_GT((int)valueMetrics.data_size(), 1);
+//
+//    auto data = valueMetrics.data(0);
+//    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    // We have 4 buckets, the first one was incomplete since the condition was unknown.
+//    EXPECT_EQ(4, data.bucket_info_size());
+//
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(0).values_size());
+//
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(1).values_size());
+//
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(2).values_size());
+//
+//    EXPECT_EQ(baseTimeNs + 7 * bucketSizeNs, data.bucket_info(3).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(3).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(3).values_size());
+//}
+//
+//TEST(ValueMetricE2eTest, TestPulledEvents_LateAlarm) {
+//    auto config = CreateStatsdConfig();
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    // 10 mins == 2 bucket durations.
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             android::util::SUBSYSTEM_SLEEP_STATE);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//
+//    // When creating the config, the value metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& expectedPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+//    // Screen off/on/off events.
+//    auto screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                        configAddedTimeNs + 55);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    auto screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + 65);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + 75);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    // Pulling alarm arrives late by 2 buckets and 1 ns. 2 buckets late is too far away in the
+//    // future, data will be skipped.
+//    processor->informPullAlarmFired(expectedPullTimeNs + 2 * bucketSizeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
+//
+//    // This screen state change will start a new bucket.
+//    screenOnEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_ON,
+//                                                       configAddedTimeNs + 4 * bucketSizeNs + 65);
+//    processor->OnLogEvent(screenOnEvent.get());
+//
+//    // The alarm is delayed but we already created a bucket thanks to the screen state condition.
+//    // This bucket does not have to be skipped since the alarm arrives in time for the next bucket.
+//    processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
+//
+//    screenOffEvent = CreateScreenStateChangedEvent(android::view::DISPLAY_STATE_OFF,
+//                                                   configAddedTimeNs + 6 * bucketSizeNs + 31);
+//    processor->OnLogEvent(screenOffEvent.get());
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + bucketSizeNs + 21);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 8 * bucketSizeNs, expectedPullTimeNs);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 9 * bucketSizeNs, expectedPullTimeNs);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 9 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::ValueMetricDataWrapper valueMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+//    EXPECT_GT((int)valueMetrics.data_size(), 1);
+//
+//    auto data = valueMetrics.data(0);
+//    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    EXPECT_EQ(3, data.bucket_info_size());
+//
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, data.bucket_info(0).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 6 * bucketSizeNs, data.bucket_info(0).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(0).values_size());
+//
+//    EXPECT_EQ(baseTimeNs + 8 * bucketSizeNs, data.bucket_info(1).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(1).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(1).values_size());
+//
+//    EXPECT_EQ(baseTimeNs + 9 * bucketSizeNs, data.bucket_info(2).start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 10 * bucketSizeNs, data.bucket_info(2).end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, data.bucket_info(2).values_size());
+//}
+//
+//TEST(ValueMetricE2eTest, TestPulledEvents_WithActivation) {
+//    auto config = CreateStatsdConfig(false);
+//    int64_t baseTimeNs = getElapsedRealtimeNs();
+//    int64_t configAddedTimeNs = 10 * 60 * NS_PER_SEC + baseTimeNs;
+//    int64_t bucketSizeNs =
+//        TimeUnitToBucketSizeInMillis(config.value_metric(0).bucket()) * 1000000;
+//
+//    auto batterySaverStartMatcher = CreateBatterySaverModeStartAtomMatcher();
+//    *config.add_atom_matcher() = batterySaverStartMatcher;
+//    const int64_t ttlNs = 2 * bucketSizeNs; // Two buckets.
+//    auto metric_activation = config.add_metric_activation();
+//    metric_activation->set_metric_id(metricId);
+//    metric_activation->set_activation_type(ACTIVATE_IMMEDIATELY);
+//    auto event_activation = metric_activation->add_event_activation();
+//    event_activation->set_atom_matcher_id(batterySaverStartMatcher.id());
+//    event_activation->set_ttl_seconds(ttlNs / 1000000000);
+//
+//    ConfigKey cfgKey;
+//    auto processor = CreateStatsLogProcessor(baseTimeNs, configAddedTimeNs, config, cfgKey,
+//                                             SharedRefBase::make<FakeSubsystemSleepCallback>(),
+//                                             android::util::SUBSYSTEM_SLEEP_STATE);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    processor->mPullerManager->ForceClearPullerCache();
+//
+//    int startBucketNum = processor->mMetricsManagers.begin()->second->
+//            mAllMetricProducers[0]->getCurrentBucketNum();
+//    EXPECT_GT(startBucketNum, (int64_t)0);
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // When creating the config, the value metric producer should register the alarm at the
+//    // end of the current bucket.
+//    EXPECT_EQ((size_t)1, processor->mPullerManager->mReceivers.size());
+//    EXPECT_EQ(bucketSizeNs,
+//              processor->mPullerManager->mReceivers.begin()->second.front().intervalNs);
+//    int64_t& expectedPullTimeNs =
+//            processor->mPullerManager->mReceivers.begin()->second.front().nextPullTimeNs;
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + bucketSizeNs, expectedPullTimeNs);
+//
+//    // Pulling alarm arrives on time and reset the sequential pulling alarm.
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1); // 15 mins + 1 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 2 * bucketSizeNs, expectedPullTimeNs);
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    // Activate the metric. A pull occurs here
+//    const int64_t activationNs = configAddedTimeNs + bucketSizeNs + (2 * 1000 * 1000); // 2 millis.
+//    auto batterySaverOnEvent = CreateBatterySaverOnEvent(activationNs);
+//    processor->OnLogEvent(batterySaverOnEvent.get()); // 15 mins + 2 ms.
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 1); // 20 mins + 1 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 3 * bucketSizeNs, expectedPullTimeNs);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 2); // 25 mins + 2 ns.
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 4 * bucketSizeNs, expectedPullTimeNs);
+//
+//    // Create random event to deactivate metric.
+//    auto deactivationEvent = CreateScreenBrightnessChangedEvent(50, activationNs + ttlNs + 1);
+//    processor->OnLogEvent(deactivationEvent.get());
+//    EXPECT_FALSE(processor->mMetricsManagers.begin()->second->mAllMetricProducers[0]->isActive());
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 3);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 5 * bucketSizeNs, expectedPullTimeNs);
+//
+//    processor->informPullAlarmFired(expectedPullTimeNs + 4);
+//    EXPECT_EQ(baseTimeNs + startBucketNum * bucketSizeNs + 6 * bucketSizeNs, expectedPullTimeNs);
+//
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, configAddedTimeNs + 7 * bucketSizeNs + 10, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(1, reports.reports_size());
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    StatsLogReport::ValueMetricDataWrapper valueMetrics;
+//    sortMetricDataByDimensionsValue(
+//            reports.reports(0).metrics(0).value_metrics(), &valueMetrics);
+//    EXPECT_GT((int)valueMetrics.data_size(), 0);
+//
+//    auto data = valueMetrics.data(0);
+//    EXPECT_EQ(android::util::SUBSYSTEM_SLEEP_STATE, data.dimensions_in_what().field());
+//    EXPECT_EQ(1, data.dimensions_in_what().value_tuple().dimensions_value_size());
+//    EXPECT_EQ(1 /* subsystem name field */,
+//              data.dimensions_in_what().value_tuple().dimensions_value(0).field());
+//    EXPECT_FALSE(data.dimensions_in_what().value_tuple().dimensions_value(0).value_str().empty());
+//    // We have 2 full buckets, the two surrounding the activation are dropped.
+//    EXPECT_EQ(2, data.bucket_info_size());
+//
+//    auto bucketInfo = data.bucket_info(0);
+//    EXPECT_EQ(baseTimeNs + 3 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, bucketInfo.values_size());
+//
+//    bucketInfo = data.bucket_info(1);
+//    EXPECT_EQ(baseTimeNs + 4 * bucketSizeNs, bucketInfo.start_bucket_elapsed_nanos());
+//    EXPECT_EQ(baseTimeNs + 5 * bucketSizeNs, bucketInfo.end_bucket_elapsed_nanos());
+//    EXPECT_EQ(1, bucketInfo.values_size());
+//}
 
 /**
  * Test initialization of a simple value metric that is sliced by a state.
diff --git a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
index e13bf14..21092e2 100644
--- a/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
+++ b/cmds/statsd/tests/e2e/WakelockDuration_e2e_test.cpp
@@ -69,282 +69,284 @@
                                                       CreateAttribution(222, "GMSCoreModule1"),
                                                       CreateAttribution(222, "GMSCoreModule2")};
 
-/*
-Events:
-Screen off is met from (200ns,1 min+500ns].
-Acquire event for wl1 from 2ns to 1min+2ns
-Acquire event for wl2 from 1min-10ns to 2min-15ns
-*/
-void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-
-    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
-    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
-    auto screenTurnedOnEvent2 =
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                          bucketStartTimeNs + bucketSizeNs + 500);
-
-    auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
-    auto releaseEvent1 =
-            CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
-    auto acquireEvent2 =
-            CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
-    auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
-                                                    bucketStartTimeNs + 2 * bucketSizeNs - 15);
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-
-    events.push_back(std::move(screenTurnedOnEvent));
-    events.push_back(std::move(screenTurnedOffEvent));
-    events.push_back(std::move(screenTurnedOnEvent2));
-    events.push_back(std::move(acquireEvent1));
-    events.push_back(std::move(acquireEvent2));
-    events.push_back(std::move(releaseEvent1));
-    events.push_back(std::move(releaseEvent2));
-
-    sortLogEventsByTimestamp(&events);
-
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+///*
+//Events:
+//Screen off is met from (200ns,1 min+500ns].
+//Acquire event for wl1 from 2ns to 1min+2ns
+//Acquire event for wl2 from 1min-10ns to 2min-15ns
+//*/
+//void FeedEvents(StatsdConfig config, sp<StatsLogProcessor> processor) {
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//
+//    auto screenTurnedOnEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 1);
+//    auto screenTurnedOffEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_OFF, bucketStartTimeNs + 200);
+//    auto screenTurnedOnEvent2 =
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                          bucketStartTimeNs + bucketSizeNs + 500);
+//
+//    auto acquireEvent1 = CreateAcquireWakelockEvent(attributions1, "wl1", bucketStartTimeNs + 2);
+//    auto releaseEvent1 =
+//            CreateReleaseWakelockEvent(attributions1, "wl1", bucketStartTimeNs + bucketSizeNs + 2);
+//    auto acquireEvent2 =
+//            CreateAcquireWakelockEvent(attributions2, "wl2", bucketStartTimeNs + bucketSizeNs - 10);
+//    auto releaseEvent2 = CreateReleaseWakelockEvent(attributions2, "wl2",
+//                                                    bucketStartTimeNs + 2 * bucketSizeNs - 15);
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//
+//    events.push_back(std::move(screenTurnedOnEvent));
+//    events.push_back(std::move(screenTurnedOffEvent));
+//    events.push_back(std::move(screenTurnedOnEvent2));
+//    events.push_back(std::move(acquireEvent1));
+//    events.push_back(std::move(acquireEvent2));
+//    events.push_back(std::move(releaseEvent1));
+//    events.push_back(std::move(releaseEvent2));
+//
+//    sortLogEventsByTimestamp(&events);
+//
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//}
 
 }  // namespace
 
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::SUM);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // Validate dimension value.
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, 111);
-    // Validate bucket info.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
-    data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // The wakelock holding interval starts from the screen off event and to the end of the 1st
-    // bucket.
-    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::SUM);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    // Dump the report after the end of 2nd bucket.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // Validate dimension value.
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, 111);
-    // Two output buckets.
-    // The wakelock holding interval in the 1st bucket starts from the screen off event and to
-    // the end of the 1st bucket.
-    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
-              bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
-    // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
-    // ends at the second screen on event.
-    EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
-}
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::SUM);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    vector<uint8_t> buffer;
-    ConfigMetricsReportList reports;
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
-    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
-                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
-    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
-                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
-    sortLogEventsByTimestamp(&events);
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, 111);
-    // The last wakelock holding spans 4 buckets.
-    EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
-    EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
-    EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
-    EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-
-    EXPECT_EQ(reports.reports_size(), 1);
-
-    // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
-    // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
-    // itself.
-    EXPECT_EQ(1, reports.reports(0).metrics_size());
-    EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    // Dump the report after the end of 2nd bucket. One dimension with one bucket.
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    // Validate dimension value.
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, 111);
-    // The max is acquire event for wl1 to screen off start.
-    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
-}
-
-TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
-    ConfigKey cfgKey;
-    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
-    uint64_t bucketStartTimeNs = 10000000000;
-    uint64_t bucketSizeNs =
-            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
-    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
-    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
-    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
-    FeedEvents(config, processor);
-    ConfigMetricsReportList reports;
-    vector<uint8_t> buffer;
-
-    std::vector<std::unique_ptr<LogEvent>> events;
-    events.push_back(
-            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
-    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
-                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
-    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
-                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
-    sortLogEventsByTimestamp(&events);
-    for (const auto& event : events) {
-        processor->OnLogEvent(event.get());
-    }
-
-    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
-                            ADB_DUMP, FAST, &buffer);
-    EXPECT_TRUE(buffer.size() > 0);
-    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
-    backfillDimensionPath(&reports);
-    backfillStringInReport(&reports);
-    backfillStartEndTimestamp(&reports);
-    EXPECT_EQ(reports.reports_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
-    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
-    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
-    ValidateAttributionUidDimension(data.dimensions_in_what(),
-                                    android::util::WAKELOCK_STATE_CHANGED, 111);
-    // The last wakelock holding spans 4 buckets.
-    EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
-    EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
-              bucketStartTimeNs + 5 * bucketSizeNs);
-    EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
-              bucketStartTimeNs + 6 * bucketSizeNs);
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration1) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::SUM);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    // Only 1 dimension output. The tag dimension in the predicate has been aggregated.
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // Validate dimension value.
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, 111);
+//    // Validate bucket info.
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+//    data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // The wakelock holding interval starts from the screen off event and to the end of the 1st
+//    // bucket.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs - 200);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration2) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::SUM);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//    // Dump the report after the end of 2nd bucket.
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // Validate dimension value.
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, 111);
+//    // Two output buckets.
+//    // The wakelock holding interval in the 1st bucket starts from the screen off event and to
+//    // the end of the 1st bucket.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(),
+//              bucketStartTimeNs + bucketSizeNs - (bucketStartTimeNs + 200));
+//    // The wakelock holding interval in the 2nd bucket starts at the beginning of the bucket and
+//    // ends at the second screen on event.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 500UL);
+//}
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForSumDuration3) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::SUM);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    vector<uint8_t> buffer;
+//    ConfigMetricsReportList reports;
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
+//    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+//                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+//                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
+//    sortLogEventsByTimestamp(&events);
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 6);
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, 111);
+//    // The last wakelock holding spans 4 buckets.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(2).duration_nanos(), bucketSizeNs - 100);
+//    EXPECT_EQ((unsigned long long)data.bucket_info(3).duration_nanos(), bucketSizeNs);
+//    EXPECT_EQ((unsigned long long)data.bucket_info(4).duration_nanos(), bucketSizeNs);
+//    EXPECT_EQ((unsigned long long)data.bucket_info(5).duration_nanos(), 100UL);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration1) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs - 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//
+//    EXPECT_EQ(reports.reports_size(), 1);
+//
+//    // When using ProtoOutputStream, if nothing written to a sub msg, it won't be treated as
+//    // one. It was previsouly 1 because we had a fake onDumpReport which calls add_metric() by
+//    // itself.
+//    EXPECT_EQ(1, reports.reports(0).metrics_size());
+//    EXPECT_EQ(0, reports.reports(0).metrics(0).duration_metrics().data_size());
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration2) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 2 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//    // Dump the report after the end of 2nd bucket. One dimension with one bucket.
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 1);
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    // Validate dimension value.
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, 111);
+//    // The max is acquire event for wl1 to screen off start.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(0).duration_nanos(), bucketSizeNs + 2 - 200);
+//}
+//
+//TEST(WakelockDurationE2eTest, TestAggregatedPredicateDimensionsForMaxDuration3) {
+//    ConfigKey cfgKey;
+//    auto config = CreateStatsdConfig(DurationMetric::MAX_SPARSE);
+//    uint64_t bucketStartTimeNs = 10000000000;
+//    uint64_t bucketSizeNs =
+//            TimeUnitToBucketSizeInMillis(config.duration_metric(0).bucket()) * 1000000LL;
+//    auto processor = CreateStatsLogProcessor(bucketStartTimeNs, bucketStartTimeNs, config, cfgKey);
+//    EXPECT_EQ(processor->mMetricsManagers.size(), 1u);
+//    EXPECT_TRUE(processor->mMetricsManagers.begin()->second->isConfigValid());
+//    FeedEvents(config, processor);
+//    ConfigMetricsReportList reports;
+//    vector<uint8_t> buffer;
+//
+//    std::vector<std::unique_ptr<LogEvent>> events;
+//    events.push_back(
+//            CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                          bucketStartTimeNs + 2 * bucketSizeNs + 90));
+//    events.push_back(CreateAcquireWakelockEvent(attributions1, "wl3",
+//                                                bucketStartTimeNs + 2 * bucketSizeNs + 100));
+//    events.push_back(CreateReleaseWakelockEvent(attributions1, "wl3",
+//                                                bucketStartTimeNs + 5 * bucketSizeNs + 100));
+//    sortLogEventsByTimestamp(&events);
+//    for (const auto& event : events) {
+//        processor->OnLogEvent(event.get());
+//    }
+//
+//    processor->onDumpReport(cfgKey, bucketStartTimeNs + 6 * bucketSizeNs + 1, false, true,
+//                            ADB_DUMP, FAST, &buffer);
+//    EXPECT_TRUE(buffer.size() > 0);
+//    EXPECT_TRUE(reports.ParseFromArray(&buffer[0], buffer.size()));
+//    backfillDimensionPath(&reports);
+//    backfillStringInReport(&reports);
+//    backfillStartEndTimestamp(&reports);
+//    EXPECT_EQ(reports.reports_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data_size(), 1);
+//    EXPECT_EQ(reports.reports(0).metrics(0).duration_metrics().data(0).bucket_info_size(), 2);
+//    auto data = reports.reports(0).metrics(0).duration_metrics().data(0);
+//    ValidateAttributionUidDimension(data.dimensions_in_what(),
+//                                    android::util::WAKELOCK_STATE_CHANGED, 111);
+//    // The last wakelock holding spans 4 buckets.
+//    EXPECT_EQ((unsigned long long)data.bucket_info(1).duration_nanos(), 3 * bucketSizeNs);
+//    EXPECT_EQ((unsigned long long)data.bucket_info(1).start_bucket_elapsed_nanos(),
+//              bucketStartTimeNs + 5 * bucketSizeNs);
+//    EXPECT_EQ((unsigned long long)data.bucket_info(1).end_bucket_elapsed_nanos(),
+//              bucketStartTimeNs + 6 * bucketSizeNs);
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/external/StatsPuller_test.cpp b/cmds/statsd/tests/external/StatsPuller_test.cpp
index f42356a..c0b4f43 100644
--- a/cmds/statsd/tests/external/StatsPuller_test.cpp
+++ b/cmds/statsd/tests/external/StatsPuller_test.cpp
@@ -57,12 +57,13 @@
 
 FakePuller puller;
 
-shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
-    event->write(value);
-    event->init();
-    return event;
-}
+// TODO(b/149590301): Update this helper to use new socket schema.
+//shared_ptr<LogEvent> createSimpleEvent(int64_t eventTimeNs, int64_t value) {
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(pullTagId, eventTimeNs);
+//    event->write(value);
+//    event->init();
+//    return event;
+//}
 
 class StatsPullerTest : public ::testing::Test {
 public:
@@ -79,148 +80,149 @@
 
 }  // Anonymous namespace.
 
-TEST_F(StatsPullerTest, PullSuccess) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = true;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
-    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
-    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
-    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
-    sleep_for(std::chrono::seconds(1));
-
-    pullData.clear();
-    pullData.push_back(createSimpleEvent(2222L, 44));
-
-    pullSuccess = true;
-
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
-    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
-    EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
-    EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
-}
-
-TEST_F(StatsPullerTest, PullFailAfterSuccess) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = true;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
-    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
-    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
-    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
-    sleep_for(std::chrono::seconds(1));
-
-    pullData.clear();
-    pullData.push_back(createSimpleEvent(2222L, 44));
-
-    pullSuccess = false;
-    dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-
-    pullSuccess = true;
-    dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-}
-
-// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
-TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-    pullSuccess = true;
-    // timeout is 0.5
-    pullDelayNs = (long)(0.8 * NS_PER_SEC);
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-
-    pullData.clear();
-    pullData.push_back(createSimpleEvent(2222L, 44));
-
-    pullSuccess = true;
-    dataHolder.clear();
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullFail) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = false;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullTakeTooLong) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = true;
-    pullDelayNs = NS_PER_SEC;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-}
-
-TEST_F(StatsPullerTest, PullTooFast) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = true;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
-    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
-    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
-    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-
-    pullData.clear();
-    pullData.push_back(createSimpleEvent(2222L, 44));
-
-    pullSuccess = true;
-
-    dataHolder.clear();
-    EXPECT_TRUE(puller.Pull(&dataHolder));
-    EXPECT_EQ(1, dataHolder.size());
-    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
-    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
-    EXPECT_EQ(1, dataHolder[0]->size());
-    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
-}
-
-TEST_F(StatsPullerTest, PullFailsAndTooFast) {
-    pullData.push_back(createSimpleEvent(1111L, 33));
-
-    pullSuccess = false;
-
-    vector<std::shared_ptr<LogEvent>> dataHolder;
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-
-    pullData.clear();
-    pullData.push_back(createSimpleEvent(2222L, 44));
-
-    pullSuccess = true;
-
-    EXPECT_FALSE(puller.Pull(&dataHolder));
-    EXPECT_EQ(0, dataHolder.size());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST_F(StatsPullerTest, PullSuccess) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = true;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_TRUE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(1, dataHolder.size());
+//    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+//    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+//    EXPECT_EQ(1, dataHolder[0]->size());
+//    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+//    sleep_for(std::chrono::seconds(1));
+//
+//    pullData.clear();
+//    pullData.push_back(createSimpleEvent(2222L, 44));
+//
+//    pullSuccess = true;
+//
+//    EXPECT_TRUE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(1, dataHolder.size());
+//    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+//    EXPECT_EQ(2222L, dataHolder[0]->GetElapsedTimestampNs());
+//    EXPECT_EQ(1, dataHolder[0]->size());
+//    EXPECT_EQ(44, dataHolder[0]->getValues()[0].mValue.int_value);
+//}
+//
+//TEST_F(StatsPullerTest, PullFailAfterSuccess) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = true;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_TRUE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(1, dataHolder.size());
+//    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+//    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+//    EXPECT_EQ(1, dataHolder[0]->size());
+//    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+//    sleep_for(std::chrono::seconds(1));
+//
+//    pullData.clear();
+//    pullData.push_back(createSimpleEvent(2222L, 44));
+//
+//    pullSuccess = false;
+//    dataHolder.clear();
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//
+//    pullSuccess = true;
+//    dataHolder.clear();
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//// Test pull takes longer than timeout, 2nd pull happens shorter than cooldown
+//TEST_F(StatsPullerTest, PullTakeTooLongAndPullFast) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//    pullSuccess = true;
+//    // timeout is 0.5
+//    pullDelayNs = (long)(0.8 * NS_PER_SEC);
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//
+//    pullData.clear();
+//    pullData.push_back(createSimpleEvent(2222L, 44));
+//
+//    pullSuccess = true;
+//    dataHolder.clear();
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullFail) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = false;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullTakeTooLong) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = true;
+//    pullDelayNs = NS_PER_SEC;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//}
+//
+//TEST_F(StatsPullerTest, PullTooFast) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = true;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_TRUE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(1, dataHolder.size());
+//    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+//    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+//    EXPECT_EQ(1, dataHolder[0]->size());
+//    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//
+//    pullData.clear();
+//    pullData.push_back(createSimpleEvent(2222L, 44));
+//
+//    pullSuccess = true;
+//
+//    dataHolder.clear();
+//    EXPECT_TRUE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(1, dataHolder.size());
+//    EXPECT_EQ(pullTagId, dataHolder[0]->GetTagId());
+//    EXPECT_EQ(1111L, dataHolder[0]->GetElapsedTimestampNs());
+//    EXPECT_EQ(1, dataHolder[0]->size());
+//    EXPECT_EQ(33, dataHolder[0]->getValues()[0].mValue.int_value);
+//}
+//
+//TEST_F(StatsPullerTest, PullFailsAndTooFast) {
+//    pullData.push_back(createSimpleEvent(1111L, 33));
+//
+//    pullSuccess = false;
+//
+//    vector<std::shared_ptr<LogEvent>> dataHolder;
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//
+//    pullData.clear();
+//    pullData.push_back(createSimpleEvent(2222L, 44));
+//
+//    pullSuccess = true;
+//
+//    EXPECT_FALSE(puller.Pull(&dataHolder));
+//    EXPECT_EQ(0, dataHolder.size());
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/external/puller_util_test.cpp b/cmds/statsd/tests/external/puller_util_test.cpp
index c25e657..81590a2 100644
--- a/cmds/statsd/tests/external/puller_util_test.cpp
+++ b/cmds/statsd/tests/external/puller_util_test.cpp
@@ -60,209 +60,210 @@
 }
 }  // anonymous namespace
 
-TEST(puller_util, MergeNoDimension) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  // 30->22->31
-  event->write(isolatedUid);
-  event->write(hostNonAdditiveData);
-  event->write(isolatedAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 20->22->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(hostNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
-      .WillRepeatedly(Return(hostUid));
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
-      .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
-  vector<vector<int>> actual;
-  extractIntoVector(inputData, actual);
-  vector<int> expectedV1 = {20, 22, 52};
-  EXPECT_EQ(1, (int)actual.size());
-  EXPECT_THAT(actual, Contains(expectedV1));
-}
-
-TEST(puller_util, MergeWithDimension) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  // 30->32->31
-  event->write(isolatedUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(isolatedAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 20->32->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 20->22->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(hostNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
-      .WillRepeatedly(Return(hostUid));
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
-      .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
-  vector<vector<int>> actual;
-  extractIntoVector(inputData, actual);
-  vector<int> expectedV1 = {20, 22, 21};
-  vector<int> expectedV2 = {20, 32, 52};
-  EXPECT_EQ(2, (int)actual.size());
-  EXPECT_THAT(actual, Contains(expectedV1));
-  EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, NoMergeHostUidOnly) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  // 20->32->31
-  event->write(hostUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(isolatedAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 20->22->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(hostNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
-      .WillRepeatedly(Return(hostUid));
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
-      .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
-  // 20->32->31
-  // 20->22->21
-  vector<vector<int>> actual;
-  extractIntoVector(inputData, actual);
-  vector<int> expectedV1 = {20, 32, 31};
-  vector<int> expectedV2 = {20, 22, 21};
-  EXPECT_EQ(2, (int)actual.size());
-  EXPECT_THAT(actual, Contains(expectedV1));
-  EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, IsolatedUidOnly) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  // 30->32->31
-  event->write(hostUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(isolatedAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 30->22->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(hostNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
-      .WillRepeatedly(Return(hostUid));
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
-      .WillRepeatedly(ReturnArg<0>());
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
-  // 20->32->31
-  // 20->22->21
-  vector<vector<int>> actual;
-  extractIntoVector(inputData, actual);
-  vector<int> expectedV1 = {20, 32, 31};
-  vector<int> expectedV2 = {20, 22, 21};
-  EXPECT_EQ(2, (int)actual.size());
-  EXPECT_THAT(actual, Contains(expectedV1));
-  EXPECT_THAT(actual, Contains(expectedV2));
-}
-
-TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  // 30->32->31
-  event->write(isolatedUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(isolatedAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 31->32->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(isolatedUid + 1);
-  event->write(isolatedNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  // 20->32->21
-  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
-  event->write(hostUid);
-  event->write(isolatedNonAdditiveData);
-  event->write(hostAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
-
-  vector<vector<int>> actual;
-  extractIntoVector(inputData, actual);
-  vector<int> expectedV1 = {20, 32, 73};
-  EXPECT_EQ(1, (int)actual.size());
-  EXPECT_THAT(actual, Contains(expectedV1));
-}
-
-TEST(puller_util, NoNeedToMerge) {
-  vector<shared_ptr<LogEvent>> inputData;
-  shared_ptr<LogEvent> event =
-      make_shared<LogEvent>(nonUidAtomTagId, timestamp);
-  // 32
-  event->write(isolatedNonAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
-  // 22
-  event->write(hostNonAdditiveData);
-  event->init();
-  inputData.push_back(event);
-
-  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
-
-  EXPECT_EQ(2, (int)inputData.size());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(puller_util, MergeNoDimension) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  // 30->22->31
+//  event->write(isolatedUid);
+//  event->write(hostNonAdditiveData);
+//  event->write(isolatedAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 20->22->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(hostNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+//      .WillRepeatedly(Return(hostUid));
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+//      .WillRepeatedly(ReturnArg<0>());
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+//  vector<vector<int>> actual;
+//  extractIntoVector(inputData, actual);
+//  vector<int> expectedV1 = {20, 22, 52};
+//  EXPECT_EQ(1, (int)actual.size());
+//  EXPECT_THAT(actual, Contains(expectedV1));
+//}
+//
+//TEST(puller_util, MergeWithDimension) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  // 30->32->31
+//  event->write(isolatedUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(isolatedAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 20->32->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 20->22->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(hostNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+//      .WillRepeatedly(Return(hostUid));
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+//      .WillRepeatedly(ReturnArg<0>());
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+//  vector<vector<int>> actual;
+//  extractIntoVector(inputData, actual);
+//  vector<int> expectedV1 = {20, 22, 21};
+//  vector<int> expectedV2 = {20, 32, 52};
+//  EXPECT_EQ(2, (int)actual.size());
+//  EXPECT_THAT(actual, Contains(expectedV1));
+//  EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, NoMergeHostUidOnly) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  // 20->32->31
+//  event->write(hostUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(isolatedAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 20->22->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(hostNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+//      .WillRepeatedly(Return(hostUid));
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+//      .WillRepeatedly(ReturnArg<0>());
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+//  // 20->32->31
+//  // 20->22->21
+//  vector<vector<int>> actual;
+//  extractIntoVector(inputData, actual);
+//  vector<int> expectedV1 = {20, 32, 31};
+//  vector<int> expectedV2 = {20, 22, 21};
+//  EXPECT_EQ(2, (int)actual.size());
+//  EXPECT_THAT(actual, Contains(expectedV1));
+//  EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, IsolatedUidOnly) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  // 30->32->31
+//  event->write(hostUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(isolatedAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 30->22->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(hostNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(isolatedUid))
+//      .WillRepeatedly(Return(hostUid));
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(Ne(isolatedUid)))
+//      .WillRepeatedly(ReturnArg<0>());
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+//  // 20->32->31
+//  // 20->22->21
+//  vector<vector<int>> actual;
+//  extractIntoVector(inputData, actual);
+//  vector<int> expectedV1 = {20, 32, 31};
+//  vector<int> expectedV2 = {20, 22, 21};
+//  EXPECT_EQ(2, (int)actual.size());
+//  EXPECT_THAT(actual, Contains(expectedV1));
+//  EXPECT_THAT(actual, Contains(expectedV2));
+//}
+//
+//TEST(puller_util, MultipleIsolatedUidToOneHostUid) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  // 30->32->31
+//  event->write(isolatedUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(isolatedAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 31->32->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(isolatedUid + 1);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  // 20->32->21
+//  event = make_shared<LogEvent>(uidAtomTagId, timestamp);
+//  event->write(hostUid);
+//  event->write(isolatedNonAdditiveData);
+//  event->write(hostAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  EXPECT_CALL(*uidMap, getHostUidOrSelf(_)).WillRepeatedly(Return(hostUid));
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, uidAtomTagId, uidAdditiveFields);
+//
+//  vector<vector<int>> actual;
+//  extractIntoVector(inputData, actual);
+//  vector<int> expectedV1 = {20, 32, 73};
+//  EXPECT_EQ(1, (int)actual.size());
+//  EXPECT_THAT(actual, Contains(expectedV1));
+//}
+//
+//TEST(puller_util, NoNeedToMerge) {
+//  vector<shared_ptr<LogEvent>> inputData;
+//  shared_ptr<LogEvent> event =
+//      make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+//  // 32
+//  event->write(isolatedNonAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  event = make_shared<LogEvent>(nonUidAtomTagId, timestamp);
+//  // 22
+//  event->write(hostNonAdditiveData);
+//  event->init();
+//  inputData.push_back(event);
+//
+//  sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//  mapAndMergeIsolatedUidsToHostUid(inputData, uidMap, nonUidAtomTagId, {} /*no additive fields*/);
+//
+//  EXPECT_EQ(2, (int)inputData.size());
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
index 8915c73..b882678 100644
--- a/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/CountMetricProducer_test.cpp
@@ -37,365 +37,366 @@
 
 const ConfigKey kConfigKey(0, 12345);
 
-TEST(CountMetricProducerTest, TestFirstBucket) {
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
-                                      600 * NS_PER_SEC + NS_PER_SEC / 2);
-    EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(10, countProducer.mCurrentBucketNum);
-    EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
-}
-
-TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
-    int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
-    int tagId = 1;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.init();
-    LogEvent event2(tagId, bucketStartTimeNs + 2);
-    event2.init();
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      bucketStartTimeNs, bucketStartTimeNs);
-
-    // 2 events in bucket 1.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-
-    // Flushes at event #2.
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
-    // Flushes.
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
-    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                countProducer.mPastBuckets.end());
-    const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
-    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(2LL, buckets[0].mCount);
-
-    // 1 matched event happens in bucket 2.
-    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
-    event3.init();
-
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
-    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                countProducer.mPastBuckets.end());
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
-    EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
-    EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
-    EXPECT_EQ(1LL, bucketInfo2.mCount);
-
-    // nothing happens in bucket 3. we should not record anything for bucket 3.
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
-    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                countProducer.mPastBuckets.end());
-    const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(2UL, buckets3.size());
-}
-
-TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_condition(StringToId("SCREEN_ON"));
-
-    LogEvent event1(1, bucketStartTimeNs + 1);
-    event1.init();
-
-    LogEvent event2(1, bucketStartTimeNs + 10);
-    event2.init();
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
-                                      bucketStartTimeNs);
-
-    countProducer.onConditionChanged(true, bucketStartTimeNs);
-    countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
-    countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
-    // Upon this match event, the matched event1 is flushed.
-    countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
-    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                countProducer.mPastBuckets.end());
-    {
-        const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-        EXPECT_EQ(1UL, buckets.size());
-        const auto& bucketInfo = buckets[0];
-        EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
-        EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
-        EXPECT_EQ(1LL, bucketInfo.mCount);
-    }
-}
-
-TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
-    int tagId = 1;
-    int conditionTagId = 2;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
-    MetricConditionLink* link = metric.add_links();
-    link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
-    buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
-    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.write("111");  // uid
-    event1.init();
-    ConditionKey key1;
-    key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
-        {getMockedDimensionKey(conditionTagId, 2, "111")};
-
-    LogEvent event2(tagId, bucketStartTimeNs + 10);
-    event2.write("222");  // uid
-    event2.init();
-    ConditionKey key2;
-    key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
-        {getMockedDimensionKey(conditionTagId, 2, "222")};
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
-
-    EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
-
-    CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
-                                      bucketStartTimeNs, bucketStartTimeNs);
-
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
-    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                countProducer.mPastBuckets.end());
-    const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
-    const auto& bucketInfo = buckets[0];
-    EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
-    EXPECT_EQ(1LL, bucketInfo.mCount);
-}
-
-TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
-    sp<AlarmMonitor> alarmMonitor;
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
-
-    int tagId = 1;
-    int conditionTagId = 2;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    Alert alert;
-    alert.set_num_buckets(3);
-    alert.set_trigger_if_sum_gt(2);
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.write("111");  // uid
-    event1.init();
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
-                                      bucketStartTimeNs, bucketStartTimeNs);
-
-    sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
-    EXPECT_TRUE(anomalyTracker != nullptr);
-
-    // Bucket is flushed yet.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    // App upgrade forces bucket flush.
-    // Check that there's a past bucket and the bucket end is not adjusted.
-    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ((long long)bucketStartTimeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-    EXPECT_EQ((long long)eventUpgradeTimeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
-    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
-    // Anomaly tracker only contains full buckets.
-    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
-    // Next event occurs in same bucket as partial bucket created.
-    LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
-    event2.write("222");  // uid
-    event2.init();
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    // Third event in following bucket.
-    LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
-    event3.write("333");  // uid
-    event3.init();
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
-
-    int tagId = 1;
-    int conditionTagId = 2;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.write("111");  // uid
-    event1.init();
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
-                                      bucketStartTimeNs, bucketStartTimeNs);
-
-    // Bucket is flushed yet.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
-
-    // App upgrade forces bucket flush.
-    // Check that there's a past bucket and the bucket end is not adjusted.
-    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ((int64_t)bucketStartTimeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
-    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
-
-    // Next event occurs in same bucket as partial bucket created.
-    LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
-    event2.write("222");  // uid
-    event2.init();
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-
-    // Third event in following bucket.
-    LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
-    event3.write("333");  // uid
-    event3.init();
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ((int64_t)eventUpgradeTimeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
-              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
-}
-
-TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
-    sp<AlarmMonitor> alarmMonitor;
-    Alert alert;
-    alert.set_id(11);
-    alert.set_metric_id(1);
-    alert.set_trigger_if_sum_gt(2);
-    alert.set_num_buckets(2);
-    const int32_t refPeriodSec = 1;
-    alert.set_refractory_period_secs(refPeriodSec);
-
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
-    int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
-
-    CountMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      bucketStartTimeNs, bucketStartTimeNs);
-
-    sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
-
-    int tagId = 1;
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.init();
-    LogEvent event2(tagId, bucketStartTimeNs + 2);
-    event2.init();
-    LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    event3.init();
-    LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
-    event4.init();
-    LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
-    event5.init();
-    LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
-    event6.init();
-    LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
-    event7.init();
-
-    // Two events in bucket #0.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
-
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
-    EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
-    // One event in bucket #2. No alarm as bucket #0 is trashed out.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
-    EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
-    // Two events in bucket #3.
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
-    EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
-    // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
-    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
-    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
-    EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(CountMetricProducerTest, TestFirstBucket) {
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, 5,
+//                                      600 * NS_PER_SEC + NS_PER_SEC / 2);
+//    EXPECT_EQ(600500000000, countProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(10, countProducer.mCurrentBucketNum);
+//    EXPECT_EQ(660000000005, countProducer.getCurrentBucketEndTimeNs());
+//}
+//
+//TEST(CountMetricProducerTest, TestNonDimensionalEvents) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
+//    int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
+//    int tagId = 1;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.init();
+//    LogEvent event2(tagId, bucketStartTimeNs + 2);
+//    event2.init();
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      bucketStartTimeNs, bucketStartTimeNs);
+//
+//    // 2 events in bucket 1.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//
+//    // Flushes at event #2.
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + 2);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+//    // Flushes.
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+//    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                countProducer.mPastBuckets.end());
+//    const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(2LL, buckets[0].mCount);
+//
+//    // 1 matched event happens in bucket 2.
+//    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+//    event3.init();
+//
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+//    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                countProducer.mPastBuckets.end());
+//    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    const auto& bucketInfo2 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1];
+//    EXPECT_EQ(bucket2StartTimeNs, bucketInfo2.mBucketStartNs);
+//    EXPECT_EQ(bucket2StartTimeNs + bucketSizeNs, bucketInfo2.mBucketEndNs);
+//    EXPECT_EQ(1LL, bucketInfo2.mCount);
+//
+//    // nothing happens in bucket 3. we should not record anything for bucket 3.
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+//    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                countProducer.mPastBuckets.end());
+//    const auto& buckets3 = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(2UL, buckets3.size());
+//}
+//
+//TEST(CountMetricProducerTest, TestEventsWithNonSlicedCondition) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_condition(StringToId("SCREEN_ON"));
+//
+//    LogEvent event1(1, bucketStartTimeNs + 1);
+//    event1.init();
+//
+//    LogEvent event2(1, bucketStartTimeNs + 10);
+//    event2.init();
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    CountMetricProducer countProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs,
+//                                      bucketStartTimeNs);
+//
+//    countProducer.onConditionChanged(true, bucketStartTimeNs);
+//    countProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+//    countProducer.onConditionChanged(false /*new condition*/, bucketStartTimeNs + 2);
+//    // Upon this match event, the matched event1 is flushed.
+//    countProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+//    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                countProducer.mPastBuckets.end());
+//    {
+//        const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//        EXPECT_EQ(1UL, buckets.size());
+//        const auto& bucketInfo = buckets[0];
+//        EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
+//        EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
+//        EXPECT_EQ(1LL, bucketInfo.mCount);
+//    }
+//}
+//
+//TEST(CountMetricProducerTest, TestEventsWithSlicedCondition) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+//    int tagId = 1;
+//    int conditionTagId = 2;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
+//    MetricConditionLink* link = metric.add_links();
+//    link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
+//    buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+//    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
+//
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.write("111");  // uid
+//    event1.init();
+//    ConditionKey key1;
+//    key1[StringToId("APP_IN_BACKGROUND_PER_UID")] =
+//        {getMockedDimensionKey(conditionTagId, 2, "111")};
+//
+//    LogEvent event2(tagId, bucketStartTimeNs + 10);
+//    event2.write("222");  // uid
+//    event2.init();
+//    ConditionKey key2;
+//    key2[StringToId("APP_IN_BACKGROUND_PER_UID")] =
+//        {getMockedDimensionKey(conditionTagId, 2, "222")};
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
+//
+//    EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
+//
+//    CountMetricProducer countProducer(kConfigKey, metric, 1 /*condition tracker index*/, wizard,
+//                                      bucketStartTimeNs, bucketStartTimeNs);
+//
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + 1);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//    countProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets.size());
+//    EXPECT_TRUE(countProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                countProducer.mPastBuckets.end());
+//    const auto& buckets = countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets.size());
+//    const auto& bucketInfo = buckets[0];
+//    EXPECT_EQ(bucketStartTimeNs, bucketInfo.mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, bucketInfo.mBucketEndNs);
+//    EXPECT_EQ(1LL, bucketInfo.mCount);
+//}
+//
+//TEST(CountMetricProducerTest, TestEventWithAppUpgrade) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//    int conditionTagId = 2;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    Alert alert;
+//    alert.set_num_buckets(3);
+//    alert.set_trigger_if_sum_gt(2);
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.write("111");  // uid
+//    event1.init();
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+//                                      bucketStartTimeNs, bucketStartTimeNs);
+//
+//    sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
+//    EXPECT_TRUE(anomalyTracker != nullptr);
+//
+//    // Bucket is flushed yet.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    // App upgrade forces bucket flush.
+//    // Check that there's a past bucket and the bucket end is not adjusted.
+//    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ((long long)bucketStartTimeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+//    EXPECT_EQ((long long)eventUpgradeTimeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+//    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+//    // Anomaly tracker only contains full buckets.
+//    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    int64_t lastEndTimeNs = countProducer.getCurrentBucketEndTimeNs();
+//    // Next event occurs in same bucket as partial bucket created.
+//    LogEvent event2(tagId, bucketStartTimeNs + 59 * NS_PER_SEC + 10);
+//    event2.write("222");  // uid
+//    event2.init();
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    // Third event in following bucket.
+//    LogEvent event3(tagId, bucketStartTimeNs + 62 * NS_PER_SEC + 10);
+//    event3.write("333");  // uid
+//    event3.init();
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+//    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(lastEndTimeNs, countProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(CountMetricProducerTest, TestEventWithAppUpgradeInNextBucket) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//    int conditionTagId = 2;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.write("111");  // uid
+//    event1.init();
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    CountMetricProducer countProducer(kConfigKey, metric, -1 /* no condition */, wizard,
+//                                      bucketStartTimeNs, bucketStartTimeNs);
+//
+//    // Bucket is flushed yet.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+//    EXPECT_EQ(0UL, countProducer.mPastBuckets.size());
+//
+//    // App upgrade forces bucket flush.
+//    // Check that there's a past bucket and the bucket end is not adjusted.
+//    countProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ((int64_t)bucketStartTimeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketEndNs);
+//    EXPECT_EQ(eventUpgradeTimeNs, countProducer.mCurrentBucketStartTimeNs);
+//
+//    // Next event occurs in same bucket as partial bucket created.
+//    LogEvent event2(tagId, bucketStartTimeNs + 70 * NS_PER_SEC + 10);
+//    event2.write("222");  // uid
+//    event2.init();
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//    EXPECT_EQ(1UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//
+//    // Third event in following bucket.
+//    LogEvent event3(tagId, bucketStartTimeNs + 121 * NS_PER_SEC + 10);
+//    event3.write("333");  // uid
+//    event3.init();
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+//    EXPECT_EQ(2UL, countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ((int64_t)eventUpgradeTimeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs,
+//              countProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][1].mBucketEndNs);
+//}
+//
+//TEST(CountMetricProducerTest, TestAnomalyDetectionUnSliced) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    Alert alert;
+//    alert.set_id(11);
+//    alert.set_metric_id(1);
+//    alert.set_trigger_if_sum_gt(2);
+//    alert.set_num_buckets(2);
+//    const int32_t refPeriodSec = 1;
+//    alert.set_refractory_period_secs(refPeriodSec);
+//
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t bucket2StartTimeNs = bucketStartTimeNs + bucketSizeNs;
+//    int64_t bucket3StartTimeNs = bucketStartTimeNs + 2 * bucketSizeNs;
+//
+//    CountMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    CountMetricProducer countProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      bucketStartTimeNs, bucketStartTimeNs);
+//
+//    sp<AnomalyTracker> anomalyTracker = countProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+//    int tagId = 1;
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.init();
+//    LogEvent event2(tagId, bucketStartTimeNs + 2);
+//    event2.init();
+//    LogEvent event3(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    event3.init();
+//    LogEvent event4(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1);
+//    event4.init();
+//    LogEvent event5(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2);
+//    event5.init();
+//    LogEvent event6(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 3);
+//    event6.init();
+//    LogEvent event7(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
+//    event7.init();
+//
+//    // Two events in bucket #0.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event1);
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event2);
+//
+//    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+//    EXPECT_EQ(2L, countProducer.mCurrentSlicedCounter->begin()->second);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+//    // One event in bucket #2. No alarm as bucket #0 is trashed out.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event3);
+//    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+//    EXPECT_EQ(1L, countProducer.mCurrentSlicedCounter->begin()->second);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+//    // Two events in bucket #3.
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event4);
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event5);
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event6);
+//    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+//    EXPECT_EQ(3L, countProducer.mCurrentSlicedCounter->begin()->second);
+//    // Anomaly at event 6 is within refractory period. The alarm is at event 5 timestamp not event 6
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//            std::ceil(1.0 * event5.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+//    countProducer.onMatchedLogEvent(1 /*log matcher index*/, event7);
+//    EXPECT_EQ(1UL, countProducer.mCurrentSlicedCounter->size());
+//    EXPECT_EQ(4L, countProducer.mCurrentSlicedCounter->begin()->second);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//            std::ceil(1.0 * event7.GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//}
 
 TEST(CountMetricProducerTest, TestOneWeekTimeUnit) {
     CountMetric metric;
diff --git a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
index b294cad..6661374 100644
--- a/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/DurationMetricProducer_test.cpp
@@ -56,382 +56,383 @@
     EXPECT_EQ(660000000005, durationProducer.getCurrentBucketEndTimeNs());
 }
 
-TEST(DurationMetricTrackerTest, TestNoCondition) {
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-    int tagId = 1;
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.init();
-    LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
-    event2.init();
-
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
-    EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                durationProducer.mPastBuckets.end());
-    const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(2UL, buckets.size());
-    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
-    EXPECT_EQ(2LL, buckets[1].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-    int tagId = 1;
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.init();
-    LogEvent event2(tagId, bucketStartTimeNs + 2);
-    event2.init();
-    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
-    event3.init();
-    LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
-    event4.init();
-
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-    durationProducer.mCondition = ConditionState::kFalse;
-
-    EXPECT_FALSE(durationProducer.mCondition);
-    EXPECT_FALSE(durationProducer.isConditionSliced());
-
-    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-
-    durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
-    durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
-    EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
-                durationProducer.mPastBuckets.end());
-    const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets2.size());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
-    EXPECT_EQ(1LL, buckets2[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-
-    int tagId = 1;
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    event1.init();
-    LogEvent event2(tagId, bucketStartTimeNs + 2);
-    event2.init();
-    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
-    event3.init();
-    LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
-    event4.init();
-
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
-    EXPECT_FALSE(durationProducer.isConditionSliced());
-
-    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-
-    durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
-    durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
-    const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets2.size());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
-    EXPECT_EQ(1LL, buckets2[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
-    /**
-     * The duration starts from the first bucket, through the two partial buckets (10-70sec),
-     * another bucket, and ends at the beginning of the next full bucket.
-     * Expected buckets:
-     *  - [10,25]: 14 secs
-     *  - [25,70]: All 45 secs
-     *  - [70,130]: All 60 secs
-     *  - [130, 210]: Only 5 secs (event ended at 135sec)
-     */
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
-    int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
-    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
-    int tagId = 1;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    LogEvent start_event(tagId, startTimeNs);
-    start_event.init();
-    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    std::vector<DurationBucket> buckets =
-            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
-    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
-    LogEvent end_event(tagId, endTimeNs);
-    end_event.init();
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(3UL, buckets.size());
-    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
-    EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
-    /**
-     * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
-     *  - [10,70]: 59 secs
-     *  - [70,75]: 5 sec
-     *  - [75,130]: 55 secs
-     */
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
-    int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
-    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
-    int tagId = 1;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    LogEvent start_event(tagId, startTimeNs);
-    start_event.init();
-    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    std::vector<DurationBucket> buckets =
-            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
-    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
-    EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
-    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
-    LogEvent end_event(tagId, endTimeNs);
-    end_event.init();
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(3UL, buckets.size());
-    EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
-    sp<AlarmMonitor> alarmMonitor;
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
-    int64_t startTimeNs = bucketStartTimeNs + 1;
-    int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
-
-    int tagId = 1;
-
-    // Setup metric with alert.
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
-    Alert alert;
-    alert.set_num_buckets(3);
-    alert.set_trigger_if_sum_gt(2);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
-    EXPECT_TRUE(anomalyTracker != nullptr);
-
-    LogEvent start_event(tagId, startTimeNs);
-    start_event.init();
-    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
-    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
-    LogEvent end_event(tagId, endTimeNs);
-    end_event.init();
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
-              anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
-    int64_t startTimeNs = bucketStartTimeNs + 1;
-    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
-
-    int tagId = 1;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
-    LogEvent event1(tagId, startTimeNs);
-    event1.write("111");  // uid
-    event1.init();
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    LogEvent start_event(tagId, startTimeNs);
-    start_event.init();
-    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
-    LogEvent end_event(tagId, endTimeNs);
-    end_event.init();
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
-    std::vector<DurationBucket> buckets =
-            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
-}
-
-TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
-    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
-    int64_t startTimeNs = bucketStartTimeNs + 1;
-    int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
-
-    int tagId = 1;
-
-    DurationMetric metric;
-    metric.set_id(1);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
-    LogEvent event1(tagId, startTimeNs);
-    event1.write("111");  // uid
-    event1.init();
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    FieldMatcher dimensions;
-    DurationMetricProducer durationProducer(
-            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
-            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
-
-    LogEvent start_event(tagId, startTimeNs);
-    start_event.init();
-    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
-    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    // Stop occurs in the same partial bucket as created for the app upgrade.
-    LogEvent end_event(tagId, endTimeNs);
-    end_event.init();
-    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
-    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
-
-    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
-    std::vector<DurationBucket> buckets =
-            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
-    EXPECT_EQ(1UL, buckets.size());
-    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
-    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
-    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
-}
+// TODO(b/149590301): Update these to use new socket schema.
+//TEST(DurationMetricTrackerTest, TestNoCondition) {
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//    int tagId = 1;
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.init();
+//    LogEvent event2(tagId, bucketStartTimeNs + bucketSizeNs + 2);
+//    event2.init();
+//
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /*no condition*/, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+//    EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                durationProducer.mPastBuckets.end());
+//    const auto& buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(2UL, buckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(bucketSizeNs - 1LL, buckets[0].mDuration);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[1].mBucketEndNs);
+//    EXPECT_EQ(2LL, buckets[1].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestNonSlicedCondition) {
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//    int tagId = 1;
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.init();
+//    LogEvent event2(tagId, bucketStartTimeNs + 2);
+//    event2.init();
+//    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+//    event3.init();
+//    LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+//    event4.init();
+//
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//    durationProducer.mCondition = ConditionState::kFalse;
+//
+//    EXPECT_FALSE(durationProducer.mCondition);
+//    EXPECT_FALSE(durationProducer.isConditionSliced());
+//
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
+//    durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+//    EXPECT_TRUE(durationProducer.mPastBuckets.find(DEFAULT_METRIC_DIMENSION_KEY) !=
+//                durationProducer.mPastBuckets.end());
+//    const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets2.size());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
+//    EXPECT_EQ(1LL, buckets2[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestNonSlicedConditionUnknownState) {
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//
+//    int tagId = 1;
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    event1.init();
+//    LogEvent event2(tagId, bucketStartTimeNs + 2);
+//    event2.init();
+//    LogEvent event3(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+//    event3.init();
+//    LogEvent event4(tagId, bucketStartTimeNs + bucketSizeNs + 3);
+//    event4.init();
+//
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, 0 /* condition index */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    EXPECT_EQ(ConditionState::kUnknown, durationProducer.mCondition);
+//    EXPECT_FALSE(durationProducer.isConditionSliced());
+//
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, event1);
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, event2);
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + bucketSizeNs + 1);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, event3);
+//    durationProducer.onConditionChanged(true /* condition */, bucketStartTimeNs + bucketSizeNs + 2);
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, event4);
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    EXPECT_EQ(1UL, durationProducer.mPastBuckets.size());
+//    const auto& buckets2 = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets2.size());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets2[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets2[0].mBucketEndNs);
+//    EXPECT_EQ(1LL, buckets2[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgrade) {
+//    /**
+//     * The duration starts from the first bucket, through the two partial buckets (10-70sec),
+//     * another bucket, and ends at the beginning of the next full bucket.
+//     * Expected buckets:
+//     *  - [10,25]: 14 secs
+//     *  - [25,70]: All 45 secs
+//     *  - [70,130]: All 60 secs
+//     *  - [130, 210]: Only 5 secs (event ended at 135sec)
+//     */
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+//    int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+//    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    LogEvent start_event(tagId, startTimeNs);
+//    start_event.init();
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    std::vector<DurationBucket> buckets =
+//            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(eventUpgradeTimeNs - startTimeNs, buckets[0].mDuration);
+//    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+//    LogEvent end_event(tagId, endTimeNs);
+//    end_event.init();
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(3UL, buckets.size());
+//    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketEndNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - eventUpgradeTimeNs, buckets[1].mDuration);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[2].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+//    EXPECT_EQ(bucketSizeNs, buckets[2].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationWithUpgradeInFollowingBucket) {
+//    /**
+//     * Expected buckets (start at 11s, upgrade at 75s, end at 135s):
+//     *  - [10,70]: 59 secs
+//     *  - [70,75]: 5 sec
+//     *  - [75,130]: 55 secs
+//     */
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+//    int64_t startTimeNs = bucketStartTimeNs + 1 * NS_PER_SEC;
+//    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    LogEvent start_event(tagId, startTimeNs);
+//    start_event.init();
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(2UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    std::vector<DurationBucket> buckets =
+//            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(bucketStartTimeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs, buckets[0].mDuration);
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, buckets[1].mBucketStartNs);
+//    EXPECT_EQ(eventUpgradeTimeNs, buckets[1].mBucketEndNs);
+//    EXPECT_EQ(eventUpgradeTimeNs - (bucketStartTimeNs + bucketSizeNs), buckets[1].mDuration);
+//    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+//    LogEvent end_event(tagId, endTimeNs);
+//    end_event.init();
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//    buckets = durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(3UL, buckets.size());
+//    EXPECT_EQ(eventUpgradeTimeNs, buckets[2].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[2].mBucketEndNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs - eventUpgradeTimeNs, buckets[2].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestSumDurationAnomalyWithUpgrade) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+//    int64_t startTimeNs = bucketStartTimeNs + 1;
+//    int64_t endTimeNs = startTimeNs + 65 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//
+//    // Setup metric with alert.
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_SUM);
+//    Alert alert;
+//    alert.set_num_buckets(3);
+//    alert.set_trigger_if_sum_gt(2);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    sp<AnomalyTracker> anomalyTracker = durationProducer.addAnomalyTracker(alert, alarmMonitor);
+//    EXPECT_TRUE(anomalyTracker != nullptr);
+//
+//    LogEvent start_event(tagId, startTimeNs);
+//    start_event.init();
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+//    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+//    LogEvent end_event(tagId, endTimeNs);
+//    end_event.init();
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs - startTimeNs,
+//              anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgrade) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 15 * NS_PER_SEC;
+//    int64_t startTimeNs = bucketStartTimeNs + 1;
+//    int64_t endTimeNs = startTimeNs + 125 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+//    LogEvent event1(tagId, startTimeNs);
+//    event1.write("111");  // uid
+//    event1.init();
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    LogEvent start_event(tagId, startTimeNs);
+//    start_event.init();
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    // We skip ahead one bucket, so we fill in the first two partial buckets and one full bucket.
+//    LogEvent end_event(tagId, endTimeNs);
+//    end_event.init();
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 3 * bucketSizeNs + 1);
+//    std::vector<DurationBucket> buckets =
+//            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets.size());
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 3 * bucketSizeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+//}
+//
+//TEST(DurationMetricTrackerTest, TestMaxDurationWithUpgradeInNextBucket) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = TimeUnitToBucketSizeInMillis(ONE_MINUTE) * 1000000LL;
+//    int64_t eventUpgradeTimeNs = bucketStartTimeNs + 65 * NS_PER_SEC;
+//    int64_t startTimeNs = bucketStartTimeNs + 1;
+//    int64_t endTimeNs = startTimeNs + 115 * NS_PER_SEC;
+//
+//    int tagId = 1;
+//
+//    DurationMetric metric;
+//    metric.set_id(1);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_aggregation_type(DurationMetric_AggregationType_MAX_SPARSE);
+//    LogEvent event1(tagId, startTimeNs);
+//    event1.write("111");  // uid
+//    event1.init();
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    FieldMatcher dimensions;
+//    DurationMetricProducer durationProducer(
+//            kConfigKey, metric, -1 /* no condition */, 1 /* start index */, 2 /* stop index */,
+//            3 /* stop_all index */, false /*nesting*/, wizard, dimensions, bucketStartTimeNs, bucketStartTimeNs);
+//
+//    LogEvent start_event(tagId, startTimeNs);
+//    start_event.init();
+//    durationProducer.onMatchedLogEvent(1 /* start index*/, start_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets.size());
+//    EXPECT_EQ(bucketStartTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    durationProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    // Stop occurs in the same partial bucket as created for the app upgrade.
+//    LogEvent end_event(tagId, endTimeNs);
+//    end_event.init();
+//    durationProducer.onMatchedLogEvent(2 /* stop index*/, end_event);
+//    EXPECT_EQ(0UL, durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(eventUpgradeTimeNs, durationProducer.mCurrentBucketStartTimeNs);
+//
+//    durationProducer.flushIfNeededLocked(bucketStartTimeNs + 2 * bucketSizeNs + 1);
+//    std::vector<DurationBucket> buckets =
+//            durationProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY];
+//    EXPECT_EQ(1UL, buckets.size());
+//    EXPECT_EQ(eventUpgradeTimeNs, buckets[0].mBucketStartNs);
+//    EXPECT_EQ(bucketStartTimeNs + 2 * bucketSizeNs, buckets[0].mBucketEndNs);
+//    EXPECT_EQ(endTimeNs - startTimeNs, buckets[0].mDuration);
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
index f30873b..0f39efd5 100644
--- a/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/EventMetricProducer_test.cpp
@@ -85,46 +85,47 @@
     // eventProducer.onDumpReport();
 }
 
-TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
-    int64_t bucketStartTimeNs = 10000000000;
-    int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
-
-    int tagId = 1;
-    int conditionTagId = 2;
-
-    EventMetric metric;
-    metric.set_id(1);
-    metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
-    MetricConditionLink* link = metric.add_links();
-    link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
-    buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
-    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
-
-    LogEvent event1(tagId, bucketStartTimeNs + 1);
-    EXPECT_TRUE(event1.write("111"));
-    event1.init();
-    ConditionKey key1;
-    key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
-
-    LogEvent event2(tagId, bucketStartTimeNs + 10);
-    EXPECT_TRUE(event2.write("222"));
-    event2.init();
-    ConditionKey key2;
-    key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
-
-    EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
-
-    EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
-
-    eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
-    eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
-
-    // TODO: get the report and check the content after the ProtoOutputStream change is done.
-    // eventProducer.onDumpReport();
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(EventMetricProducerTest, TestEventsWithSlicedCondition) {
+//    int64_t bucketStartTimeNs = 10000000000;
+//    int64_t bucketSizeNs = 30 * 1000 * 1000 * 1000LL;
+//
+//    int tagId = 1;
+//    int conditionTagId = 2;
+//
+//    EventMetric metric;
+//    metric.set_id(1);
+//    metric.set_condition(StringToId("APP_IN_BACKGROUND_PER_UID_AND_SCREEN_ON"));
+//    MetricConditionLink* link = metric.add_links();
+//    link->set_condition(StringToId("APP_IN_BACKGROUND_PER_UID"));
+//    buildSimpleAtomFieldMatcher(tagId, 1, link->mutable_fields_in_what());
+//    buildSimpleAtomFieldMatcher(conditionTagId, 2, link->mutable_fields_in_condition());
+//
+//    LogEvent event1(tagId, bucketStartTimeNs + 1);
+//    EXPECT_TRUE(event1.write("111"));
+//    event1.init();
+//    ConditionKey key1;
+//    key1[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "111")};
+//
+//    LogEvent event2(tagId, bucketStartTimeNs + 10);
+//    EXPECT_TRUE(event2.write("222"));
+//    event2.init();
+//    ConditionKey key2;
+//    key2[StringToId("APP_IN_BACKGROUND_PER_UID")] = {getMockedDimensionKey(conditionTagId, 2, "222")};
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    EXPECT_CALL(*wizard, query(_, key1, _)).WillOnce(Return(ConditionState::kFalse));
+//
+//    EXPECT_CALL(*wizard, query(_, key2, _)).WillOnce(Return(ConditionState::kTrue));
+//
+//    EventMetricProducer eventProducer(kConfigKey, metric, 1, wizard, bucketStartTimeNs);
+//
+//    eventProducer.onMatchedLogEvent(1 /*matcher index*/, event1);
+//    eventProducer.onMatchedLogEvent(1 /*matcher index*/, event2);
+//
+//    // TODO: get the report and check the content after the ProtoOutputStream change is done.
+//    // eventProducer.onDumpReport();
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
index 308c43d..609324e 100644
--- a/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/GaugeMetricProducer_test.cpp
@@ -88,768 +88,769 @@
     EXPECT_EQ(660000000005, gaugeProducer.getCurrentBucketEndTimeNs());
 }
 
-TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.mutable_gauge_fields_filter()->set_include_all(false);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(1);
-    gaugeFieldMatcher->add_child()->set_field(3);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(3);
-                event->write("some value");
-                event->write(11);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(10);
-    event->write("some value");
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(10, it->mValue.int_value);
-    it++;
-    EXPECT_EQ(11, it->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
-        .front().mFields->begin()->mValue.int_value);
-
-    allData.clear();
-    std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
-    event2->write(24);
-    event2->write("some value");
-    event2->write(25);
-    event2->init();
-    allData.push_back(event2);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(24, it->mValue.int_value);
-    it++;
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(25, it->mValue.int_value);
-    // One dimension.
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
-    it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(10L, it->mValue.int_value);
-    it++;
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(11L, it->mValue.int_value);
-
-    gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
-    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
-    // One dimension.
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
-    it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(24L, it->mValue.int_value);
-    it++;
-    EXPECT_EQ(INT, it->mValue.getType());
-    EXPECT_EQ(25L, it->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
-    sp<AlarmMonitor> alarmMonitor;
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.mutable_gauge_fields_filter()->set_include_all(true);
-
-    Alert alert;
-    alert.set_id(101);
-    alert.set_metric_id(metricId);
-    alert.set_trigger_if_sum_gt(25);
-    alert.set_num_buckets(100);
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
-    EXPECT_TRUE(anomalyTracker != nullptr);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
-
-    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    // Partial buckets are not sent to anomaly tracker.
-    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    // Create an event in the same partial bucket.
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
-    event2->write(1);
-    event2->write(10);
-    event2->init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    // Partial buckets are not sent to anomaly tracker.
-    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    // Next event should trigger creation of new bucket and send previous full bucket to anomaly
-    // tracker.
-    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
-    event3->write(1);
-    event3->write(10);
-    event3->init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-    EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-
-    // Next event should trigger creation of new bucket.
-    shared_ptr<LogEvent> event4 =
-            make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
-    event4->write(1);
-    event4->write(10);
-    event4->init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-    EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
-}
-
-TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(2);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Return(false))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
-                event->write("some value");
-                event->write(2);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
-                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event->write("some value");
-    event->write(1);
-    event->init();
-    allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
-                         ->second.front()
-                         .mFields->begin()
-                         ->mValue.int_value);
-
-    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
-                         ->second.front()
-                         .mFields->begin()
-                         ->mValue.int_value);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
-    event->write("some value");
-    event->write(3);
-    event->init();
-    allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
-                         ->second.front()
-                         .mFields->begin()
-                         ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    metric.set_split_bucket_for_app_upgrade(false);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(2);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event->write("some value");
-    event->write(1);
-    event->init();
-    allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
-                         ->second.front()
-                         .mFields->begin()
-                         ->mValue.int_value);
-
-    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
-    EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
-                         ->second.front()
-                         .mFields->begin()
-                         ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(2);
-    metric.set_condition(StringToId("SCREEN_ON"));
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("some value");
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
-                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
-    gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
-                           ->second.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write("some value");
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
-                           ->second.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
-                           ->second.back()
-                           .mGaugeAtoms.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-
-    gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
-    gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
-                            ->second.back()
-                            .mGaugeAtoms.front()
-                            .mFields->begin()
-                            ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
-    const int conditionTag = 65;
-    GaugeMetric metric;
-    metric.set_id(1111111);
-    metric.set_bucket(ONE_MINUTE);
-    metric.mutable_gauge_fields_filter()->set_include_all(true);
-    metric.set_condition(StringToId("APP_DIED"));
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto dim = metric.mutable_dimensions_in_what();
-    dim->set_field(tagId);
-    dim->add_child()->set_field(1);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    EXPECT_CALL(*wizard, query(_, _, _))
-            .WillRepeatedly(
-                    Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
-                              const bool isPartialLink) {
-                        int pos[] = {1, 0, 0};
-                        Field f(conditionTag, pos, 0);
-                        HashableDimensionKey key;
-                        key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
-
-                        return ConditionState::kTrue;
-                    }));
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(1000);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
-                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
-    gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
-
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
-    EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
-    EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-
-    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(1000);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-}
-
-TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
-    sp<AlarmMonitor> alarmMonitor;
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(2);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    Alert alert;
-    alert.set_id(101);
-    alert.set_metric_id(metricId);
-    alert.set_trigger_if_sum_gt(25);
-    alert.set_num_buckets(2);
-    const int32_t refPeriodSec = 60;
-    alert.set_refractory_period_secs(refPeriodSec);
-    sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
-
-    int tagId = 1;
-    std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event1->write("some value");
-    event1->write(13);
-    event1->init();
-
-    gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
-                           ->second.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
-    std::shared_ptr<LogEvent> event2 =
-            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
-    event2->write("some value");
-    event2->write(15);
-    event2->init();
-
-    gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
-                           ->second.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-              std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
-
-    std::shared_ptr<LogEvent> event3 =
-            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
-    event3->write("some value");
-    event3->write(26);
-    event3->init();
-
-    gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
-                           ->second.front()
-                           .mFields->begin()
-                           ->mValue.int_value);
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-              std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
-    // The event4 does not have the gauge field. Thus the current bucket value is 0.
-    std::shared_ptr<LogEvent> event4 =
-            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
-    event4->write("some value");
-    event4->init();
-    gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
-}
-
-TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
-    metric.mutable_gauge_fields_filter()->set_include_all(false);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
-    gaugeFieldMatcher->set_field(tagId);
-    gaugeFieldMatcher->add_child()->set_field(1);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(4);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Return(true));
-
-    int triggerId = 5;
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-
-    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
-    LogEvent trigger(triggerId, bucketStartTimeNs + 10);
-    trigger.init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
-    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
-    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
-    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
-    EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
-                         ->second.back()
-                         .mGaugeAtoms[0]
-                         .mFields->begin()
-                         ->mValue.int_value);
-    EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
-                         ->second.back()
-                         .mGaugeAtoms[1]
-                         .mFields->begin()
-                         ->mValue.int_value);
-}
-
-TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(ONE_MINUTE);
-    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
-    metric.mutable_gauge_fields_filter()->set_include_all(true);
-    metric.set_max_pull_delay_sec(INT_MAX);
-    auto dimensionMatcher = metric.mutable_dimensions_in_what();
-    // use field 1 as dimension.
-    dimensionMatcher->set_field(tagId);
-    dimensionMatcher->add_child()->set_field(1);
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
-                event->write(3);
-                event->write(4);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(4);
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-                event->write(4);
-                event->write(6);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Return(true));
-
-    int triggerId = 5;
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-
-    LogEvent trigger(triggerId, bucketStartTimeNs + 3);
-    trigger.init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
-    trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
-    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
-    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
-    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
-    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
-    auto bucketIt = gaugeProducer.mPastBuckets.begin();
-    EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
-    EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
-    EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
-    bucketIt++;
-    EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
-    EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
-    EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
-    EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
-}
-
-/*
- * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
- * is smaller than the "min_bucket_size_nanos" specified in the metric config.
- */
-TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
-    GaugeMetric metric;
-    metric.set_id(metricId);
-    metric.set_bucket(FIVE_MINUTES);
-    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
-    metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
-
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
-        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Bucket start.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    int triggerId = 5;
-    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard,
-                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    LogEvent trigger(triggerId, bucketStartTimeNs + 3);
-    trigger.init();
-    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
-                                true, FAST /* dump_latency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_gauge_metrics());
-    EXPECT_EQ(0, report.gauge_metrics().data_size());
-    EXPECT_EQ(1, report.gauge_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
-              report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//TEST(GaugeMetricProducerTest, TestPulledEventsNoCondition) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.mutable_gauge_fields_filter()->set_include_all(false);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(1);
+//    gaugeFieldMatcher->add_child()->set_field(3);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write(3);
+//                event->write("some value");
+//                event->write(11);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(10);
+//    event->write("some value");
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    auto it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(10, it->mValue.int_value);
+//    it++;
+//    EXPECT_EQ(11, it->mValue.int_value);
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(3, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms
+//        .front().mFields->begin()->mValue.int_value);
+//
+//    allData.clear();
+//    std::shared_ptr<LogEvent> event2 = std::make_shared<LogEvent>(tagId, bucket3StartTimeNs + 10);
+//    event2->write(24);
+//    event2->write("some value");
+//    event2->write(25);
+//    event2->init();
+//    allData.push_back(event2);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    it = gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->begin();
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(24, it->mValue.int_value);
+//    it++;
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(25, it->mValue.int_value);
+//    // One dimension.
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+//    it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(10L, it->mValue.int_value);
+//    it++;
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(11L, it->mValue.int_value);
+//
+//    gaugeProducer.flushIfNeededLocked(bucket4StartTimeNs);
+//    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    // One dimension.
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets.begin()->second.size());
+//    it = gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.front().mFields->begin();
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(24L, it->mValue.int_value);
+//    it++;
+//    EXPECT_EQ(INT, it->mValue.getType());
+//    EXPECT_EQ(25L, it->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPushedEventsWithUpgrade) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.mutable_gauge_fields_filter()->set_include_all(true);
+//
+//    Alert alert;
+//    alert.set_id(101);
+//    alert.set_metric_id(metricId);
+//    alert.set_trigger_if_sum_gt(25);
+//    alert.set_num_buckets(100);
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      -1 /* -1 means no pulling */, -1, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
+//    EXPECT_TRUE(anomalyTracker != nullptr);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    EXPECT_EQ(1UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(0UL, (*gaugeProducer.mCurrentSlicedBucket).count(DEFAULT_METRIC_DIMENSION_KEY));
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ(eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+//    // Partial buckets are not sent to anomaly tracker.
+//    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    // Create an event in the same partial bucket.
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+//    event2->write(1);
+//    event2->write(10);
+//    event2->init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+//    // Partial buckets are not sent to anomaly tracker.
+//    EXPECT_EQ(0, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    // Next event should trigger creation of new bucket and send previous full bucket to anomaly
+//    // tracker.
+//    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+//    event3->write(1);
+//    event3->write(10);
+//    event3->init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//    EXPECT_EQ(1L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ((int64_t)bucketStartTimeNs + bucketSizeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(1, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//
+//    // Next event should trigger creation of new bucket.
+//    shared_ptr<LogEvent> event4 =
+//            make_shared<LogEvent>(tagId, bucketStartTimeNs + 125 * NS_PER_SEC);
+//    event4->write(1);
+//    event4->write(10);
+//    event4->init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//    EXPECT_EQ(2L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ(3UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(2, anomalyTracker->getSumOverPastBuckets(DEFAULT_METRIC_DIMENSION_KEY));
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledWithUpgrade) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(2);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Return(false))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventUpgradeTimeNs);
+//                event->write("some value");
+//                event->write(2);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+//                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event->write("some value");
+//    event->write(1);
+//    event->init();
+//    allData.push_back(event);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+//                         ->second.front()
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//
+//    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ((int64_t)eventUpgradeTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(2, gaugeProducer.mCurrentSlicedBucket->begin()
+//                         ->second.front()
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 1);
+//    event->write("some value");
+//    event->write(3);
+//    event->init();
+//    allData.push_back(event);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(3, gaugeProducer.mCurrentSlicedBucket->begin()
+//                         ->second.front()
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    metric.set_split_bucket_for_app_upgrade(false);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(2);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event->write("some value");
+//    event->write(1);
+//    event->init();
+//    allData.push_back(event);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+//                         ->second.front()
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//
+//    gaugeProducer.notifyAppUpgrade(eventUpgradeTimeNs, "ANY.APP", 1, 1);
+//    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(0L, gaugeProducer.mCurrentBucketNum);
+//    EXPECT_EQ(bucketStartTimeNs, gaugeProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(1, gaugeProducer.mCurrentSlicedBucket->begin()
+//                         ->second.front()
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsWithCondition) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(2);
+//    metric.set_condition(StringToId("SCREEN_ON"));
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("some value");
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+//                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+//    gaugeProducer.onConditionChanged(true, bucketStartTimeNs + 8);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(100, gaugeProducer.mCurrentSlicedBucket->begin()
+//                           ->second.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write("some value");
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(110, gaugeProducer.mCurrentSlicedBucket->begin()
+//                           ->second.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(100, gaugeProducer.mPastBuckets.begin()
+//                           ->second.back()
+//                           .mGaugeAtoms.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//
+//    gaugeProducer.onConditionChanged(false, bucket2StartTimeNs + 10);
+//    gaugeProducer.flushIfNeededLocked(bucket3StartTimeNs + 10);
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(110L, gaugeProducer.mPastBuckets.begin()
+//                            ->second.back()
+//                            .mGaugeAtoms.front()
+//                            .mFields->begin()
+//                            ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsWithSlicedCondition) {
+//    const int conditionTag = 65;
+//    GaugeMetric metric;
+//    metric.set_id(1111111);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.mutable_gauge_fields_filter()->set_include_all(true);
+//    metric.set_condition(StringToId("APP_DIED"));
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto dim = metric.mutable_dimensions_in_what();
+//    dim->set_field(tagId);
+//    dim->add_child()->set_field(1);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    EXPECT_CALL(*wizard, query(_, _, _))
+//            .WillRepeatedly(
+//                    Invoke([](const int conditionIndex, const ConditionKey& conditionParameters,
+//                              const bool isPartialLink) {
+//                        int pos[] = {1, 0, 0};
+//                        Field f(conditionTag, pos, 0);
+//                        HashableDimensionKey key;
+//                        key.mutableValues()->emplace_back(f, Value((int32_t)1000000));
+//
+//                        return ConditionState::kTrue;
+//                    }));
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write(1000);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, 1, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, tagId, -1, tagId,
+//                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+//    gaugeProducer.onSlicedConditionMayChange(true, bucketStartTimeNs + 8);
+//
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    const auto& key = gaugeProducer.mCurrentSlicedBucket->begin()->first;
+//    EXPECT_EQ(1UL, key.getDimensionKeyInWhat().getValues().size());
+//    EXPECT_EQ(1000, key.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//
+//    EXPECT_EQ(0UL, gaugeProducer.mPastBuckets.size());
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(1000);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    gaugeProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPulledEventsAnomalyDetection) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+//
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(2);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, -1, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    Alert alert;
+//    alert.set_id(101);
+//    alert.set_metric_id(metricId);
+//    alert.set_trigger_if_sum_gt(25);
+//    alert.set_num_buckets(2);
+//    const int32_t refPeriodSec = 60;
+//    alert.set_refractory_period_secs(refPeriodSec);
+//    sp<AnomalyTracker> anomalyTracker = gaugeProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+//    int tagId = 1;
+//    std::shared_ptr<LogEvent> event1 = std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event1->write("some value");
+//    event1->write(13);
+//    event1->init();
+//
+//    gaugeProducer.onDataPulled({event1}, /** succeed */ true, bucketStartTimeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(13L, gaugeProducer.mCurrentSlicedBucket->begin()
+//                           ->second.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+//    std::shared_ptr<LogEvent> event2 =
+//            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + bucketSizeNs + 20);
+//    event2->write("some value");
+//    event2->write(15);
+//    event2->init();
+//
+//    gaugeProducer.onDataPulled({event2}, /** succeed */ true, bucketStartTimeNs + bucketSizeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(15L, gaugeProducer.mCurrentSlicedBucket->begin()
+//                           ->second.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//              std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC) + refPeriodSec);
+//
+//    std::shared_ptr<LogEvent> event3 =
+//            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 10);
+//    event3->write("some value");
+//    event3->write(26);
+//    event3->init();
+//
+//    gaugeProducer.onDataPulled({event3}, /** succeed */ true, bucket2StartTimeNs + 2 * bucketSizeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(26L, gaugeProducer.mCurrentSlicedBucket->begin()
+//                           ->second.front()
+//                           .mFields->begin()
+//                           ->mValue.int_value);
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//              std::ceil(1.0 * event2->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+//    // The event4 does not have the gauge field. Thus the current bucket value is 0.
+//    std::shared_ptr<LogEvent> event4 =
+//            std::make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10);
+//    event4->write("some value");
+//    event4->init();
+//    gaugeProducer.onDataPulled({event4}, /** succeed */ true, bucketStartTimeNs + 3 * bucketSizeNs);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_TRUE(gaugeProducer.mCurrentSlicedBucket->begin()->second.front().mFields->empty());
+//}
+//
+//TEST(GaugeMetricProducerTest, TestPullOnTrigger) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+//    metric.mutable_gauge_fields_filter()->set_include_all(false);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto gaugeFieldMatcher = metric.mutable_gauge_fields_filter()->mutable_fields();
+//    gaugeFieldMatcher->set_field(tagId);
+//    gaugeFieldMatcher->add_child()->set_field(1);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write(4);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Return(true));
+//
+//    int triggerId = 5;
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//
+//    EXPECT_EQ(0UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    LogEvent trigger(triggerId, bucketStartTimeNs + 10);
+//    trigger.init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+//    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+//    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+//    EXPECT_EQ(1UL, gaugeProducer.mPastBuckets.size());
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.begin()->second.back().mGaugeAtoms.size());
+//    EXPECT_EQ(4, gaugeProducer.mPastBuckets.begin()
+//                         ->second.back()
+//                         .mGaugeAtoms[0]
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//    EXPECT_EQ(5, gaugeProducer.mPastBuckets.begin()
+//                         ->second.back()
+//                         .mGaugeAtoms[1]
+//                         .mFields->begin()
+//                         ->mValue.int_value);
+//}
+//
+//TEST(GaugeMetricProducerTest, TestRemoveDimensionInOutput) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(ONE_MINUTE);
+//    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+//    metric.mutable_gauge_fields_filter()->set_include_all(true);
+//    metric.set_max_pull_delay_sec(INT_MAX);
+//    auto dimensionMatcher = metric.mutable_dimensions_in_what();
+//    // use field 1 as dimension.
+//    dimensionMatcher->set_field(tagId);
+//    dimensionMatcher->add_child()->set_field(1);
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3);
+//                event->write(3);
+//                event->write(4);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write(4);
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//                event->write(4);
+//                event->write(6);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Return(true));
+//
+//    int triggerId = 5;
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//
+//    LogEvent trigger(triggerId, bucketStartTimeNs + 3);
+//    trigger.init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    trigger.setElapsedTimestampNs(bucketStartTimeNs + 10);
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->size());
+//    EXPECT_EQ(1UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+//    trigger.setElapsedTimestampNs(bucketStartTimeNs + 20);
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//    EXPECT_EQ(2UL, gaugeProducer.mCurrentSlicedBucket->begin()->second.size());
+//    trigger.setElapsedTimestampNs(bucket2StartTimeNs + 1);
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+//    EXPECT_EQ(2UL, gaugeProducer.mPastBuckets.size());
+//    auto bucketIt = gaugeProducer.mPastBuckets.begin();
+//    EXPECT_EQ(1UL, bucketIt->second.back().mGaugeAtoms.size());
+//    EXPECT_EQ(3, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+//    EXPECT_EQ(4, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+//    bucketIt++;
+//    EXPECT_EQ(2UL, bucketIt->second.back().mGaugeAtoms.size());
+//    EXPECT_EQ(4, bucketIt->first.getDimensionKeyInWhat().getValues().begin()->mValue.int_value);
+//    EXPECT_EQ(5, bucketIt->second.back().mGaugeAtoms[0].mFields->begin()->mValue.int_value);
+//    EXPECT_EQ(6, bucketIt->second.back().mGaugeAtoms[1].mFields->begin()->mValue.int_value);
+//}
+//
+///*
+// * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+// * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+// */
+//TEST(GaugeMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+//    GaugeMetric metric;
+//    metric.set_id(metricId);
+//    metric.set_bucket(FIVE_MINUTES);
+//    metric.set_sampling_type(GaugeMetric::FIRST_N_SAMPLES);
+//    metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
+//
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard = new EventMatcherWizard({
+//        new SimpleLogMatchingTracker(atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Bucket start.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    int triggerId = 5;
+//    GaugeMetricProducer gaugeProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard,
+//                                      tagId, triggerId, tagId, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    LogEvent trigger(triggerId, bucketStartTimeNs + 3);
+//    trigger.init();
+//    gaugeProducer.onMatchedLogEvent(1 /*log matcher index*/, trigger);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    gaugeProducer.onDumpReport(bucketStartTimeNs + 9000000, true /* include recent buckets */,
+//                                true, FAST /* dump_latency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_gauge_metrics());
+//    EXPECT_EQ(0, report.gauge_metrics().data_size());
+//    EXPECT_EQ(1, report.gauge_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.gauge_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000),
+//              report.gauge_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.gauge_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.gauge_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 9000000), dropEvent.drop_time_millis());
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
index f6245ac..e48f378 100644
--- a/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
+++ b/cmds/statsd/tests/metrics/ValueMetricProducer_test.cpp
@@ -79,4533 +79,4535 @@
     }
 }
 
-class ValueMetricProducerTestHelper {
-
- public:
-    static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
-        shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
-        event->write(tagId);
-        event->write(value);
-        event->write(value);
-        event->init();
-        return event;
-    }
-
-    static sp<ValueMetricProducer> createValueProducerNoConditions(
-            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-        UidMap uidMap;
-        SimpleAtomMatcher atomMatcher;
-        atomMatcher.set_atom_id(tagId);
-        sp<EventMatcherWizard> eventMatcherWizard =
-                new EventMatcherWizard({new SimpleLogMatchingTracker(
-                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-                kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                logEventMatcherIndex, eventMatcherWizard, tagId,
-                bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-        return valueProducer;
-    }
-
-    static sp<ValueMetricProducer> createValueProducerWithCondition(
-            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-        UidMap uidMap;
-        SimpleAtomMatcher atomMatcher;
-        atomMatcher.set_atom_id(tagId);
-        sp<EventMatcherWizard> eventMatcherWizard =
-                new EventMatcherWizard({new SimpleLogMatchingTracker(
-                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-        sp<ValueMetricProducer> valueProducer =
-                new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
-                                        eventMatcherWizard, tagId, bucketStartTimeNs,
-                                        bucketStartTimeNs, pullerManager);
-        valueProducer->mCondition = ConditionState::kFalse;
-        return valueProducer;
-    }
-
-    static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
-            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
-        UidMap uidMap;
-        SimpleAtomMatcher atomMatcher;
-        atomMatcher.set_atom_id(tagId);
-        sp<EventMatcherWizard> eventMatcherWizard =
-                new EventMatcherWizard({new SimpleLogMatchingTracker(
-                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-                kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
-                bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-        return valueProducer;
-    }
-
-    static sp<ValueMetricProducer> createValueProducerWithState(
-            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
-            vector<int32_t> slicedStateAtoms,
-            unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
-        UidMap uidMap;
-        SimpleAtomMatcher atomMatcher;
-        atomMatcher.set_atom_id(tagId);
-        sp<EventMatcherWizard> eventMatcherWizard =
-                new EventMatcherWizard({new SimpleLogMatchingTracker(
-                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-                kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
-                eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
-                {}, slicedStateAtoms, stateGroupMap);
-        return valueProducer;
-    }
-
-    static ValueMetric createMetric() {
-        ValueMetric metric;
-        metric.set_id(metricId);
-        metric.set_bucket(ONE_MINUTE);
-        metric.mutable_value_field()->set_field(tagId);
-        metric.mutable_value_field()->add_child()->set_field(2);
-        metric.set_max_pull_delay_sec(INT_MAX);
-        return metric;
-    }
-
-    static ValueMetric createMetricWithCondition() {
-        ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-        metric.set_condition(StringToId("SCREEN_ON"));
-        return metric;
-    }
-
-    static ValueMetric createMetricWithState(string state) {
-        ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-        metric.add_slice_by_state(StringToId(state));
-        return metric;
-    }
-};
-
-/*
- * Tests that the first bucket works correctly
- */
-TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    int64_t startTimeBase = 11;
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    // statsd started long ago.
-    // The metric starts in the middle of the bucket
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
-                                      22, pullerManager);
-
-    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
-    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
-    EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
-              valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
-    EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
-              valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
-}
-
-/*
- * Tests that the first bucket works correctly
- */
-TEST(ValueMetricProducerTest, TestFirstBucket) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    // statsd started long ago.
-    // The metric starts in the middle of the bucket
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, -1, 5,
-                                      600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
-
-    EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
-    EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
-}
-
-/*
- * Tests pulled atoms with no conditions
- */
-TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(tagId);
-    event->write(23);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(23, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(12, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-    EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event->write(tagId);
-    event->write(36);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(36, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(13, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-    EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
-    EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
-}
-
-TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initialize bucket.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                event->write(tagId);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Partial bucket.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-                event->write(tagId);
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    // First bucket ends.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-    event->write(tagId);
-    event->write(2);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
-
-    // Partial buckets created in 2nd bucket.
-    valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-
-    // One full bucket and one partial bucket.
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
-    EXPECT_EQ(2UL, buckets.size());
-    // Full bucket (2 - 1)
-    EXPECT_EQ(1, buckets[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
-    // Full bucket (5 - 3)
-    EXPECT_EQ(3, buckets[1].values[0].long_value);
-    // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
-    EXPECT_EQ(2, buckets[1].mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with filtering
- */
-TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    auto keyValue = atomMatcher.add_field_value_matcher();
-    keyValue->set_field(1);
-    keyValue->set_eq_int(3);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(3);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
-            kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
-            eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(3);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(4);
-    event->write(23);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // No new data seen, so data has been cleared.
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(8, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event->write(3);
-    event->write(36);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    // the base was reset
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(36, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
-    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with no conditions and take absolute value after reset
- */
-TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_use_absolute_value_on_reset(true);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(tagId);
-    event->write(10);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(10, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event->write(tagId);
-    event->write(36);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(36, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(26, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
-    EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-    EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
-}
-
-/*
- * Tests pulled atoms with no conditions and take zero value after reset
- */
-TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(tagId);
-    event->write(10);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(10, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event->write(tagId);
-    event->write(36);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(36, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(26, curInterval.value.long_value);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
-}
-
-/*
- * Test pulled event with non sliced condition.
- */
-TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-                event->write(tagId);
-                event->write(130);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-                event->write(tagId);
-                event->write(180);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    // startUpdated:false sum:0 start:100
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(1);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(110, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(10, curInterval.value.long_value);
-
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(20, curInterval.value.long_value);
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-
-    valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
-}
-
-TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
-    valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
-    event2->write(1);
-    event2->write(10);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-
-    // Next value should create a new bucket.
-    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
-    event3->write(1);
-    event3->write(10);
-    event3->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
-}
-
-TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Return(true))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(100);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
-    valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(tagId);
-    event->write(150);
-    event->init();
-    allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-    EXPECT_EQ(20L,
-              valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
-                                    {150, bucketSizeNs - 150});
-}
-
-TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_split_bucket_for_app_upgrade(false);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(100);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-
-    valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
-    EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
-}
-
-TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
-    EXPECT_FALSE(valueProducer->mCondition);
-
-    valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
-    // Expect one full buckets already done and starting a partial bucket.
-    EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
-    EXPECT_EQ(bucketStartTimeNs,
-              valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
-                                    {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
-    EXPECT_FALSE(valueProducer->mCondition);
-}
-
-TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(20);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(30, curInterval.value.long_value);
-
-    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-    valueProducer.mCondition = ConditionState::kFalse;
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has 1 slice
-    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
-
-    valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(20);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(20, curInterval.value.long_value);
-
-    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
-    event3->write(1);
-    event3->write(30);
-    event3->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(50, curInterval.value.long_value);
-
-    valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
-    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
-    event4->write(1);
-    event4->write(40);
-    event4->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(50, curInterval.value.long_value);
-
-    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
-}
-
-TEST(ValueMetricProducerTest, TestAnomalyDetection) {
-    sp<AlarmMonitor> alarmMonitor;
-    Alert alert;
-    alert.set_id(101);
-    alert.set_metric_id(metricId);
-    alert.set_trigger_if_sum_gt(130);
-    alert.set_num_buckets(2);
-    const int32_t refPeriodSec = 3;
-    alert.set_refractory_period_secs(refPeriodSec);
-
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
-                                      logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
-                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
-
-    sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
-
-
-    shared_ptr<LogEvent> event1
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
-    event1->write(161);
-    event1->write(10); // value of interest
-    event1->init();
-    shared_ptr<LogEvent> event2
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
-    event2->write(162);
-    event2->write(20); // value of interest
-    event2->init();
-    shared_ptr<LogEvent> event3
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
-    event3->write(163);
-    event3->write(130); // value of interest
-    event3->init();
-    shared_ptr<LogEvent> event4
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
-    event4->write(35);
-    event4->write(1); // value of interest
-    event4->init();
-    shared_ptr<LogEvent> event5
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
-    event5->write(45);
-    event5->write(150); // value of interest
-    event5->init();
-    shared_ptr<LogEvent> event6
-            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
-    event6->write(25);
-    event6->write(160); // value of interest
-    event6->init();
-
-    // Two events in bucket #0.
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-    // Value sum == 30 <= 130.
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
-    // One event in bucket #2. No alarm as bucket #0 is trashed out.
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-    // Value sum == 130 <= 130.
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
-
-    // Three events in bucket #3.
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-    // Anomaly at event 4 since Value sum == 131 > 130!
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
-    // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
-    // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
-    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
-            std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
-}
-
-// Test value metric no condition, the pull on bucket boundary come in time and too late
-TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    // pull 1
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(11);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-
-    // startUpdated:true sum:0 start:11
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(11, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    // pull 2 at correct time
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event->write(tagId);
-    event->write(23);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    // tartUpdated:false sum:12
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(23, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-
-    // pull 3 come late.
-    // The previous bucket gets closed with error. (Has start value 23, no ending)
-    // Another bucket gets closed with error. (No start, but ending with 36)
-    // The new bucket is back to normal.
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
-    event->write(tagId);
-    event->write(36);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    // startUpdated:false sum:12
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(36, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
- * was delivered late.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // condition becomes false
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    // pull on bucket boundary come late, condition change happens before it
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-
-    // Now the alarm is delivered.
-    // since the condition turned to off before this pull finish, it has no effect
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-}
-
-/*
- * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
- * change to false, and then true again. This is due to alarm delivered late.
- */
-TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // condition becomes false
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // condition becomes true again
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
-                event->write(tagId);
-                event->write(130);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    // startUpdated:false sum:0 start:100
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    // pull on bucket boundary come late, condition change happens before it
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    // condition changed to true again, before the pull alarm is delivered
-    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(130, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    // Now the alarm is delivered, but it is considered late, the data will be used
-    // for the new bucket since it was just pulled.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
-
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(140, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(10, curInterval.value.long_value);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
-
-    allData.clear();
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
-                                    {bucketSizeNs - 8, bucketSizeNs - 24});
-}
-
-TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_aggregation_type(ValueMetric::MIN);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(20);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-
-    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_aggregation_type(ValueMetric::MAX);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(20);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(20, curInterval.value.long_value);
-
-    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-    /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
-    /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
-    /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
-}
-
-TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_aggregation_type(ValueMetric::AVG);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(15);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval;
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(1, curInterval.sampleSize);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(25, curInterval.value.long_value);
-    EXPECT_EQ(2, curInterval.sampleSize);
-
-    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-
-    EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
-                         12.5) < epsilon);
-}
-
-TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_aggregation_type(ValueMetric::SUM);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-    event2->write(1);
-    event2->write(15);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(10, curInterval.value.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(25, curInterval.value.long_value);
-
-    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_aggregation_type(ValueMetric::MIN);
-    metric.set_use_diff(true);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-    event2->write(1);
-    event2->write(15);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(10, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(5, curInterval.value.long_value);
-
-    // no change in data.
-    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-    event3->write(1);
-    event3->write(15);
-    event3->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(15, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
-    event4->write(1);
-    event4->write(15);
-    event4->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(15, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
-    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_value_field()->add_child()->set_field(3);
-    metric.set_aggregation_type(ValueMetric::MIN);
-    metric.set_use_diff(true);
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
-                                      pullerManager);
-
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-    event1->write(1);
-    event1->write(10);
-    event1->write(20);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-    event2->write(1);
-    event2->write(15);
-    event2->write(22);
-    event2->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(10, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(20, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(5, curInterval.value.long_value);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(2, curInterval.value.long_value);
-
-    // no change in first value field
-    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
-    event3->write(1);
-    event3->write(15);
-    event3->write(25);
-    event3->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(15, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(25, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
-    event4->write(1);
-    event4->write(15);
-    event4->write(29);
-    event4->init();
-    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
-    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(15, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
-    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(29, curBaseInfo.base.long_value);
-    EXPECT_EQ(true, curInterval.hasValue);
-
-    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
-
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
-    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
-    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
-
-    EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
-    EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
-    EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
-    EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
-    EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
-
-    EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
-    EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
-    EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
-}
-
-/*
- * Tests zero default base.
- */
-TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-    metric.set_use_zero_default_base(true);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(1);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto iter = valueProducer->mCurrentSlicedBucket.begin();
-    auto& interval1 = iter->second[0];
-    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
-    auto& baseInfo1 = iterBase->second[0];
-    EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(3, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    vector<shared_ptr<LogEvent>> allData;
-
-    allData.clear();
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event1->write(2);
-    event1->write(4);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(11);
-    event2->init();
-    allData.push_back(event1);
-    allData.push_back(event2);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(11, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(8, interval1.value.long_value);
-
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
-        if (it != iter) {
-            break;
-        }
-    }
-    auto itBase = valueProducer->mCurrentBaseInfo.begin();
-    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
-        if (itBase != iterBase) {
-            break;
-        }
-    }
-    EXPECT_TRUE(it != iter);
-    EXPECT_TRUE(itBase != iterBase);
-    auto& interval2 = it->second[0];
-    auto& baseInfo2 = itBase->second[0];
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(4, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_EQ(4, interval2.value.long_value);
-
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-    auto iterator = valueProducer->mPastBuckets.begin();
-    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
-    EXPECT_EQ(8, iterator->second[0].values[0].long_value);
-    iterator++;
-    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
-    EXPECT_EQ(4, iterator->second[0].values[0].long_value);
-}
-
-/*
- * Tests using zero default base with failed pull.
- */
-TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-    metric.set_use_zero_default_base(true);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(1);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    auto& interval1 = it->second[0];
-    auto& baseInfo1 =
-            valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(3, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    vector<shared_ptr<LogEvent>> allData;
-
-    allData.clear();
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event1->write(2);
-    event1->write(4);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(11);
-    event2->init();
-    allData.push_back(event1);
-    allData.push_back(event2);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(11, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(8, interval1.value.long_value);
-
-    auto it2 = valueProducer->mCurrentSlicedBucket.begin();
-    for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
-        if (it2 != it) {
-            break;
-        }
-    }
-    // auto itBase = valueProducer->mCurrentBaseInfo.begin();
-    // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
-    //     if (itBase != iterBase) {
-    //         break;
-    //     }
-    // }
-    EXPECT_TRUE(it2 != it);
-    // EXPECT_TRUE(itBase != iterBase);
-    auto& interval2 = it2->second[0];
-    auto& baseInfo2 =
-            valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
-    EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(4, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_EQ(4, interval2.value.long_value);
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-
-    // next pull somehow did not happen, skip to end of bucket 3
-    allData.clear();
-    event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event1->write(2);
-    event1->write(5);
-    event1->init();
-    allData.push_back(event1);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(5, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-
-    allData.clear();
-    event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
-    event1->write(2);
-    event1->write(13);
-    event1->init();
-    allData.push_back(event1);
-    event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
-    event2->write(1);
-    event2->write(5);
-    event2->init();
-    allData.push_back(event2);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
-
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
-    interval1 = it->second[0];
-    interval2 = it2->second[0];
-    baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
-    baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
-
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(5, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(5, interval1.value.long_value);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(13, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_EQ(8, interval2.value.long_value);
-
-    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
-}
-
-/*
- * Tests trim unused dimension key if no new data is seen in an entire bucket.
- */
-TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(1);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto iter = valueProducer->mCurrentSlicedBucket.begin();
-    auto& interval1 = iter->second[0];
-    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
-    auto& baseInfo1 = iterBase->second[0];
-    EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(3, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    vector<shared_ptr<LogEvent>> allData;
-
-    allData.clear();
-    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event1->write(2);
-    event1->write(4);
-    event1->init();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(11);
-    event2->init();
-    allData.push_back(event1);
-    allData.push_back(event2);
-
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(true, baseInfo1.hasBase);
-    EXPECT_EQ(11, baseInfo1.base.long_value);
-    EXPECT_EQ(false, interval1.hasValue);
-    EXPECT_EQ(8, interval1.value.long_value);
-    EXPECT_FALSE(interval1.seenNewData);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
-        if (it != iter) {
-            break;
-        }
-    }
-    auto itBase = valueProducer->mCurrentBaseInfo.begin();
-    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
-        if (itBase != iterBase) {
-            break;
-        }
-    }
-    EXPECT_TRUE(it != iter);
-    EXPECT_TRUE(itBase != iterBase);
-    auto& interval2 = it->second[0];
-    auto& baseInfo2 = itBase->second[0];
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(4, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_FALSE(interval2.seenNewData);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
-    // next pull somehow did not happen, skip to end of bucket 3
-    allData.clear();
-    event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
-    event1->write(2);
-    event1->write(5);
-    event1->init();
-    allData.push_back(event1);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
-    // Only one interval left. One was trimmed.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(5, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_FALSE(interval2.seenNewData);
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
-
-    allData.clear();
-    event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
-    event1->write(2);
-    event1->write(14);
-    event1->init();
-    allData.push_back(event1);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
-
-    interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, baseInfo2.hasBase);
-    EXPECT_EQ(14, baseInfo2.base.long_value);
-    EXPECT_EQ(false, interval2.hasValue);
-    EXPECT_FALSE(interval2.seenNewData);
-    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
-    auto iterator = valueProducer->mPastBuckets.begin();
-    EXPECT_EQ(9, iterator->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
-    iterator++;
-    EXPECT_EQ(8, iterator->second[0].values[0].long_value);
-    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    // Used by onConditionChanged.
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    vector<shared_ptr<LogEvent>> allData;
-    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Return(false));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
-
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(50);
-                event->init();
-                data->push_back(event);
-                return false;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Don't directly set mCondition; the real code never does that. Go through regular code path
-    // to avoid unexpected behaviors.
-    // valueProducer->mCondition = ConditionState::kTrue;
-    valueProducer->onConditionChanged(true, bucketStartTimeNs);
-
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_condition(StringToId("SCREEN_ON"));
-    metric.set_max_pull_delay_sec(0);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    // Max delay is set to 0 so pull will exceed max delay.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-}
-
-TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucket2StartTimeNs,
-                                      bucket2StartTimeNs, pullerManager);
-    valueProducer.mCondition = ConditionState::kFalse;
-
-    // Event should be skipped since it is from previous bucket.
-    // Pull should not be called.
-    valueProducer.onConditionChanged(true, bucketStartTimeNs);
-    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
-}
-
-TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                event->write(tagId);
-                event->write(100);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->mCondition = ConditionState::kFalse;
-    valueProducer->mHasGlobalBase = false;
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
-    valueProducer->mHasGlobalBase = true;
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(100, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-}
-
-/*
- * Tests that a bucket is marked invalid when a condition change pull fails.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Return(false))
-            // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(130);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->mCondition = ConditionState::kTrue;
-
-    // Bucket start.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event->write(1);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-
-    // This will fail and should invalidate the whole bucket since we do not have all the data
-    // needed to compute the metric value when the screen was on.
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
-    // Bucket end.
-    allData.clear();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(140);
-    event2->init();
-    allData.push_back(event2);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    // Contains base from last pull which was successful.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(140, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
-                                FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the guardrail is hit.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-    metric.set_condition(StringToId("SCREEN_ON"));
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                for (int i = 0; i < 2000; i++) {
-                    shared_ptr<LogEvent> event =
-                            make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                    event->write(i);
-                    event->write(i);
-                    event->init();
-                    data->push_back(event);
-                }
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
-    EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
-
-    // Bucket 2 start.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(1);
-    event->write(10);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // First bucket added to mSkippedBuckets after flush.
-    EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
-                                true, FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the bucket's initial pull fails.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(130);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->mCondition = ConditionState::kTrue;
-
-    // Bucket start.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event->write(1);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
-
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
-    // Bucket end.
-    allData.clear();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(140);
-    event2->init();
-    allData.push_back(event2);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    // Contains base from last pull which was successful.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(140, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
-                                true, FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
-}
-
-/*
- * Tests that a bucket is marked invalid when the bucket's final pull fails
- * (i.e. failed pull on bucket boundary).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(120);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Second onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
-                event->write(tagId);
-                event->write(130);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->mCondition = ConditionState::kTrue;
-
-    // Bucket start.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-    event->write(1);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
-
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
-
-    // Bucket end.
-    allData.clear();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event2->write(1);
-    event2->write(140);
-    event2->init();
-    allData.push_back(event2);
-    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-
-    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
-
-    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
-    // Last pull failed so base has been reset.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
-                                true, FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Start bucket.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    // Bucket 2 start.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(110);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-
-    // Bucket 3 empty.
-    allData.clear();
-    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
-    event2->init();
-    allData.push_back(event2);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
-    // Data has been trimmed.
-    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    // Empty pull.
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(2);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval& curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    // End of bucket
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    // Data is empty, base should be reset.
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(5, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-
-    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
-}
-
-TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-    metric.set_condition(StringToId("SCREEN_ON"));
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First onConditionChanged
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(1);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-
-    // End of bucket
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(2);
-    event->write(2);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // Key 1 should be reset since in not present in the most pull.
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    auto iterator = valueProducer->mCurrentSlicedBucket.begin();
-    auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
-    EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
-    EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
-    EXPECT_EQ(false, iterator->second[0].hasValue);
-    iterator++;
-    baseInfoIter++;
-    EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
-    EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
-    EXPECT_EQ(false, iterator->second[0].hasValue);
-
-    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
-}
-
-TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initialization.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-                return true;
-            }))
-            // notifyAppUpgrade.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(
-                        bucketStartTimeNs + bucketSizeNs / 2, 10));
-                return true;
-            }));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-
-    valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
-    ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
-    valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
-    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
-}
-
-TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Second onConditionChanged.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
-                return true;
-            }))
-            // Third onConditionChanged.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kUnknown;
-
-    valueProducer->onConditionChanged(false, bucketStartTimeNs);
-    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
-    // End of first bucket
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
-    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
-
-    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curBaseInfo.hasBase);
-    EXPECT_EQ(5, curBaseInfo.base.long_value);
-    EXPECT_EQ(false, curInterval.hasValue);
-
-    valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
-
-    // Bucket should have been completed.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
-}
-
-TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-
-    allData.clear();
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // Bucket should have been completed.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initialization.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
-
-    allData.clear();
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // Bucket should have been completed.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initialization.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-                return true;
-            }))
-            // notifyAppUpgrade.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
-
-    // Bucket should have been completed.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First on condition changed.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-                return true;
-            }))
-            // Second on condition changed.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
-
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(2, curInterval.value.long_value);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
-
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
-}
-
-// TODO: b/145705635 fix or delete this test
-TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First condition change.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
-                return true;
-            }))
-            // 2nd condition change.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
-                return true;
-            }))
-            // 3rd condition change.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
-    valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
-
-    allData.clear();
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
-    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
-
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
-    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
-
-    allData.clear();
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // There was not global base available so all buckets are invalid.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initial pull.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(1);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
-                               FAST, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    // Bucket is invalid since we did not pull when dump report was called.
-    EXPECT_EQ(0, report.value_metrics().data_size());
-}
-
-TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initial pull.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(1);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.clear();
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
-    event->write(tagId);
-    event->write(2);
-    event->write(2);
-    event->init();
-    allData.push_back(event);
-    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
-                               &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    // Previous bucket is part of the report.
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
-}
-
-TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-
-    UidMap uidMap;
-    SimpleAtomMatcher atomMatcher;
-    atomMatcher.set_atom_id(tagId);
-    sp<EventMatcherWizard> eventMatcherWizard =
-            new EventMatcherWizard({new SimpleLogMatchingTracker(
-                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
-    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
-    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
-
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Initial pull.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(tagId);
-                event->write(1);
-                event->write(1);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write(tagId);
-                event->write(3);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
-                                      eventMatcherWizard, tagId, bucketStartTimeNs,
-                                      bucketStartTimeNs, pullerManager);
-
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
-                               NO_TIME_CONSTRAINTS, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
-    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
-
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
-
-    // Bucket should have been completed.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-                return true;
-            }))
-            // condition becomes false
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
-                return true;
-            }));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
-    // has one slice
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(true, curInterval.hasValue);
-    EXPECT_EQ(20, curInterval.value.long_value);
-
-    // Now the alarm is delivered. Condition is off though.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
-    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-                return true;
-            }));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-
-    // Now the alarm is delivered. Condition is off though.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
-    ValueMetricProducer::Interval curInterval =
-            valueProducer->mCurrentSlicedBucket.begin()->second[0];
-    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
-    EXPECT_EQ(false, curBaseInfo.hasBase);
-    EXPECT_EQ(false, curInterval.hasValue);
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    // Now the alarm is delivered. Condition is off though.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // Condition was always false.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    metric.set_use_diff(false);
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // condition becomes true
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                data->push_back(
-                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
-                return true;
-            }))
-            .WillOnce(Return(false));
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-    valueProducer->mCondition = ConditionState::kFalse;
-
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
-
-    // Now the alarm is delivered. Condition is off though.
-    vector<shared_ptr<LogEvent>> allData;
-    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
-    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
-
-    // No buckets, we had a failure.
-    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
-}
-
-/*
- * Test that DUMP_REPORT_REQUESTED dump reason is logged.
- *
- * For the bucket to be marked invalid during a dump report requested,
- * three things must be true:
- * - we want to include the current partial bucket
- * - we need a pull (metric is pulled and condition is true)
- * - the dump latency must be FAST
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
-                                FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
- * change event (i.e. the condition change occurs in the wrong bucket).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
-    // Bucket boundary pull.
-    vector<shared_ptr<LogEvent>> allData;
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-    event->write("field1");
-    event->write(15);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
-    // Late condition change event.
-    valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
- * event (i.e. the accumulate events call occurs in the wrong bucket).
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
-                event->write("field1");
-                event->write(15);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
-    // Bucket boundary pull.
-    vector<shared_ptr<LogEvent>> allData;
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-    event->write("field1");
-    event->write(15);
-    event->init();
-    allData.push_back(event);
-    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
-    allData.clear();
-    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
-    event->write("field1");
-    event->write(20);
-    event->init();
-    allData.push_back(event);
-
-    // Late accumulateEvents event.
-    valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(1, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
- * when a metric is initialized.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
-                event->write("field1");
-                event->write(15);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
-                                                                                     metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
-    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that PULL_FAILED dump reason is logged due to a pull failure in
- * #pullAndMatchEventsLocked.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested, pull fails.
-            .WillOnce(Return(false));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
-    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
- * skips over more than one bucket.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event =
-                        make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1000);
-                event->write("field1");
-                event->write(15);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
-    // Condition change event that skips forward by three buckets.
-    valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
- * is smaller than the "min_bucket_size_nanos" specified in the metric config.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-    metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event =
-                        make_shared<LogEvent>(tagId, bucketStartTimeNs + 9000000);
-                event->write("field1");
-                event->write(15);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
-    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test multiple bucket drop events in the same bucket.
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // Condition change to true.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
-                                                                                     metric);
-
-    // Condition change event.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
-    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
-                                FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(1);
-    EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
-}
-
-/*
- * Test that the number of logged bucket drop events is capped at the maximum.
- * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
- */
-TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // First condition change event.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                for (int i = 0; i < 2000; i++) {
-                    shared_ptr<LogEvent> event =
-                            make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
-                    event->write(i);
-                    event->write(i);
-                    event->init();
-                    data->push_back(event);
-                }
-                return true;
-            }))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Return(false))
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
-                event->write("field1");
-                event->write(10);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
-                                                                                     metric);
-
-    // First condition change event causes guardrail to be reached.
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
-
-    // 2-10 condition change events result in failed pulls.
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
-    valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
-
-    // Condition change event 11
-    valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
-
-    // Check dump report.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
-    // Because we already have 10 dump events in the current bucket,
-    // this case should not be added to the list of dump events.
-    valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
-                                FAST /* dumpLatency */, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(0, report.value_metrics().data_size());
-    EXPECT_EQ(1, report.value_metrics().skipped_size());
-
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
-              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
-    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
-              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
-    EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
-
-    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
-    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(1);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(2);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(3);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(4);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(5);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(6);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(7);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(8);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
-
-    dropEvent = report.value_metrics().skipped(0).drop_event(9);
-    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
-    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
-}
-
-/*
- * Test metric with a simple sliced state
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedState) {
-    // Set up ValueMetricProducer.
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // ValueMetricProducer initialized.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write("field1");
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
-                event->write("field1");
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to OFF.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("field1");
-                event->write(9);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-                event->write("field1");
-                event->write(21);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(30);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithState(
-                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
-
-    // Set up StateManager and check that StateTrackers are initialized.
-    StateManager::getInstance().clear();
-    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
-    // Bucket status after metric initialized.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(3, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after screen state change kStateUnknown->ON.
-    auto screenEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(5, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Bucket status after screen state change ON->OFF.
-    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                                bucketStartTimeNs + 10);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(9, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, ON}
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(4, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    it++;
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Bucket status after screen state change OFF->ON.
-    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-                                                bucketStartTimeNs + 15);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(21, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, OFF}
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(12, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, ON}
-    it++;
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(4, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    it++;
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Start dump report and check output.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(3, report.value_metrics().data_size());
-
-    auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-
-    data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
-    EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
-
-    data = report.value_metrics().data(2);
-    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
-    EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
-}
-
-/*
- * Test metric with sliced state with map
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
-    // Set up ValueMetricProducer.
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // ValueMetricProducer initialized.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write("field1");
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to ON.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
-                event->write("field1");
-                event->write(5);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to VR.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
-                event->write("field1");
-                event->write(9);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Screen state change to OFF.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
-                event->write("field1");
-                event->write(21);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report requested.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
-                event->write("field1");
-                event->write(30);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    const StateMap& stateMap = CreateScreenStateOnOffMap();
-    const StateMap_StateGroup screenOnGroup = stateMap.group(0);
-    const StateMap_StateGroup screenOffGroup = stateMap.group(1);
-
-    unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
-    for (auto group : stateMap.group()) {
-        for (auto value : group.value()) {
-            stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
-        }
-    }
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithState(
-                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
-
-    // Set up StateManager and check that StateTrackers are initialized.
-    StateManager::getInstance().clear();
-    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
-
-    // Bucket status after metric initialized.
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(3, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, {}}
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after screen state change kStateUnknown->ON.
-    auto screenEvent = CreateScreenStateChangedEvent(
-            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(5, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Bucket status after screen state change ON->VR (also ON).
-    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
-                                                bucketStartTimeNs + 10);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(9, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, ON GROUP}
-    EXPECT_EQ(screenOnGroup.group_id(),
-              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(4, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    it++;
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Bucket status after screen state change VR->OFF.
-    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
-                                                bucketStartTimeNs + 15);
-    StateManager::getInstance().onLogEvent(*screenEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(21, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{}, ON GROUP}
-    EXPECT_EQ(screenOnGroup.group_id(),
-              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(16, it->second[0].value.long_value);
-    // Value for dimension, state key {{}, kStateUnknown}
-    it++;
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Start dump report and check output.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(3, report.value_metrics().data_size());
-
-    auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-
-    data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
-    EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
-
-    data = report.value_metrics().data(2);
-    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
-    EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
-    EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
-}
-
-/*
- * Test metric that slices by state with a primary field and has dimensions
- * - Increasing values
- * - Using diff
- * - Second field is value field
- */
-TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
-    // Set up ValueMetricProducer.
-    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
-    metric.mutable_dimensions_in_what()->set_field(tagId);
-    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
-
-    MetricStateLink* stateLink = metric.add_state_link();
-    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
-    auto fieldsInWhat = stateLink->mutable_fields_in_what();
-    *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
-    auto fieldsInState = stateLink->mutable_fields_in_state();
-    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(tagId, _))
-            // ValueMetricProducer initialized.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(2 /* uid */);
-                event->write(7);
-                event->init();
-                data->push_back(event);
-
-                event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
-                event->write(1 /* uid */);
-                event->write(3);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Uid 1 process state change from kStateUnknown -> Foreground
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-                event->write(1 /* uid */);
-                event->write(6);
-                event->init();
-                data->push_back(event);
-
-                // This event should be skipped.
-                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
-                event->write(2 /* uid */);
-                event->write(8);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Uid 2 process state change from kStateUnknown -> Background
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
-                event->write(2 /* uid */);
-                event->write(9);
-                event->init();
-                data->push_back(event);
-
-                // This event should be skipped.
-                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
-                event->write(1 /* uid */);
-                event->write(12);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Uid 1 process state change from Foreground -> Background
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
-                event->write(1 /* uid */);
-                event->write(13);
-                event->init();
-                data->push_back(event);
-
-                // This event should be skipped.
-                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
-                event->write(2 /* uid */);
-                event->write(11);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Uid 1 process state change from Background -> Foreground
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
-                event->write(1 /* uid */);
-                event->write(17);
-                event->init();
-                data->push_back(event);
-
-                // This event should be skipped.
-                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
-                event->write(2 /* uid */);
-                event->write(15);
-                event->init();
-                data->push_back(event);
-                return true;
-            }))
-            // Dump report pull.
-            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
-                event->write(2 /* uid */);
-                event->write(20);
-                event->init();
-                data->push_back(event);
-
-                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
-                event->write(1 /* uid */);
-                event->write(21);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    sp<ValueMetricProducer> valueProducer =
-            ValueMetricProducerTestHelper::createValueProducerWithState(
-                    pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
-
-    // Set up StateManager and check that StateTrackers are initialized.
-    StateManager::getInstance().clear();
-    StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
-    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
-    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
-
-    // Bucket status after metric initialized.
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {uid 1}.
-    auto it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(3, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{uid 1}, kStateUnknown}
-    // TODO(tsaichristine): test equality of state values key
-    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-    // Base for dimension key {uid 2}
-    it++;
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(7, itBase->second[0].base.long_value);
-    // Value for dimension, state key {{uid 2}, kStateUnknown}
-    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
-    auto uidProcessEvent = CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
-    StateManager::getInstance().onLogEvent(*uidProcessEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {uid 1}.
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(6, itBase->second[0].base.long_value);
-    // Value for key {uid 1, kStateUnknown}.
-    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(3, it->second[0].value.long_value);
-
-    // Base for dimension key {uid 2}
-    it++;
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(7, itBase->second[0].base.long_value);
-    // Value for key {uid 2, kStateUnknown}
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after uid 2 process state change kStateUnknown -> Background.
-    uidProcessEvent = CreateUidProcessStateChangedEvent(
-            2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
-    StateManager::getInstance().onLogEvent(*uidProcessEvent);
-    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
-    // Base for dimension key {uid 1}.
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(6, itBase->second[0].base.long_value);
-    // Value for key {uid 1, kStateUnknown}.
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(3, it->second[0].value.long_value);
-
-    // Base for dimension key {uid 2}
-    it++;
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(9, itBase->second[0].base.long_value);
-    // Value for key {uid 2, kStateUnknown}
-    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(2, it->second[0].value.long_value);
-
-    // Pull at end of first bucket.
-    vector<shared_ptr<LogEvent>> allData;
-    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-    event->write(1 /* uid */);
-    event->write(10);
-    event->init();
-    allData.push_back(event);
-
-    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
-    event->write(2 /* uid */);
-    event->write(15);
-    event->init();
-    allData.push_back(event);
-
-    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
-
-    // Buckets flushed after end of first bucket.
-    // None of the buckets should have a value.
-    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
-    // Base for dimension key {uid 2}.
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(15, itBase->second[0].base.long_value);
-    // Value for key {uid 2, BACKGROUND}.
-    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
-    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Base for dimension key {uid 1}
-    it++;
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(10, itBase->second[0].base.long_value);
-    // Value for key {uid 1, kStateUnknown}
-    EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
-    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Value for key {uid 1, FOREGROUND}
-    it++;
-    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
-    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Value for key {uid 2, kStateUnknown}
-    it++;
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after uid 1 process state change from Foreground -> Background.
-    uidProcessEvent = CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
-    StateManager::getInstance().onLogEvent(*uidProcessEvent);
-
-    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
-    // Base for dimension key {uid 2}.
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(15, itBase->second[0].base.long_value);
-    // Value for key {uid 2, BACKGROUND}.
-    EXPECT_EQ(false, it->second[0].hasValue);
-    // Base for dimension key {uid 1}
-    it++;
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(13, itBase->second[0].base.long_value);
-    // Value for key {uid 1, kStateUnknown}
-    EXPECT_EQ(false, it->second[0].hasValue);
-    // Value for key {uid 1, FOREGROUND}
-    it++;
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(3, it->second[0].value.long_value);
-    // Value for key {uid 2, kStateUnknown}
-    it++;
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Bucket status after uid 1 process state change Background->Foreground.
-    uidProcessEvent = CreateUidProcessStateChangedEvent(
-            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
-    StateManager::getInstance().onLogEvent(*uidProcessEvent);
-
-    EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
-    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
-    // Base for dimension key {uid 2}
-    it = valueProducer->mCurrentSlicedBucket.begin();
-    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(true, itBase->second[0].hasBase);
-    EXPECT_EQ(15, itBase->second[0].base.long_value);
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    it++;
-    EXPECT_EQ(false, it->second[0].hasValue);
-
-    // Base for dimension key {uid 1}
-    it++;
-    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
-    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
-    EXPECT_EQ(17, itBase->second[0].base.long_value);
-    // Value for key {uid 1, BACKGROUND}
-    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(4, it->second[0].value.long_value);
-    // Value for key {uid 1, FOREGROUND}
-    it++;
-    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
-    EXPECT_EQ(true, it->second[0].hasValue);
-    EXPECT_EQ(3, it->second[0].value.long_value);
-
-    // Start dump report and check output.
-    ProtoOutputStream output;
-    std::set<string> strSet;
-    valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
-                                NO_TIME_CONSTRAINTS, &strSet, &output);
-
-    StatsLogReport report = outputStreamToProto(&output);
-    EXPECT_TRUE(report.has_value_metrics());
-    EXPECT_EQ(5, report.value_metrics().data_size());
-
-    auto data = report.value_metrics().data(0);
-    EXPECT_EQ(1, data.bucket_info_size());
-    EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
-              data.slice_by_state(0).value());
-
-    data = report.value_metrics().data(1);
-    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
-    EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
-
-    data = report.value_metrics().data(2);
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
-              data.slice_by_state(0).value());
-    EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
-    EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
-
-    data = report.value_metrics().data(3);
-    EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
-    EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
-
-    data = report.value_metrics().data(4);
-    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
-    EXPECT_TRUE(data.slice_by_state(0).has_value());
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
-              data.slice_by_state(0).value());
-    EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
-    EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
-    EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+//class ValueMetricProducerTestHelper {
+//
+// public:
+//    static shared_ptr<LogEvent> createEvent(int64_t eventTimeNs, int64_t value) {
+//        shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, eventTimeNs);
+//        event->write(tagId);
+//        event->write(value);
+//        event->write(value);
+//        event->init();
+//        return event;
+//    }
+//
+//    static sp<ValueMetricProducer> createValueProducerNoConditions(
+//            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+//        UidMap uidMap;
+//        SimpleAtomMatcher atomMatcher;
+//        atomMatcher.set_atom_id(tagId);
+//        sp<EventMatcherWizard> eventMatcherWizard =
+//                new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+//                kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                logEventMatcherIndex, eventMatcherWizard, tagId,
+//                bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//        return valueProducer;
+//    }
+//
+//    static sp<ValueMetricProducer> createValueProducerWithCondition(
+//            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+//        UidMap uidMap;
+//        SimpleAtomMatcher atomMatcher;
+//        atomMatcher.set_atom_id(tagId);
+//        sp<EventMatcherWizard> eventMatcherWizard =
+//                new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//        sp<ValueMetricProducer> valueProducer =
+//                new ValueMetricProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+//                                        eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                        bucketStartTimeNs, pullerManager);
+//        valueProducer->mCondition = ConditionState::kFalse;
+//        return valueProducer;
+//    }
+//
+//    static sp<ValueMetricProducer> createValueProducerWithNoInitialCondition(
+//            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric) {
+//        UidMap uidMap;
+//        SimpleAtomMatcher atomMatcher;
+//        atomMatcher.set_atom_id(tagId);
+//        sp<EventMatcherWizard> eventMatcherWizard =
+//                new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+//                kConfigKey, metric, 1, wizard, logEventMatcherIndex, eventMatcherWizard, tagId,
+//                bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//        return valueProducer;
+//    }
+//
+//    static sp<ValueMetricProducer> createValueProducerWithState(
+//            sp<MockStatsPullerManager>& pullerManager, ValueMetric& metric,
+//            vector<int32_t> slicedStateAtoms,
+//            unordered_map<int, unordered_map<int, int64_t>> stateGroupMap) {
+//        UidMap uidMap;
+//        SimpleAtomMatcher atomMatcher;
+//        atomMatcher.set_atom_id(tagId);
+//        sp<EventMatcherWizard> eventMatcherWizard =
+//                new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                        atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//        sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//        EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//        EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//        sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+//                kConfigKey, metric, -1 /* no condition */, wizard, logEventMatcherIndex,
+//                eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager, {},
+//                {}, slicedStateAtoms, stateGroupMap);
+//        return valueProducer;
+//    }
+//
+//    static ValueMetric createMetric() {
+//        ValueMetric metric;
+//        metric.set_id(metricId);
+//        metric.set_bucket(ONE_MINUTE);
+//        metric.mutable_value_field()->set_field(tagId);
+//        metric.mutable_value_field()->add_child()->set_field(2);
+//        metric.set_max_pull_delay_sec(INT_MAX);
+//        return metric;
+//    }
+//
+//    static ValueMetric createMetricWithCondition() {
+//        ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//        metric.set_condition(StringToId("SCREEN_ON"));
+//        return metric;
+//    }
+//
+//    static ValueMetric createMetricWithState(string state) {
+//        ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//        metric.add_slice_by_state(StringToId(state));
+//        return metric;
+//    }
+//};
+//
+///*
+// * Tests that the first bucket works correctly
+// */
+//TEST(ValueMetricProducerTest, TestCalcPreviousBucketEndTime) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    int64_t startTimeBase = 11;
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    // statsd started long ago.
+//    // The metric starts in the middle of the bucket
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, -1, startTimeBase,
+//                                      22, pullerManager);
+//
+//    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+//    EXPECT_EQ(startTimeBase, valueProducer.calcPreviousBucketEndTime(60 * NS_PER_SEC + 10));
+//    EXPECT_EQ(60 * NS_PER_SEC + startTimeBase,
+//              valueProducer.calcPreviousBucketEndTime(2 * 60 * NS_PER_SEC));
+//    EXPECT_EQ(2 * 60 * NS_PER_SEC + startTimeBase,
+//              valueProducer.calcPreviousBucketEndTime(3 * 60 * NS_PER_SEC));
+//}
+//
+///*
+// * Tests that the first bucket works correctly
+// */
+//TEST(ValueMetricProducerTest, TestFirstBucket) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    // statsd started long ago.
+//    // The metric starts in the middle of the bucket
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, -1, 5,
+//                                      600 * NS_PER_SEC + NS_PER_SEC / 2, pullerManager);
+//
+//    EXPECT_EQ(600500000000, valueProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(10, valueProducer.mCurrentBucketNum);
+//    EXPECT_EQ(660000000005, valueProducer.getCurrentBucketEndTimeNs());
+//}
+//
+///*
+// * Tests pulled atoms with no conditions
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsNoCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(8, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(23);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(23, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(12, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//    EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(36);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(36, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(13, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(3UL, valueProducer->mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//    EXPECT_EQ(12, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+//    EXPECT_EQ(13, valueProducer->mPastBuckets.begin()->second[2].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[2].mConditionTrueNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPartialBucketCreated) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initialize bucket.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Partial bucket.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+//                event->write(tagId);
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    // First bucket ends.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+//    event->write(tagId);
+//    event->write(2);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** success */ true, bucket2StartTimeNs);
+//
+//    // Partial buckets created in 2nd bucket.
+//    valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+//
+//    // One full bucket and one partial bucket.
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    vector<ValueBucket> buckets = valueProducer->mPastBuckets.begin()->second;
+//    EXPECT_EQ(2UL, buckets.size());
+//    // Full bucket (2 - 1)
+//    EXPECT_EQ(1, buckets[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, buckets[0].mConditionTrueNs);
+//    // Full bucket (5 - 3)
+//    EXPECT_EQ(3, buckets[1].values[0].long_value);
+//    // partial bucket [bucket2StartTimeNs, bucket2StartTimeNs + 2]
+//    EXPECT_EQ(2, buckets[1].mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with filtering
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsWithFiltering) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    auto keyValue = atomMatcher.add_field_value_matcher();
+//    keyValue->set_field(1);
+//    keyValue->set_eq_int(3);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(3);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer = new ValueMetricProducer(
+//            kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard, logEventMatcherIndex,
+//            eventMatcherWizard, tagId, bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(3);
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(8, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(4);
+//    event->write(23);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // No new data seen, so data has been cleared.
+//    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(8, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event->write(3);
+//    event->write(36);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    // the base was reset
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(36, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(8, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with no conditions and take absolute value after reset
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsTakeAbsoluteValueOnReset) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_use_absolute_value_on_reset(true);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(10);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(10, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second.back().values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second.back().mConditionTrueNs);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(36);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(36, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(26, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(10, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//    EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[1].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[1].mConditionTrueNs);
+//}
+//
+///*
+// * Tests pulled atoms with no conditions and take zero value after reset
+// */
+//TEST(ValueMetricProducerTest, TestPulledEventsTakeZeroOnReset) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(false));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(10);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(10, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(36);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(36, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(26, curInterval.value.long_value);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(26, valueProducer->mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, valueProducer->mPastBuckets.begin()->second[0].mConditionTrueNs);
+//}
+//
+///*
+// * Test pulled event with non sliced condition.
+// */
+//TEST(ValueMetricProducerTest, TestEventsWithNonSlicedCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(130);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(180);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    // startUpdated:false sum:0 start:100
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(1);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(110, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs - 8});
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(20, curInterval.value.long_value);
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//
+//    valueProducer->onConditionChanged(true, bucket3StartTimeNs + 1);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10, 20}, {bucketSizeNs - 8, 1});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedEventsWithUpgrade) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+//    valueProducer.notifyAppUpgrade(bucketStartTimeNs + 150, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+//
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 59 * NS_PER_SEC);
+//    event2->write(1);
+//    event2->write(10);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucketStartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+//
+//    // Next value should create a new bucket.
+//    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 65 * NS_PER_SEC);
+//    event3->write(1);
+//    event3->write(10);
+//    event3->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucketStartTimeNs + bucketSizeNs, valueProducer.mCurrentBucketStartTimeNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledValueWithUpgrade) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Return(true))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 149);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(100);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+//    valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucket2StartTimeNs + 150, valueProducer.mCurrentBucketStartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20}, {150});
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(150);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer.onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    EXPECT_EQ(2UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucket3StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(20L,
+//              valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].values[0].long_value);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {20, 30},
+//                                    {150, bucketSizeNs - 150});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledWithAppUpgradeDisabled) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_split_bucket_for_app_upgrade(false);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(100);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//
+//    valueProducer.notifyAppUpgrade(bucket2StartTimeNs + 150, "ANY.APP", 1, 1);
+//    EXPECT_EQ(0UL, valueProducer.mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucket2StartTimeNs, valueProducer.mCurrentBucketStartTimeNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledValueWithUpgradeWhileConditionFalse) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+//
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs-100);
+//    EXPECT_FALSE(valueProducer->mCondition);
+//
+//    valueProducer->notifyAppUpgrade(bucket2StartTimeNs-50, "ANY.APP", 1, 1);
+//    // Expect one full buckets already done and starting a partial bucket.
+//    EXPECT_EQ(bucket2StartTimeNs-50, valueProducer->mCurrentBucketStartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY].size());
+//    EXPECT_EQ(bucketStartTimeNs,
+//              valueProducer->mPastBuckets[DEFAULT_METRIC_DIMENSION_KEY][0].mBucketStartNs);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20},
+//                                    {(bucket2StartTimeNs - 100) - (bucketStartTimeNs + 1)});
+//    EXPECT_FALSE(valueProducer->mCondition);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedEventsWithoutCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(20);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(30, curInterval.value.long_value);
+//
+//    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {30}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedEventsWithCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//    valueProducer.mCondition = ConditionState::kFalse;
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has 1 slice
+//    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+//
+//    valueProducer.onConditionChangedLocked(true, bucketStartTimeNs + 15);
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(20);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(20, curInterval.value.long_value);
+//
+//    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 30);
+//    event3->write(1);
+//    event3->write(30);
+//    event3->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(50, curInterval.value.long_value);
+//
+//    valueProducer.onConditionChangedLocked(false, bucketStartTimeNs + 35);
+//    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+//    event4->write(1);
+//    event4->write(40);
+//    event4->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(50, curInterval.value.long_value);
+//
+//    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {50}, {20});
+//}
+//
+//TEST(ValueMetricProducerTest, TestAnomalyDetection) {
+//    sp<AlarmMonitor> alarmMonitor;
+//    Alert alert;
+//    alert.set_id(101);
+//    alert.set_metric_id(metricId);
+//    alert.set_trigger_if_sum_gt(130);
+//    alert.set_num_buckets(2);
+//    const int32_t refPeriodSec = 3;
+//    alert.set_refractory_period_secs(refPeriodSec);
+//
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1 /*-1 meaning no condition*/, wizard,
+//                                      logEventMatcherIndex, eventMatcherWizard, -1 /*not pulled*/,
+//                                      bucketStartTimeNs, bucketStartTimeNs, pullerManager);
+//
+//    sp<AnomalyTracker> anomalyTracker = valueProducer.addAnomalyTracker(alert, alarmMonitor);
+//
+//
+//    shared_ptr<LogEvent> event1
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1 * NS_PER_SEC);
+//    event1->write(161);
+//    event1->write(10); // value of interest
+//    event1->init();
+//    shared_ptr<LogEvent> event2
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 + NS_PER_SEC);
+//    event2->write(162);
+//    event2->write(20); // value of interest
+//    event2->init();
+//    shared_ptr<LogEvent> event3
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 2 * bucketSizeNs + 1 * NS_PER_SEC);
+//    event3->write(163);
+//    event3->write(130); // value of interest
+//    event3->init();
+//    shared_ptr<LogEvent> event4
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 1 * NS_PER_SEC);
+//    event4->write(35);
+//    event4->write(1); // value of interest
+//    event4->init();
+//    shared_ptr<LogEvent> event5
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 2 * NS_PER_SEC);
+//    event5->write(45);
+//    event5->write(150); // value of interest
+//    event5->init();
+//    shared_ptr<LogEvent> event6
+//            = make_shared<LogEvent>(tagId, bucketStartTimeNs + 3 * bucketSizeNs + 10 * NS_PER_SEC);
+//    event6->write(25);
+//    event6->write(160); // value of interest
+//    event6->init();
+//
+//    // Two events in bucket #0.
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//    // Value sum == 30 <= 130.
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+//    // One event in bucket #2. No alarm as bucket #0 is trashed out.
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//    // Value sum == 130 <= 130.
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY), 0U);
+//
+//    // Three events in bucket #3.
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//    // Anomaly at event 4 since Value sum == 131 > 130!
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//            std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event5);
+//    // Event 5 is within 3 sec refractory period. Thus last alarm timestamp is still event4.
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//            std::ceil(1.0 * event4->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event6);
+//    // Anomaly at event 6 since Value sum == 160 > 130 and after refractory period.
+//    EXPECT_EQ(anomalyTracker->getRefractoryPeriodEndsSec(DEFAULT_METRIC_DIMENSION_KEY),
+//            std::ceil(1.0 * event6->GetElapsedTimestampNs() / NS_PER_SEC + refPeriodSec));
+//}
+//
+//// Test value metric no condition, the pull on bucket boundary come in time and too late
+//TEST(ValueMetricProducerTest, TestBucketBoundaryNoCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _)).WillOnce(Return(true));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    // pull 1
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(11);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//
+//    // startUpdated:true sum:0 start:11
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(11, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    // pull 2 at correct time
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(23);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    // tartUpdated:false sum:12
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(23, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+//
+//    // pull 3 come late.
+//    // The previous bucket gets closed with error. (Has start value 23, no ending)
+//    // Another bucket gets closed with error. (No start, but ending with 36)
+//    // The new bucket is back to normal.
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket6StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(36);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket6StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    // startUpdated:false sum:12
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(36, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {12}, {bucketSizeNs});
+//}
+//
+///*
+// * Test pulled event with non sliced condition. The pull on boundary come late because the alarm
+// * was delivered late.
+// */
+//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // condition becomes true
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // condition becomes false
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    // pull on bucket boundary come late, condition change happens before it
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//
+//    // Now the alarm is delivered.
+//    // since the condition turned to off before this pull finish, it has no effect
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+///*
+// * Test pulled event with non sliced condition. The pull on boundary come late, after the condition
+// * change to false, and then true again. This is due to alarm delivered late.
+// */
+//TEST(ValueMetricProducerTest, TestBucketBoundaryWithCondition2) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // condition becomes true
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // condition becomes false
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // condition becomes true again
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 25);
+//                event->write(tagId);
+//                event->write(130);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    // startUpdated:false sum:0 start:100
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    // pull on bucket boundary come late, condition change happens before it
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 1);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    // condition changed to true again, before the pull alarm is delivered
+//    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 25);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(130, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    // Now the alarm is delivered, but it is considered late, the data will be used
+//    // for the new bucket since it was just pulled.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 50, 140));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 50);
+//
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(140, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {bucketSizeNs - 8});
+//
+//    allData.clear();
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 160));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20, 30},
+//                                    {bucketSizeNs - 8, bucketSizeNs - 24});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedAggregateMin) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_aggregation_type(ValueMetric::MIN);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(20);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//
+//    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {10}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedAggregateMax) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_aggregation_type(ValueMetric::MAX);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(20);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(20, curInterval.value.long_value);
+//
+//    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+//    /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.size()); */
+//    /* EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size()); */
+//    /* EXPECT_EQ(20, valueProducer.mPastBuckets.begin()->second.back().values[0].long_value); */
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedAggregateAvg) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_aggregation_type(ValueMetric::AVG);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(15);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval;
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(1, curInterval.sampleSize);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(25, curInterval.value.long_value);
+//    EXPECT_EQ(2, curInterval.sampleSize);
+//
+//    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+//
+//    EXPECT_TRUE(std::abs(valueProducer.mPastBuckets.begin()->second.back().values[0].double_value -
+//                         12.5) < epsilon);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPushedAggregateSum) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_aggregation_type(ValueMetric::SUM);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//    event2->write(1);
+//    event2->write(15);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(10, curInterval.value.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(25, curInterval.value.long_value);
+//
+//    valueProducer.flushIfNeededLocked(bucket2StartTimeNs);
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {25}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutput) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_aggregation_type(ValueMetric::MIN);
+//    metric.set_use_diff(true);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+//    event2->write(1);
+//    event2->write(15);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(10, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(5, curInterval.value.long_value);
+//
+//    // no change in data.
+//    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+//    event3->write(1);
+//    event3->write(15);
+//    event3->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(15, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+//    event4->write(1);
+//    event4->write(15);
+//    event4->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(15, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second.size());
+//    assertPastBucketValuesSingleKey(valueProducer.mPastBuckets, {5}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestSkipZeroDiffOutputMultiValue) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_value_field()->add_child()->set_field(3);
+//    metric.set_aggregation_type(ValueMetric::MIN);
+//    metric.set_use_diff(true);
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, -1, bucketStartTimeNs, bucketStartTimeNs,
+//                                      pullerManager);
+//
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//    event1->write(1);
+//    event1->write(10);
+//    event1->write(20);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+//    event2->write(1);
+//    event2->write(15);
+//    event2->write(22);
+//    event2->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event1);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(10, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(20, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event2);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(5, curInterval.value.long_value);
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(2, curInterval.value.long_value);
+//
+//    // no change in first value field
+//    shared_ptr<LogEvent> event3 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 10);
+//    event3->write(1);
+//    event3->write(15);
+//    event3->write(25);
+//    event3->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event3);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(15, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(25, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    shared_ptr<LogEvent> event4 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 15);
+//    event4->write(1);
+//    event4->write(15);
+//    event4->write(29);
+//    event4->init();
+//    valueProducer.onMatchedLogEvent(1 /*log matcher index*/, *event4);
+//    EXPECT_EQ(1UL, valueProducer.mCurrentSlicedBucket.size());
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(15, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    curInterval = valueProducer.mCurrentSlicedBucket.begin()->second[1];
+//    curBaseInfo = valueProducer.mCurrentBaseInfo.begin()->second[1];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(29, curBaseInfo.base.long_value);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//
+//    valueProducer.flushIfNeededLocked(bucket3StartTimeNs);
+//
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.size());
+//    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second.size());
+//    EXPECT_EQ(2UL, valueProducer.mPastBuckets.begin()->second[0].values.size());
+//    EXPECT_EQ(1UL, valueProducer.mPastBuckets.begin()->second[1].values.size());
+//
+//    EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[0].mConditionTrueNs);
+//    EXPECT_EQ(5, valueProducer.mPastBuckets.begin()->second[0].values[0].long_value);
+//    EXPECT_EQ(0, valueProducer.mPastBuckets.begin()->second[0].valueIndex[0]);
+//    EXPECT_EQ(2, valueProducer.mPastBuckets.begin()->second[0].values[1].long_value);
+//    EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[0].valueIndex[1]);
+//
+//    EXPECT_EQ(bucketSizeNs, valueProducer.mPastBuckets.begin()->second[1].mConditionTrueNs);
+//    EXPECT_EQ(3, valueProducer.mPastBuckets.begin()->second[1].values[0].long_value);
+//    EXPECT_EQ(1, valueProducer.mPastBuckets.begin()->second[1].valueIndex[0]);
+//}
+//
+///*
+// * Tests zero default base.
+// */
+//TEST(ValueMetricProducerTest, TestUseZeroDefaultBase) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//    metric.set_use_zero_default_base(true);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(1);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto iter = valueProducer->mCurrentSlicedBucket.begin();
+//    auto& interval1 = iter->second[0];
+//    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+//    auto& baseInfo1 = iterBase->second[0];
+//    EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(3, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    vector<shared_ptr<LogEvent>> allData;
+//
+//    allData.clear();
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(4);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(11);
+//    event2->init();
+//    allData.push_back(event1);
+//    allData.push_back(event2);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(11, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(8, interval1.value.long_value);
+//
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
+//        if (it != iter) {
+//            break;
+//        }
+//    }
+//    auto itBase = valueProducer->mCurrentBaseInfo.begin();
+//    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+//        if (itBase != iterBase) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(it != iter);
+//    EXPECT_TRUE(itBase != iterBase);
+//    auto& interval2 = it->second[0];
+//    auto& baseInfo2 = itBase->second[0];
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(4, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_EQ(4, interval2.value.long_value);
+//
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//    auto iterator = valueProducer->mPastBuckets.begin();
+//    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+//    EXPECT_EQ(8, iterator->second[0].values[0].long_value);
+//    iterator++;
+//    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+//    EXPECT_EQ(4, iterator->second[0].values[0].long_value);
+//}
+//
+///*
+// * Tests using zero default base with failed pull.
+// */
+//TEST(ValueMetricProducerTest, TestUseZeroDefaultBaseWithPullFailures) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//    metric.set_use_zero_default_base(true);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(1);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    auto& interval1 = it->second[0];
+//    auto& baseInfo1 =
+//            valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(3, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    vector<shared_ptr<LogEvent>> allData;
+//
+//    allData.clear();
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(4);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(11);
+//    event2->init();
+//    allData.push_back(event1);
+//    allData.push_back(event2);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(11, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(8, interval1.value.long_value);
+//
+//    auto it2 = valueProducer->mCurrentSlicedBucket.begin();
+//    for (; it2 != valueProducer->mCurrentSlicedBucket.end(); it2++) {
+//        if (it2 != it) {
+//            break;
+//        }
+//    }
+//    // auto itBase = valueProducer->mCurrentBaseInfo.begin();
+//    // for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+//    //     if (itBase != iterBase) {
+//    //         break;
+//    //     }
+//    // }
+//    EXPECT_TRUE(it2 != it);
+//    // EXPECT_TRUE(itBase != iterBase);
+//    auto& interval2 = it2->second[0];
+//    auto& baseInfo2 =
+//            valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+//    EXPECT_EQ(2, it2->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(4, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_EQ(4, interval2.value.long_value);
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//
+//    // next pull somehow did not happen, skip to end of bucket 3
+//    allData.clear();
+//    event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(5);
+//    event1->init();
+//    allData.push_back(event1);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(5, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//
+//    allData.clear();
+//    event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(13);
+//    event1->init();
+//    allData.push_back(event1);
+//    event2 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(5);
+//    event2->init();
+//    allData.push_back(event2);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+//
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    it2 = std::next(valueProducer->mCurrentSlicedBucket.begin());
+//    interval1 = it->second[0];
+//    interval2 = it2->second[0];
+//    baseInfo1 = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat())->second[0];
+//    baseInfo2 = valueProducer->mCurrentBaseInfo.find(it2->first.getDimensionKeyInWhat())->second[0];
+//
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(5, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(5, interval1.value.long_value);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(13, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_EQ(8, interval2.value.long_value);
+//
+//    EXPECT_EQ(2UL, valueProducer->mPastBuckets.size());
+//}
+//
+///*
+// * Tests trim unused dimension key if no new data is seen in an entire bucket.
+// */
+//TEST(ValueMetricProducerTest, TestTrimUnusedDimensionKey) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(1);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto iter = valueProducer->mCurrentSlicedBucket.begin();
+//    auto& interval1 = iter->second[0];
+//    auto iterBase = valueProducer->mCurrentBaseInfo.begin();
+//    auto& baseInfo1 = iterBase->second[0];
+//    EXPECT_EQ(1, iter->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(3, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    vector<shared_ptr<LogEvent>> allData;
+//
+//    allData.clear();
+//    shared_ptr<LogEvent> event1 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(4);
+//    event1->init();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(11);
+//    event2->init();
+//    allData.push_back(event1);
+//    allData.push_back(event2);
+//
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(true, baseInfo1.hasBase);
+//    EXPECT_EQ(11, baseInfo1.base.long_value);
+//    EXPECT_EQ(false, interval1.hasValue);
+//    EXPECT_EQ(8, interval1.value.long_value);
+//    EXPECT_FALSE(interval1.seenNewData);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    for (; it != valueProducer->mCurrentSlicedBucket.end(); it++) {
+//        if (it != iter) {
+//            break;
+//        }
+//    }
+//    auto itBase = valueProducer->mCurrentBaseInfo.begin();
+//    for (; itBase != valueProducer->mCurrentBaseInfo.end(); it++) {
+//        if (itBase != iterBase) {
+//            break;
+//        }
+//    }
+//    EXPECT_TRUE(it != iter);
+//    EXPECT_TRUE(itBase != iterBase);
+//    auto& interval2 = it->second[0];
+//    auto& baseInfo2 = itBase->second[0];
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(4, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_FALSE(interval2.seenNewData);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+//    // next pull somehow did not happen, skip to end of bucket 3
+//    allData.clear();
+//    event1 = make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(5);
+//    event1->init();
+//    allData.push_back(event1);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket4StartTimeNs);
+//    // Only one interval left. One was trimmed.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(5, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_FALSE(interval2.seenNewData);
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {8}, {bucketSizeNs});
+//
+//    allData.clear();
+//    event1 = make_shared<LogEvent>(tagId, bucket5StartTimeNs + 1);
+//    event1->write(2);
+//    event1->write(14);
+//    event1->init();
+//    allData.push_back(event1);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket5StartTimeNs);
+//
+//    interval2 = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    baseInfo2 = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, baseInfo2.hasBase);
+//    EXPECT_EQ(14, baseInfo2.base.long_value);
+//    EXPECT_EQ(false, interval2.hasValue);
+//    EXPECT_FALSE(interval2.seenNewData);
+//    ASSERT_EQ(2UL, valueProducer->mPastBuckets.size());
+//    auto iterator = valueProducer->mPastBuckets.begin();
+//    EXPECT_EQ(9, iterator->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+//    iterator++;
+//    EXPECT_EQ(8, iterator->second[0].values[0].long_value);
+//    EXPECT_EQ(bucketSizeNs, iterator->second[0].mConditionTrueNs);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange_EndOfBucket) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    // Used by onConditionChanged.
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailAfterConditionChange) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Return(false));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo& curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 20);
+//
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullFailBeforeConditionChange) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(50);
+//                event->init();
+//                data->push_back(event);
+//                return false;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Don't directly set mCondition; the real code never does that. Go through regular code path
+//    // to avoid unexpected behaviors.
+//    // valueProducer->mCondition = ConditionState::kTrue;
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs);
+//
+//    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 1);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullDelayExceeded) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_condition(StringToId("SCREEN_ON"));
+//    metric.set_max_pull_delay_sec(0);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    // Max delay is set to 0 so pull will exceed max delay.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+//    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestResetBaseOnPullTooLate) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, 1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucket2StartTimeNs,
+//                                      bucket2StartTimeNs, pullerManager);
+//    valueProducer.mCondition = ConditionState::kFalse;
+//
+//    // Event should be skipped since it is from previous bucket.
+//    // Pull should not be called.
+//    valueProducer.onConditionChanged(true, bucketStartTimeNs);
+//    EXPECT_EQ(0UL, valueProducer.mCurrentSlicedBucket.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestBaseSetOnConditionChange) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                event->write(tagId);
+//                event->write(100);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->mCondition = ConditionState::kFalse;
+//    valueProducer->mHasGlobalBase = false;
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 1);
+//    valueProducer->mHasGlobalBase = true;
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(100, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when a condition change pull fails.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenOneConditionFailed) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Return(false))
+//            // Second onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(130);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->mCondition = ConditionState::kTrue;
+//
+//    // Bucket start.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event->write(1);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//
+//    // This will fail and should invalidate the whole bucket since we do not have all the data
+//    // needed to compute the metric value when the screen was on.
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+//    // Bucket end.
+//    allData.clear();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(140);
+//    event2->init();
+//    allData.push_back(event2);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    // Contains base from last pull which was successful.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(140, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 10, false /* include partial bucket */, true,
+//                                FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the guardrail is hit.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenGuardRailHit) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//    metric.set_condition(StringToId("SCREEN_ON"));
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                for (int i = 0; i < 2000; i++) {
+//                    shared_ptr<LogEvent> event =
+//                            make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                    event->write(i);
+//                    event->write(i);
+//                    event->init();
+//                    data->push_back(event);
+//                }
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 2);
+//    EXPECT_EQ(true, valueProducer->mCurrentBucketIsInvalid);
+//    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(0UL, valueProducer->mSkippedBuckets.size());
+//
+//    // Bucket 2 start.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(1);
+//    event->write(10);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // First bucket added to mSkippedBuckets after flush.
+//    EXPECT_EQ(1UL, valueProducer->mSkippedBuckets.size());
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+//                                true, FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::DIMENSION_GUARDRAIL_REACHED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the bucket's initial pull fails.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenInitialPullFailed) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Second onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(130);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->mCondition = ConditionState::kTrue;
+//
+//    // Bucket start.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event->write(1);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs);
+//
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+//    // Bucket end.
+//    allData.clear();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(140);
+//    event2->init();
+//    allData.push_back(event2);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    // Contains base from last pull which was successful.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(140, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+//                                true, FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 2), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Tests that a bucket is marked invalid when the bucket's final pull fails
+// * (i.e. failed pull on bucket boundary).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenLastPullFailed) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(120);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Second onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 8);
+//                event->write(tagId);
+//                event->write(130);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->mCondition = ConditionState::kTrue;
+//
+//    // Bucket start.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//    event->write(1);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs);
+//
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 2);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 3);
+//
+//    // Bucket end.
+//    allData.clear();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event2->write(1);
+//    event2->write(140);
+//    event2->init();
+//    allData.push_back(event2);
+//    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+//
+//    valueProducer->flushIfNeededLocked(bucket2StartTimeNs + 1);
+//
+//    EXPECT_EQ(0UL, valueProducer->mPastBuckets.size());
+//    // Last pull failed so base has been reset.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 10000, false /* include recent buckets */,
+//                                true, FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs), dropEvent.drop_time_millis());
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onDataPulled) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Start bucket.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    // Bucket 2 start.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(110);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//
+//    // Bucket 3 empty.
+//    allData.clear();
+//    shared_ptr<LogEvent> event2 = make_shared<LogEvent>(tagId, bucket3StartTimeNs + 1);
+//    event2->init();
+//    allData.push_back(event2);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket3StartTimeNs);
+//    // Data has been trimmed.
+//    EXPECT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onConditionChanged) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    // Empty pull.
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(false, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestEmptyDataResetsBase_onBucketBoundary) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(2);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 11);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 12);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval& curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    // End of bucket
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    // Data is empty, base should be reset.
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(5, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//
+//    EXPECT_EQ(1UL, valueProducer->mPastBuckets.size());
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {1}, {bucketSizeNs - 12 + 1});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPartialResetOnBucketBoundaries) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//    metric.set_condition(StringToId("SCREEN_ON"));
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First onConditionChanged
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(1);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//
+//    // End of bucket
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(2);
+//    event->write(2);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // Key 1 should be reset since in not present in the most pull.
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto iterator = valueProducer->mCurrentSlicedBucket.begin();
+//    auto baseInfoIter = valueProducer->mCurrentBaseInfo.begin();
+//    EXPECT_EQ(true, baseInfoIter->second[0].hasBase);
+//    EXPECT_EQ(2, baseInfoIter->second[0].base.long_value);
+//    EXPECT_EQ(false, iterator->second[0].hasValue);
+//    iterator++;
+//    baseInfoIter++;
+//    EXPECT_EQ(false, baseInfoIter->second[0].hasBase);
+//    EXPECT_EQ(1, baseInfoIter->second[0].base.long_value);
+//    EXPECT_EQ(false, iterator->second[0].hasValue);
+//
+//    EXPECT_EQ(true, valueProducer->mHasGlobalBase);
+//}
+//
+//TEST(ValueMetricProducerTest, TestFullBucketResetWhenLastBucketInvalid) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initialization.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+//                return true;
+//            }))
+//            // notifyAppUpgrade.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(
+//                        bucketStartTimeNs + bucketSizeNs / 2, 10));
+//                return true;
+//            }));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+//
+//    valueProducer->notifyAppUpgrade(bucketStartTimeNs + bucketSizeNs / 2, "com.foo", 10000, 1);
+//    ASSERT_EQ(1UL, valueProducer->mCurrentFullBucket.size());
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 1, 4));
+//    valueProducer->onDataPulled(allData, /** fails */ false, bucket3StartTimeNs + 1);
+//    ASSERT_EQ(0UL, valueProducer->mCurrentFullBucket.size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestBucketBoundariesOnConditionChange) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Second onConditionChanged.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 10, 5));
+//                return true;
+//            }))
+//            // Third onConditionChanged.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs + 10, 7));
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kUnknown;
+//
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs);
+//    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+//    // End of first bucket
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 4));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+//    ASSERT_EQ(0UL, valueProducer->mCurrentSlicedBucket.size());
+//
+//    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+//    ASSERT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curBaseInfo.hasBase);
+//    EXPECT_EQ(5, curBaseInfo.base.long_value);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//
+//    valueProducer->onConditionChanged(false, bucket3StartTimeNs + 10);
+//
+//    // Bucket should have been completed.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {bucketSizeNs - 10});
+//}
+//
+//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithoutDiff) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+//
+//    allData.clear();
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // Bucket should have been completed.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestLateOnDataPulledWithDiff) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initialization.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucketStartTimeNs + 30);
+//
+//    allData.clear();
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // Bucket should have been completed.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {19}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestBucketBoundariesOnAppUpgrade) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initialization.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+//                return true;
+//            }))
+//            // notifyAppUpgrade.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 2, 10));
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    valueProducer->notifyAppUpgrade(bucket2StartTimeNs + 2, "com.foo", 10000, 1);
+//
+//    // Bucket should have been completed.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {9}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestDataIsNotUpdatedWhenNoConditionChanged) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First on condition changed.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+//                return true;
+//            }))
+//            // Second on condition changed.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 3));
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 10);
+//
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    auto curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    auto curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(2, curInterval.value.long_value);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 1, 10));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 1);
+//
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {2}, {2});
+//}
+//
+//// TODO: b/145705635 fix or delete this test
+//TEST(ValueMetricProducerTest, TestBucketInvalidIfGlobalBaseIsNotSet) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First condition change.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs, 1));
+//                return true;
+//            }))
+//            // 2nd condition change.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+//                return true;
+//            }))
+//            // 3rd condition change.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 1));
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 3, 10));
+//    valueProducer->onDataPulled(allData, /** succeed */ false, bucketStartTimeNs + 3);
+//
+//    allData.clear();
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs, 20));
+//    valueProducer->onDataPulled(allData, /** succeed */ false, bucket2StartTimeNs);
+//
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs + 8);
+//    valueProducer->onConditionChanged(true, bucket2StartTimeNs + 10);
+//
+//    allData.clear();
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket3StartTimeNs, 30));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // There was not global base available so all buckets are invalid.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPullNeededFastDump) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initial pull.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(1);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+//                               FAST, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    // Bucket is invalid since we did not pull when dump report was called.
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//}
+//
+//TEST(ValueMetricProducerTest, TestFastDumpWithoutCurrentBucket) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initial pull.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(1);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.clear();
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 1);
+//    event->write(tagId);
+//    event->write(2);
+//    event->write(2);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer.onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer.onDumpReport(bucket4StartTimeNs, false /* include recent buckets */, true, FAST,
+//                               &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    // Previous bucket is part of the report.
+//    EXPECT_EQ(1, report.value_metrics().data_size());
+//    EXPECT_EQ(0, report.value_metrics().data(0).bucket_info(0).bucket_num());
+//}
+//
+//TEST(ValueMetricProducerTest, TestPullNeededNoTimeConstraints) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//
+//    UidMap uidMap;
+//    SimpleAtomMatcher atomMatcher;
+//    atomMatcher.set_atom_id(tagId);
+//    sp<EventMatcherWizard> eventMatcherWizard =
+//            new EventMatcherWizard({new SimpleLogMatchingTracker(
+//                    atomMatcherId, logEventMatcherIndex, atomMatcher, uidMap)});
+//    sp<MockConditionWizard> wizard = new NaggyMock<MockConditionWizard>();
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, RegisterReceiver(tagId, _, _, _)).WillOnce(Return());
+//    EXPECT_CALL(*pullerManager, UnRegisterReceiver(tagId, _)).WillRepeatedly(Return());
+//
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Initial pull.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(tagId);
+//                event->write(1);
+//                event->write(1);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write(tagId);
+//                event->write(3);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    ValueMetricProducer valueProducer(kConfigKey, metric, -1, wizard, logEventMatcherIndex,
+//                                      eventMatcherWizard, tagId, bucketStartTimeNs,
+//                                      bucketStartTimeNs, pullerManager);
+//
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer.onDumpReport(bucketStartTimeNs + 10, true /* include recent buckets */, true,
+//                               NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_EQ(1, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().data(0).bucket_info_size());
+//    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withoutCondition) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetric();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerNoConditions(pullerManager, metric);
+//
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 10));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs + 30);
+//
+//    // Bucket should have been completed.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {10}, {bucketSizeNs});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withMultipleConditionChanges) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // condition becomes true
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+//                return true;
+//            }))
+//            // condition becomes false
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 50, 20));
+//                return true;
+//            }));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+//    // has one slice
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(true, curInterval.hasValue);
+//    EXPECT_EQ(20, curInterval.value.long_value);
+//
+//    // Now the alarm is delivered. Condition is off though.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 110));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {20}, {50 - 8});
+//    curInterval = valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryTrue) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // condition becomes true
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+//                return true;
+//            }));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//
+//    // Now the alarm is delivered. Condition is off though.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {30}, {bucketSizeNs - 8});
+//    ValueMetricProducer::Interval curInterval =
+//            valueProducer->mCurrentSlicedBucket.begin()->second[0];
+//    ValueMetricProducer::BaseInfo curBaseInfo = valueProducer->mCurrentBaseInfo.begin()->second[0];
+//    EXPECT_EQ(false, curBaseInfo.hasBase);
+//    EXPECT_EQ(false, curInterval.hasValue);
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_bucketBoundaryFalse) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    // Now the alarm is delivered. Condition is off though.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // Condition was always false.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+//TEST(ValueMetricProducerTest, TestPulledData_noDiff_withFailure) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    metric.set_use_diff(false);
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // condition becomes true
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                data->push_back(
+//                        ValueMetricProducerTestHelper::createEvent(bucketStartTimeNs + 30, 10));
+//                return true;
+//            }))
+//            .WillOnce(Return(false));
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//    valueProducer->mCondition = ConditionState::kFalse;
+//
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 8);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 50);
+//
+//    // Now the alarm is delivered. Condition is off though.
+//    vector<shared_ptr<LogEvent>> allData;
+//    allData.push_back(ValueMetricProducerTestHelper::createEvent(bucket2StartTimeNs + 30, 30));
+//    valueProducer->onDataPulled(allData, /** succeed */ true, bucket2StartTimeNs);
+//
+//    // No buckets, we had a failure.
+//    assertPastBucketValuesSingleKey(valueProducer->mPastBuckets, {}, {});
+//}
+//
+///*
+// * Test that DUMP_REPORT_REQUESTED dump reason is logged.
+// *
+// * For the bucket to be marked invalid during a dump report requested,
+// * three things must be true:
+// * - we want to include the current partial bucket
+// * - we need a pull (metric is pulled and condition is true)
+// * - the dump latency must be FAST
+// */
+//
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenDumpReportRequested) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 20);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucketStartTimeNs + 40, true /* include recent buckets */, true,
+//                                FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 40), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late condition
+// * change event (i.e. the condition change occurs in the wrong bucket).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionEventWrongBucket) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+//    // Bucket boundary pull.
+//    vector<shared_ptr<LogEvent>> allData;
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+//    event->write("field1");
+//    event->write(15);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+//    // Late condition change event.
+//    valueProducer->onConditionChanged(false, bucket2StartTimeNs - 100);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(1, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that EVENT_IN_WRONG_BUCKET dump reason is logged for a late accumulate
+// * event (i.e. the accumulate events call occurs in the wrong bucket).
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenAccumulateEventWrongBucket) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 100);
+//                event->write("field1");
+//                event->write(15);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+//    // Bucket boundary pull.
+//    vector<shared_ptr<LogEvent>> allData;
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+//    event->write("field1");
+//    event->write(15);
+//    event->init();
+//    allData.push_back(event);
+//    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+//    allData.clear();
+//    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs - 100);
+//    event->write("field1");
+//    event->write(20);
+//    event->init();
+//    allData.push_back(event);
+//
+//    // Late accumulateEvents event.
+//    valueProducer->accumulateEvents(allData, bucket2StartTimeNs - 100, bucket2StartTimeNs - 100);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 100, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(1, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs + 100),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::EVENT_IN_WRONG_BUCKET, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs - 100), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that CONDITION_UNKNOWN dump reason is logged due to an unknown condition
+// * when a metric is initialized.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenConditionUnknown) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 100);
+//                event->write("field1");
+//                event->write(15);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+//                                                                                     metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+//    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that PULL_FAILED dump reason is logged due to a pull failure in
+// * #pullAndMatchEventsLocked.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenPullFailed) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested, pull fails.
+//            .WillOnce(Return(false));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    int64_t dumpReportTimeNs = bucketStartTimeNs + 10000;
+//    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that MULTIPLE_BUCKETS_SKIPPED dump reason is logged when a log event
+// * skips over more than one bucket.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestInvalidBucketWhenMultipleBucketsSkipped) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event =
+//                        make_shared<LogEvent>(tagId, bucket4StartTimeNs + 1000);
+//                event->write("field1");
+//                event->write(15);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+//    // Condition change event that skips forward by three buckets.
+//    valueProducer->onConditionChanged(false, bucket4StartTimeNs + 10);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket4StartTimeNs + 1000, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(bucket2StartTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::MULTIPLE_BUCKETS_SKIPPED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucket4StartTimeNs + 10), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that BUCKET_TOO_SMALL dump reason is logged when a flushed bucket size
+// * is smaller than the "min_bucket_size_nanos" specified in the metric config.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestBucketDropWhenBucketTooSmall) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//    metric.set_min_bucket_size_nanos(10000000000);  // 10 seconds
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event =
+//                        make_shared<LogEvent>(tagId, bucketStartTimeNs + 9000000);
+//                event->write("field1");
+//                event->write(15);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithCondition(pullerManager, metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    int64_t dumpReportTimeNs = bucketStartTimeNs + 9000000;
+//    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(1, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::BUCKET_TOO_SMALL, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test multiple bucket drop events in the same bucket.
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestMultipleBucketDropEvents) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // Condition change to true.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+//                                                                                     metric);
+//
+//    // Condition change event.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
+//    valueProducer->onDumpReport(dumpReportTimeNs, true /* include recent buckets */, true,
+//                                FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(2, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(1);
+//    EXPECT_EQ(BucketDropReason::DUMP_REPORT_REQUESTED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test that the number of logged bucket drop events is capped at the maximum.
+// * The maximum is currently 10 and is set in MetricProducer::maxDropEventsReached().
+// */
+//TEST(ValueMetricProducerTest_BucketDrop, TestMaxBucketDropEvents) {
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithCondition();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // First condition change event.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                for (int i = 0; i < 2000; i++) {
+//                    shared_ptr<LogEvent> event =
+//                            make_shared<LogEvent>(tagId, bucketStartTimeNs + 1);
+//                    event->write(i);
+//                    event->write(i);
+//                    event->init();
+//                    data->push_back(event);
+//                }
+//                return true;
+//            }))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Return(false))
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 220);
+//                event->write("field1");
+//                event->write(10);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithNoInitialCondition(pullerManager,
+//                                                                                     metric);
+//
+//    // First condition change event causes guardrail to be reached.
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 10);
+//
+//    // 2-10 condition change events result in failed pulls.
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 30);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 50);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 70);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 90);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 100);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 150);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 170);
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 190);
+//    valueProducer->onConditionChanged(false, bucketStartTimeNs + 200);
+//
+//    // Condition change event 11
+//    valueProducer->onConditionChanged(true, bucketStartTimeNs + 220);
+//
+//    // Check dump report.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    int64_t dumpReportTimeNs = bucketStartTimeNs + 1000;
+//    // Because we already have 10 dump events in the current bucket,
+//    // this case should not be added to the list of dump events.
+//    valueProducer->onDumpReport(bucketStartTimeNs + 1000, true /* include recent buckets */, true,
+//                                FAST /* dumpLatency */, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(0, report.value_metrics().data_size());
+//    EXPECT_EQ(1, report.value_metrics().skipped_size());
+//
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs),
+//              report.value_metrics().skipped(0).start_bucket_elapsed_millis());
+//    EXPECT_EQ(NanoToMillis(dumpReportTimeNs),
+//              report.value_metrics().skipped(0).end_bucket_elapsed_millis());
+//    EXPECT_EQ(10, report.value_metrics().skipped(0).drop_event_size());
+//
+//    auto dropEvent = report.value_metrics().skipped(0).drop_event(0);
+//    EXPECT_EQ(BucketDropReason::CONDITION_UNKNOWN, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 10), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(1);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 30), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(2);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 50), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(3);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 70), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(4);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 90), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(5);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 100), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(6);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 150), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(7);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 170), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(8);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 190), dropEvent.drop_time_millis());
+//
+//    dropEvent = report.value_metrics().skipped(0).drop_event(9);
+//    EXPECT_EQ(BucketDropReason::PULL_FAILED, dropEvent.drop_reason());
+//    EXPECT_EQ(NanoToMillis(bucketStartTimeNs + 200), dropEvent.drop_time_millis());
+//}
+//
+///*
+// * Test metric with a simple sliced state
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedState) {
+//    // Set up ValueMetricProducer.
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE");
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // ValueMetricProducer initialized.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write("field1");
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to ON.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+//                event->write("field1");
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to OFF.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("field1");
+//                event->write(9);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to ON.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+//                event->write("field1");
+//                event->write(21);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(30);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithState(
+//                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, {});
+//
+//    // Set up StateManager and check that StateTrackers are initialized.
+//    StateManager::getInstance().clear();
+//    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+//    // Bucket status after metric initialized.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(3, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after screen state change kStateUnknown->ON.
+//    auto screenEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(5, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Bucket status after screen state change ON->OFF.
+//    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                                bucketStartTimeNs + 10);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(9, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, ON}
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(4, it->second[0].value.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Bucket status after screen state change OFF->ON.
+//    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//                                                bucketStartTimeNs + 15);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(3UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(21, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, OFF}
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(12, it->second[0].value.long_value);
+//    // Value for dimension, state key {{}, ON}
+//    it++;
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//              it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(4, it->second[0].value.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Start dump report and check output.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(3, report.value_metrics().data_size());
+//
+//    auto data = report.value_metrics().data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//
+//    data = report.value_metrics().data(1);
+//    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+//    EXPECT_EQ(13, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON, data.slice_by_state(0).value());
+//
+//    data = report.value_metrics().data(2);
+//    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+//    EXPECT_EQ(12, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_OFF, data.slice_by_state(0).value());
+//}
+//
+///*
+// * Test metric with sliced state with map
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedStateWithMap) {
+//    // Set up ValueMetricProducer.
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("SCREEN_STATE_ONOFF");
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // ValueMetricProducer initialized.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write("field1");
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to ON.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 5);
+//                event->write("field1");
+//                event->write(5);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to VR.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 10);
+//                event->write("field1");
+//                event->write(9);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Screen state change to OFF.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 15);
+//                event->write("field1");
+//                event->write(21);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report requested.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 50);
+//                event->write("field1");
+//                event->write(30);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    const StateMap& stateMap = CreateScreenStateOnOffMap();
+//    const StateMap_StateGroup screenOnGroup = stateMap.group(0);
+//    const StateMap_StateGroup screenOffGroup = stateMap.group(1);
+//
+//    unordered_map<int, unordered_map<int, int64_t>> stateGroupMap;
+//    for (auto group : stateMap.group()) {
+//        for (auto value : group.value()) {
+//            stateGroupMap[SCREEN_STATE_ATOM_ID][value] = group.group_id();
+//        }
+//    }
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithState(
+//                    pullerManager, metric, {android::util::SCREEN_STATE_CHANGED}, stateGroupMap);
+//
+//    // Set up StateManager and check that StateTrackers are initialized.
+//    StateManager::getInstance().clear();
+//    StateManager::getInstance().registerListener(SCREEN_STATE_ATOM_ID, valueProducer);
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(SCREEN_STATE_ATOM_ID));
+//
+//    // Bucket status after metric initialized.
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(3, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, {}}
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after screen state change kStateUnknown->ON.
+//    auto screenEvent = CreateScreenStateChangedEvent(
+//            android::view::DisplayStateEnum::DISPLAY_STATE_ON, bucketStartTimeNs + 5);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(1UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(5, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Bucket status after screen state change ON->VR (also ON).
+//    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_VR,
+//                                                bucketStartTimeNs + 10);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(9, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, ON GROUP}
+//    EXPECT_EQ(screenOnGroup.group_id(),
+//              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(4, it->second[0].value.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Bucket status after screen state change VR->OFF.
+//    screenEvent = CreateScreenStateChangedEvent(android::view::DisplayStateEnum::DISPLAY_STATE_OFF,
+//                                                bucketStartTimeNs + 15);
+//    StateManager::getInstance().onLogEvent(*screenEvent);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(21, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{}, ON GROUP}
+//    EXPECT_EQ(screenOnGroup.group_id(),
+//              it->first.getStateValuesKey().getValues()[0].mValue.long_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(16, it->second[0].value.long_value);
+//    // Value for dimension, state key {{}, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Start dump report and check output.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucketStartTimeNs + 50, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(3, report.value_metrics().data_size());
+//
+//    auto data = report.value_metrics().data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(2, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//
+//    data = report.value_metrics().data(1);
+//    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+//    EXPECT_EQ(16, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(screenOnGroup.group_id(), data.slice_by_state(0).group_id());
+//
+//    data = report.value_metrics().data(2);
+//    EXPECT_EQ(1, report.value_metrics().data(2).bucket_info_size());
+//    EXPECT_EQ(9, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(SCREEN_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_group_id());
+//    EXPECT_EQ(screenOffGroup.group_id(), data.slice_by_state(0).group_id());
+//}
+//
+///*
+// * Test metric that slices by state with a primary field and has dimensions
+// * - Increasing values
+// * - Using diff
+// * - Second field is value field
+// */
+//TEST(ValueMetricProducerTest, TestSlicedStateWithPrimaryField_WithDimensions) {
+//    // Set up ValueMetricProducer.
+//    ValueMetric metric = ValueMetricProducerTestHelper::createMetricWithState("UID_PROCESS_STATE");
+//    metric.mutable_dimensions_in_what()->set_field(tagId);
+//    metric.mutable_dimensions_in_what()->add_child()->set_field(1);
+//
+//    MetricStateLink* stateLink = metric.add_state_link();
+//    stateLink->set_state_atom_id(UID_PROCESS_STATE_ATOM_ID);
+//    auto fieldsInWhat = stateLink->mutable_fields_in_what();
+//    *fieldsInWhat = CreateDimensions(tagId, {1 /* uid */});
+//    auto fieldsInState = stateLink->mutable_fields_in_state();
+//    *fieldsInState = CreateDimensions(UID_PROCESS_STATE_ATOM_ID, {1 /* uid */});
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(tagId, _))
+//            // ValueMetricProducer initialized.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(2 /* uid */);
+//                event->write(7);
+//                event->init();
+//                data->push_back(event);
+//
+//                event = make_shared<LogEvent>(tagId, bucketStartTimeNs);
+//                event->write(1 /* uid */);
+//                event->write(3);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Uid 1 process state change from kStateUnknown -> Foreground
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//                event->write(1 /* uid */);
+//                event->write(6);
+//                event->init();
+//                data->push_back(event);
+//
+//                // This event should be skipped.
+//                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 20);
+//                event->write(2 /* uid */);
+//                event->write(8);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Uid 2 process state change from kStateUnknown -> Background
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+//                event->write(2 /* uid */);
+//                event->write(9);
+//                event->init();
+//                data->push_back(event);
+//
+//                // This event should be skipped.
+//                event = make_shared<LogEvent>(tagId, bucketStartTimeNs + 40);
+//                event->write(1 /* uid */);
+//                event->write(12);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Uid 1 process state change from Foreground -> Background
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+//                event->write(1 /* uid */);
+//                event->write(13);
+//                event->init();
+//                data->push_back(event);
+//
+//                // This event should be skipped.
+//                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 20);
+//                event->write(2 /* uid */);
+//                event->write(11);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Uid 1 process state change from Background -> Foreground
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+//                event->write(1 /* uid */);
+//                event->write(17);
+//                event->init();
+//                data->push_back(event);
+//
+//                // This event should be skipped.
+//                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 40);
+//                event->write(2 /* uid */);
+//                event->write(15);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }))
+//            // Dump report pull.
+//            .WillOnce(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+//                event->write(2 /* uid */);
+//                event->write(20);
+//                event->init();
+//                data->push_back(event);
+//
+//                event = make_shared<LogEvent>(tagId, bucket2StartTimeNs + 50);
+//                event->write(1 /* uid */);
+//                event->write(21);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    sp<ValueMetricProducer> valueProducer =
+//            ValueMetricProducerTestHelper::createValueProducerWithState(
+//                    pullerManager, metric, {UID_PROCESS_STATE_ATOM_ID}, {});
+//
+//    // Set up StateManager and check that StateTrackers are initialized.
+//    StateManager::getInstance().clear();
+//    StateManager::getInstance().registerListener(UID_PROCESS_STATE_ATOM_ID, valueProducer);
+//    EXPECT_EQ(1, StateManager::getInstance().getStateTrackersCount());
+//    EXPECT_EQ(1, StateManager::getInstance().getListenersCount(UID_PROCESS_STATE_ATOM_ID));
+//
+//    // Bucket status after metric initialized.
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {uid 1}.
+//    auto it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    auto itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(3, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{uid 1}, kStateUnknown}
+//    // TODO(tsaichristine): test equality of state values key
+//    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//    // Base for dimension key {uid 2}
+//    it++;
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(7, itBase->second[0].base.long_value);
+//    // Value for dimension, state key {{uid 2}, kStateUnknown}
+//    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after uid 1 process state change kStateUnknown -> Foreground.
+//    auto uidProcessEvent = CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucketStartTimeNs + 20);
+//    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {uid 1}.
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(6, itBase->second[0].base.long_value);
+//    // Value for key {uid 1, kStateUnknown}.
+//    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(3, it->second[0].value.long_value);
+//
+//    // Base for dimension key {uid 2}
+//    it++;
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(7, itBase->second[0].base.long_value);
+//    // Value for key {uid 2, kStateUnknown}
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after uid 2 process state change kStateUnknown -> Background.
+//    uidProcessEvent = CreateUidProcessStateChangedEvent(
+//            2 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucketStartTimeNs + 40);
+//    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//    EXPECT_EQ(2UL, valueProducer->mCurrentSlicedBucket.size());
+//    // Base for dimension key {uid 1}.
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(6, itBase->second[0].base.long_value);
+//    // Value for key {uid 1, kStateUnknown}.
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(3, it->second[0].value.long_value);
+//
+//    // Base for dimension key {uid 2}
+//    it++;
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(9, itBase->second[0].base.long_value);
+//    // Value for key {uid 2, kStateUnknown}
+//    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(2, it->second[0].value.long_value);
+//
+//    // Pull at end of first bucket.
+//    vector<shared_ptr<LogEvent>> allData;
+//    shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+//    event->write(1 /* uid */);
+//    event->write(10);
+//    event->init();
+//    allData.push_back(event);
+//
+//    event = make_shared<LogEvent>(tagId, bucket2StartTimeNs);
+//    event->write(2 /* uid */);
+//    event->write(15);
+//    event->init();
+//    allData.push_back(event);
+//
+//    valueProducer->onDataPulled(allData, /** succeeds */ true, bucket2StartTimeNs + 1);
+//
+//    // Buckets flushed after end of first bucket.
+//    // None of the buckets should have a value.
+//    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+//    // Base for dimension key {uid 2}.
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(15, itBase->second[0].base.long_value);
+//    // Value for key {uid 2, BACKGROUND}.
+//    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+//    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Base for dimension key {uid 1}
+//    it++;
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(10, itBase->second[0].base.long_value);
+//    // Value for key {uid 1, kStateUnknown}
+//    EXPECT_EQ(0, it->first.getStateValuesKey().getValues().size());
+//    // EXPECT_EQ(-1, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Value for key {uid 1, FOREGROUND}
+//    it++;
+//    EXPECT_EQ(1, it->first.getStateValuesKey().getValues().size());
+//    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Value for key {uid 2, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after uid 1 process state change from Foreground -> Background.
+//    uidProcessEvent = CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_BACKGROUND, bucket2StartTimeNs + 20);
+//    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//
+//    EXPECT_EQ(4UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(4UL, valueProducer->mPastBuckets.size());
+//    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+//    // Base for dimension key {uid 2}.
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(15, itBase->second[0].base.long_value);
+//    // Value for key {uid 2, BACKGROUND}.
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//    // Base for dimension key {uid 1}
+//    it++;
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(13, itBase->second[0].base.long_value);
+//    // Value for key {uid 1, kStateUnknown}
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//    // Value for key {uid 1, FOREGROUND}
+//    it++;
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(3, it->second[0].value.long_value);
+//    // Value for key {uid 2, kStateUnknown}
+//    it++;
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Bucket status after uid 1 process state change Background->Foreground.
+//    uidProcessEvent = CreateUidProcessStateChangedEvent(
+//            1 /* uid */, android::app::PROCESS_STATE_IMPORTANT_FOREGROUND, bucket2StartTimeNs + 40);
+//    StateManager::getInstance().onLogEvent(*uidProcessEvent);
+//
+//    EXPECT_EQ(5UL, valueProducer->mCurrentSlicedBucket.size());
+//    EXPECT_EQ(2UL, valueProducer->mCurrentBaseInfo.size());
+//    // Base for dimension key {uid 2}
+//    it = valueProducer->mCurrentSlicedBucket.begin();
+//    EXPECT_EQ(2, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(true, itBase->second[0].hasBase);
+//    EXPECT_EQ(15, itBase->second[0].base.long_value);
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    it++;
+//    EXPECT_EQ(false, it->second[0].hasValue);
+//
+//    // Base for dimension key {uid 1}
+//    it++;
+//    EXPECT_EQ(1, it->first.getDimensionKeyInWhat().getValues()[0].mValue.int_value);
+//    itBase = valueProducer->mCurrentBaseInfo.find(it->first.getDimensionKeyInWhat());
+//    EXPECT_EQ(17, itBase->second[0].base.long_value);
+//    // Value for key {uid 1, BACKGROUND}
+//    EXPECT_EQ(1006, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(4, it->second[0].value.long_value);
+//    // Value for key {uid 1, FOREGROUND}
+//    it++;
+//    EXPECT_EQ(1005, it->first.getStateValuesKey().getValues()[0].mValue.int_value);
+//    EXPECT_EQ(true, it->second[0].hasValue);
+//    EXPECT_EQ(3, it->second[0].value.long_value);
+//
+//    // Start dump report and check output.
+//    ProtoOutputStream output;
+//    std::set<string> strSet;
+//    valueProducer->onDumpReport(bucket2StartTimeNs + 50, true /* include recent buckets */, true,
+//                                NO_TIME_CONSTRAINTS, &strSet, &output);
+//
+//    StatsLogReport report = outputStreamToProto(&output);
+//    EXPECT_TRUE(report.has_value_metrics());
+//    EXPECT_EQ(5, report.value_metrics().data_size());
+//
+//    auto data = report.value_metrics().data(0);
+//    EXPECT_EQ(1, data.bucket_info_size());
+//    EXPECT_EQ(4, report.value_metrics().data(0).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+//              data.slice_by_state(0).value());
+//
+//    data = report.value_metrics().data(1);
+//    EXPECT_EQ(1, report.value_metrics().data(1).bucket_info_size());
+//    EXPECT_EQ(2, report.value_metrics().data(1).bucket_info(0).values(0).value_long());
+//
+//    data = report.value_metrics().data(2);
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_FOREGROUND,
+//              data.slice_by_state(0).value());
+//    EXPECT_EQ(2, report.value_metrics().data(2).bucket_info_size());
+//    EXPECT_EQ(4, report.value_metrics().data(2).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(7, report.value_metrics().data(2).bucket_info(1).values(0).value_long());
+//
+//    data = report.value_metrics().data(3);
+//    EXPECT_EQ(1, report.value_metrics().data(3).bucket_info_size());
+//    EXPECT_EQ(3, report.value_metrics().data(3).bucket_info(0).values(0).value_long());
+//
+//    data = report.value_metrics().data(4);
+//    EXPECT_EQ(UID_PROCESS_STATE_ATOM_ID, data.slice_by_state(0).atom_id());
+//    EXPECT_TRUE(data.slice_by_state(0).has_value());
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_IMPORTANT_BACKGROUND,
+//              data.slice_by_state(0).value());
+//    EXPECT_EQ(2, report.value_metrics().data(4).bucket_info_size());
+//    EXPECT_EQ(6, report.value_metrics().data(4).bucket_info(0).values(0).value_long());
+//    EXPECT_EQ(5, report.value_metrics().data(4).bucket_info(1).values(0).value_long());
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
index dac5f33..57e4265 100644
--- a/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
+++ b/cmds/statsd/tests/shell/ShellSubscriber_test.cpp
@@ -105,29 +105,30 @@
     close(fds_data[0]);
 }
 
-TEST(ShellSubscriberTest, testPushedSubscription) {
-    sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    vector<std::shared_ptr<LogEvent>> pushedList;
-
-    std::shared_ptr<LogEvent> event1 =
-            std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
-    event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
-    event1->init();
-    pushedList.push_back(event1);
-
-    // create a simple config to get screen events
-    ShellSubscription config;
-    config.add_pushed()->set_atom_id(29);
-
-    // this is the expected screen event atom.
-    ShellData shellData;
-    shellData.add_atom()->mutable_screen_state_changed()->set_state(
-            ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
-
-    runShellTest(config, uidMap, pullerManager, pushedList, shellData);
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ShellSubscriberTest, testPushedSubscription) {
+//    sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    vector<std::shared_ptr<LogEvent>> pushedList;
+//
+//    std::shared_ptr<LogEvent> event1 =
+//            std::make_shared<LogEvent>(29 /*screen_state_atom_id*/, 1000 /*timestamp*/);
+//    event1->write(::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+//    event1->init();
+//    pushedList.push_back(event1);
+//
+//    // create a simple config to get screen events
+//    ShellSubscription config;
+//    config.add_pushed()->set_atom_id(29);
+//
+//    // this is the expected screen event atom.
+//    ShellData shellData;
+//    shellData.add_atom()->mutable_screen_state_changed()->set_state(
+//            ::android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+//
+//    runShellTest(config, uidMap, pullerManager, pushedList, shellData);
+//}
 
 namespace {
 
@@ -160,30 +161,31 @@
 
 }  // namespace
 
-TEST(ShellSubscriberTest, testPulledSubscription) {
-    sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
-
-    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
-    EXPECT_CALL(*pullerManager, Pull(10016, _))
-            .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
-                data->clear();
-                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
-                event->write(kUid1);
-                event->write(kCpuTime1);
-                event->init();
-                data->push_back(event);
-                // another event
-                event = make_shared<LogEvent>(tagId, 1111L);
-                event->write(kUid2);
-                event->write(kCpuTime2);
-                event->init();
-                data->push_back(event);
-                return true;
-            }));
-
-    runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
-                 getExpectedShellData());
-}
+// TODO(b/149590301): Update this test to use new socket schema.
+//TEST(ShellSubscriberTest, testPulledSubscription) {
+//    sp<MockUidMap> uidMap = new NaggyMock<MockUidMap>();
+//
+//    sp<MockStatsPullerManager> pullerManager = new StrictMock<MockStatsPullerManager>();
+//    EXPECT_CALL(*pullerManager, Pull(10016, _))
+//            .WillRepeatedly(Invoke([](int tagId, vector<std::shared_ptr<LogEvent>>* data) {
+//                data->clear();
+//                shared_ptr<LogEvent> event = make_shared<LogEvent>(tagId, 1111L);
+//                event->write(kUid1);
+//                event->write(kCpuTime1);
+//                event->init();
+//                data->push_back(event);
+//                // another event
+//                event = make_shared<LogEvent>(tagId, 1111L);
+//                event->write(kUid2);
+//                event->write(kCpuTime2);
+//                event->init();
+//                data->push_back(event);
+//                return true;
+//            }));
+//
+//    runShellTest(getPulledConfig(), uidMap, pullerManager, vector<std::shared_ptr<LogEvent>>(),
+//                 getExpectedShellData());
+//}
 
 #else
 GTEST_LOG_(INFO) << "This test does nothing.\n";
diff --git a/cmds/statsd/tests/state/StateTracker_test.cpp b/cmds/statsd/tests/state/StateTracker_test.cpp
index b0acd5a..36c0f32 100644
--- a/cmds/statsd/tests/state/StateTracker_test.cpp
+++ b/cmds/statsd/tests/state/StateTracker_test.cpp
@@ -56,94 +56,95 @@
     return output.mValue.int_value;
 }
 
-// START: build event functions.
-// State with no primary fields - ScreenStateChanged
-std::shared_ptr<LogEvent> buildScreenEvent(int state) {
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
-    event->write((int32_t)state);
-    event->init();
-    return event;
-}
-
-// State with one primary field - UidProcessStateChanged
-std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
-    event->write((int32_t)uid);
-    event->write((int32_t)state);
-    event->init();
-    return event;
-}
-
-// State with first uid in attribution chain as primary field - WakelockStateChanged
-std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
-    std::vector<AttributionNodeInternal> chain;
-    chain.push_back(AttributionNodeInternal());
-    AttributionNodeInternal& attr = chain.back();
-    attr.set_uid(uid);
-
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
-    event->write(chain);
-    event->write((int32_t)1);  // PARTIAL_WAKE_LOCK
-    event->write(tag);
-    event->write(acquire ? 1 : 0);
-    event->init();
-    return event;
-}
-
-// State with multiple primary fields - OverlayStateChanged
-std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
-    event->write((int32_t)uid);
-    event->write(packageName);
-    event->write(true);  // using_alert_window
-    event->write((int32_t)state);
-    event->init();
-    return event;
-}
-
-// Incorrect event - missing fields
-std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
-    event->write((int32_t)uid);
-    event->write(packageName);
-    event->write((int32_t)state);
-    event->init();
-    return event;
-}
-
-// Incorrect event - exclusive state has wrong type
-std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
-    event->write((int32_t)uid);
-    event->write(packageName);
-    event->write(true);
-    event->write("string");  // exclusive state: string instead of int
-    event->init();
-    return event;
-}
-
-std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
-    std::vector<AttributionNodeInternal> chain;
-    chain.push_back(AttributionNodeInternal());
-    AttributionNodeInternal& attr = chain.back();
-    attr.set_uid(uid);
-
-    std::shared_ptr<LogEvent> event =
-            std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
-    event->write(chain);
-    event->write(reset ? 2 : acquire ? 1 : 0);  // PARTIAL_WAKE_LOCK
-    event->write(0);                            // filtered
-    event->write(0);                            // first match
-    event->write(0);                            // opportunistic
-    event->init();
-    return event;
-}
+// TODO(b/149590301): Update these helpers to use new socket schema.
+//// START: build event functions.
+//// State with no primary fields - ScreenStateChanged
+//std::shared_ptr<LogEvent> buildScreenEvent(int state) {
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::SCREEN_STATE_CHANGED, 1000 /*timestamp*/);
+//    event->write((int32_t)state);
+//    event->init();
+//    return event;
+//}
+//
+//// State with one primary field - UidProcessStateChanged
+//std::shared_ptr<LogEvent> buildUidProcessEvent(int uid, int state) {
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, 1000 /*timestamp*/);
+//    event->write((int32_t)uid);
+//    event->write((int32_t)state);
+//    event->init();
+//    return event;
+//}
+//
+//// State with first uid in attribution chain as primary field - WakelockStateChanged
+//std::shared_ptr<LogEvent> buildPartialWakelockEvent(int uid, const std::string& tag, bool acquire) {
+//    std::vector<AttributionNodeInternal> chain;
+//    chain.push_back(AttributionNodeInternal());
+//    AttributionNodeInternal& attr = chain.back();
+//    attr.set_uid(uid);
+//
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, 1000 /* timestamp */);
+//    event->write(chain);
+//    event->write((int32_t)1);  // PARTIAL_WAKE_LOCK
+//    event->write(tag);
+//    event->write(acquire ? 1 : 0);
+//    event->init();
+//    return event;
+//}
+//
+//// State with multiple primary fields - OverlayStateChanged
+//std::shared_ptr<LogEvent> buildOverlayEvent(int uid, const std::string& packageName, int state) {
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+//    event->write((int32_t)uid);
+//    event->write(packageName);
+//    event->write(true);  // using_alert_window
+//    event->write((int32_t)state);
+//    event->init();
+//    return event;
+//}
+//
+//// Incorrect event - missing fields
+//std::shared_ptr<LogEvent> buildIncorrectOverlayEvent(int uid, const std::string& packageName, int state) {
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+//    event->write((int32_t)uid);
+//    event->write(packageName);
+//    event->write((int32_t)state);
+//    event->init();
+//    return event;
+//}
+//
+//// Incorrect event - exclusive state has wrong type
+//std::shared_ptr<LogEvent> buildOverlayEventBadStateType(int uid, const std::string& packageName) {
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::OVERLAY_STATE_CHANGED, 1000 /*timestamp*/);
+//    event->write((int32_t)uid);
+//    event->write(packageName);
+//    event->write(true);
+//    event->write("string");  // exclusive state: string instead of int
+//    event->init();
+//    return event;
+//}
+//
+//std::shared_ptr<LogEvent> buildBleScanEvent(int uid, bool acquire, bool reset) {
+//    std::vector<AttributionNodeInternal> chain;
+//    chain.push_back(AttributionNodeInternal());
+//    AttributionNodeInternal& attr = chain.back();
+//    attr.set_uid(uid);
+//
+//    std::shared_ptr<LogEvent> event =
+//            std::make_shared<LogEvent>(android::util::BLE_SCAN_STATE_CHANGED, 1000);
+//    event->write(chain);
+//    event->write(reset ? 2 : acquire ? 1 : 0);  // PARTIAL_WAKE_LOCK
+//    event->write(0);                            // filtered
+//    event->write(0);                            // first match
+//    event->write(0);                            // opportunistic
+//    event->init();
+//    return event;
+//}
 // END: build event functions.
 
 // START: get primary key functions
@@ -292,302 +293,302 @@
     EXPECT_EQ(0, mgr.getStateTrackersCount());
     EXPECT_EQ(-1, mgr.getListenersCount(android::util::SCREEN_STATE_CHANGED));
 }
-
-/**
- * Test a binary state atom with nested counting.
- *
- * To go from an "ON" state to an "OFF" state with nested counting, we must see
- * an equal number of "OFF" events as "ON" events.
- * For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
- * ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
- */
-TEST(StateTrackerTest, TestStateChangeNested) {
-    sp<TestStateListener> listener = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
-
-    std::shared_ptr<LogEvent> event1 =
-            buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
-    mgr.onLogEvent(*event1);
-    EXPECT_EQ(1, listener->updates.size());
-    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(1, listener->updates[0].mState);
-    listener->updates.clear();
-
-    std::shared_ptr<LogEvent> event2 =
-            buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
-    mgr.onLogEvent(*event2);
-    EXPECT_EQ(0, listener->updates.size());
-
-    std::shared_ptr<LogEvent> event3 =
-            buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
-    mgr.onLogEvent(*event3);
-    EXPECT_EQ(0, listener->updates.size());
-
-    std::shared_ptr<LogEvent> event4 =
-            buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
-    mgr.onLogEvent(*event4);
-    EXPECT_EQ(1, listener->updates.size());
-    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(0, listener->updates[0].mState);
-}
-
-/**
- * Test a state atom with a reset state.
- *
- * If the reset state value is seen, every state in the map is set to the default
- * state and every listener is notified.
- */
-TEST(StateTrackerTest, TestStateChangeReset) {
-    sp<TestStateListener> listener = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
-
-    std::shared_ptr<LogEvent> event1 =
-            buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
-    mgr.onLogEvent(*event1);
-    EXPECT_EQ(1, listener->updates.size());
-    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
-    listener->updates.clear();
-
-    std::shared_ptr<LogEvent> event2 =
-            buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
-    mgr.onLogEvent(*event2);
-    EXPECT_EQ(1, listener->updates.size());
-    EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
-    listener->updates.clear();
-
-    std::shared_ptr<LogEvent> event3 =
-            buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
-    mgr.onLogEvent(*event3);
-    EXPECT_EQ(2, listener->updates.size());
-    EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
-    EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states without primary keys.
- */
-TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
-
-    // log event
-    std::shared_ptr<LogEvent> event =
-            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
-    mgr.onLogEvent(*event);
-
-    // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
-    EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
-    EXPECT_EQ(2, listener1->updates[0].mState);
-
-    // check StateTracker was updated by querying for state
-    HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-              getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states with one primary key.
- */
-TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
-
-    // log event
-    std::shared_ptr<LogEvent> event =
-            buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
-    mgr.onLogEvent(*event);
-
-    // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
-    EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(1002, listener1->updates[0].mState);
-
-    // check StateTracker was updated by querying for state
-    HashableDimensionKey queryKey;
-    getUidProcessKey(1000 /* uid */, &queryKey);
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
-}
-
-TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
-
-    // Log event.
-    std::shared_ptr<LogEvent> event =
-            buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
-    mgr.onLogEvent(*event);
-
-    EXPECT_EQ(1, mgr.getStateTrackersCount());
-    EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
-
-    // Check listener was updated.
-    EXPECT_EQ(1, listener1->updates.size());
-    EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
-    EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
-    EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
-    EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
-
-    // Check StateTracker was updated by querying for state.
-    HashableDimensionKey queryKey;
-    getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
-    EXPECT_EQ(WakelockStateChanged::ACQUIRE,
-              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
-
-    // No state stored for this query key.
-    HashableDimensionKey queryKey2;
-    getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
-    EXPECT_EQ(WakelockStateChanged::RELEASE,
-              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
-
-    // Partial query fails.
-    HashableDimensionKey queryKey3;
-    getPartialWakelockKey(1001 /* uid */, &queryKey3);
-    EXPECT_EQ(WakelockStateChanged::RELEASE,
-              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
- * updates listener for states with multiple primary keys.
- */
-TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
-
-    // log event
-    std::shared_ptr<LogEvent> event =
-            buildOverlayEvent(1000 /* uid */, "package1", 1);  // state: ENTERED
-    mgr.onLogEvent(*event);
-
-    // check listener was updated
-    EXPECT_EQ(1, listener1->updates.size());
-    EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
-    EXPECT_EQ(1, listener1->updates[0].mState);
-
-    // check StateTracker was updated by querying for state
-    HashableDimensionKey queryKey;
-    getOverlayKey(1000 /* uid */, "package1", &queryKey);
-    EXPECT_EQ(OverlayStateChanged::ENTERED,
-              getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
-}
-
-/**
- * Test StateManager's onLogEvent and StateListener's onStateChanged
- * when there is an error extracting state from log event. Listener is not
- * updated of state change.
- */
-TEST(StateTrackerTest, TestStateChangeEventError) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
-
-    // log event
-    std::shared_ptr<LogEvent> event1 =
-            buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
-    std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
-
-    // check listener was updated
-    mgr.onLogEvent(*event1);
-    EXPECT_EQ(0, listener1->updates.size());
-    mgr.onLogEvent(*event2);
-    EXPECT_EQ(0, listener1->updates.size());
-}
-
-TEST(StateTrackerTest, TestStateQuery) {
-    sp<TestStateListener> listener1 = new TestStateListener();
-    sp<TestStateListener> listener2 = new TestStateListener();
-    sp<TestStateListener> listener3 = new TestStateListener();
-    sp<TestStateListener> listener4 = new TestStateListener();
-    StateManager mgr;
-    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
-    mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
-    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
-    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
-
-    std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
-            1000,
-            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
-    std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
-            1001,
-            android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE);  //  state value:
-                                                                                //  1003
-    std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
-            1002,
-            android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT);  //  state value: 1000
-    std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
-            1001,
-            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
-    std::shared_ptr<LogEvent> event5 =
-            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
-    std::shared_ptr<LogEvent> event6 =
-            buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
-    std::shared_ptr<LogEvent> event7 =
-            buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
-    std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
-    std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
-
-    mgr.onLogEvent(*event1);
-    mgr.onLogEvent(*event2);
-    mgr.onLogEvent(*event3);
-    mgr.onLogEvent(*event5);
-    mgr.onLogEvent(*event5);
-    mgr.onLogEvent(*event6);
-    mgr.onLogEvent(*event7);
-    mgr.onLogEvent(*event8);
-    mgr.onLogEvent(*event9);
-
-    // Query for UidProcessState of uid 1001
-    HashableDimensionKey queryKey1;
-    getUidProcessKey(1001, &queryKey1);
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
-              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
-
-    // Query for UidProcessState of uid 1004 - not in state map
-    HashableDimensionKey queryKey2;
-    getUidProcessKey(1004, &queryKey2);
-    EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
-                              queryKey2));  // default state
-
-    // Query for UidProcessState of uid 1001 - after change in state
-    mgr.onLogEvent(*event4);
-    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
-              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
-
-    // Query for ScreenState
-    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
-              getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
-
-    // Query for OverlayState of uid 1000, package name "package2"
-    HashableDimensionKey queryKey3;
-    getOverlayKey(1000, "package2", &queryKey3);
-    EXPECT_EQ(OverlayStateChanged::EXITED,
-              getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
-
-    // Query for WakelockState of uid 1005, tag 2
-    HashableDimensionKey queryKey4;
-    getPartialWakelockKey(1005, "tag2", &queryKey4);
-    EXPECT_EQ(WakelockStateChanged::RELEASE,
-              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
-
-    // Query for WakelockState of uid 1005, tag 1
-    HashableDimensionKey queryKey5;
-    getPartialWakelockKey(1005, "tag1", &queryKey5);
-    EXPECT_EQ(WakelockStateChanged::ACQUIRE,
-              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
-}
+// TODO(b/149590301): Update these tests to use new socket schema.
+///**
+// * Test a binary state atom with nested counting.
+// *
+// * To go from an "ON" state to an "OFF" state with nested counting, we must see
+// * an equal number of "OFF" events as "ON" events.
+// * For example, ACQUIRE, ACQUIRE, RELEASE will still be in the ACQUIRE state.
+// * ACQUIRE, ACQUIRE, RELEASE, RELEASE will be in the RELEASE state.
+// */
+//TEST(StateTrackerTest, TestStateChangeNested) {
+//    sp<TestStateListener> listener = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener);
+//
+//    std::shared_ptr<LogEvent> event1 =
+//            buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
+//    mgr.onLogEvent(*event1);
+//    EXPECT_EQ(1, listener->updates.size());
+//    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(1, listener->updates[0].mState);
+//    listener->updates.clear();
+//
+//    std::shared_ptr<LogEvent> event2 =
+//            buildPartialWakelockEvent(1000 /* uid */, "tag", true /*acquire*/);
+//    mgr.onLogEvent(*event2);
+//    EXPECT_EQ(0, listener->updates.size());
+//
+//    std::shared_ptr<LogEvent> event3 =
+//            buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
+//    mgr.onLogEvent(*event3);
+//    EXPECT_EQ(0, listener->updates.size());
+//
+//    std::shared_ptr<LogEvent> event4 =
+//            buildPartialWakelockEvent(1000 /* uid */, "tag", false /*release*/);
+//    mgr.onLogEvent(*event4);
+//    EXPECT_EQ(1, listener->updates.size());
+//    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(0, listener->updates[0].mState);
+//}
+//
+///**
+// * Test a state atom with a reset state.
+// *
+// * If the reset state value is seen, every state in the map is set to the default
+// * state and every listener is notified.
+// */
+//TEST(StateTrackerTest, TestStateChangeReset) {
+//    sp<TestStateListener> listener = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::BLE_SCAN_STATE_CHANGED, listener);
+//
+//    std::shared_ptr<LogEvent> event1 =
+//            buildBleScanEvent(1000 /* uid */, true /*acquire*/, false /*reset*/);
+//    mgr.onLogEvent(*event1);
+//    EXPECT_EQ(1, listener->updates.size());
+//    EXPECT_EQ(1000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
+//    listener->updates.clear();
+//
+//    std::shared_ptr<LogEvent> event2 =
+//            buildBleScanEvent(2000 /* uid */, true /*acquire*/, false /*reset*/);
+//    mgr.onLogEvent(*event2);
+//    EXPECT_EQ(1, listener->updates.size());
+//    EXPECT_EQ(2000, listener->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(BleScanStateChanged::ON, listener->updates[0].mState);
+//    listener->updates.clear();
+//
+//    std::shared_ptr<LogEvent> event3 =
+//            buildBleScanEvent(2000 /* uid */, false /*acquire*/, true /*reset*/);
+//    mgr.onLogEvent(*event3);
+//    EXPECT_EQ(2, listener->updates.size());
+//    EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[0].mState);
+//    EXPECT_EQ(BleScanStateChanged::OFF, listener->updates[1].mState);
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states without primary keys.
+// */
+//TEST(StateTrackerTest, TestStateChangeNoPrimaryFields) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+//
+//    // log event
+//    std::shared_ptr<LogEvent> event =
+//            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+//    mgr.onLogEvent(*event);
+//
+//    // check listener was updated
+//    EXPECT_EQ(1, listener1->updates.size());
+//    EXPECT_EQ(DEFAULT_DIMENSION_KEY, listener1->updates[0].mKey);
+//    EXPECT_EQ(2, listener1->updates[0].mState);
+//
+//    // check StateTracker was updated by querying for state
+//    HashableDimensionKey queryKey = DEFAULT_DIMENSION_KEY;
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//              getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, queryKey));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states with one primary key.
+// */
+//TEST(StateTrackerTest, TestStateChangeOnePrimaryField) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener1);
+//
+//    // log event
+//    std::shared_ptr<LogEvent> event =
+//            buildUidProcessEvent(1000 /* uid */, android::app::ProcessStateEnum::PROCESS_STATE_TOP);
+//    mgr.onLogEvent(*event);
+//
+//    // check listener was updated
+//    EXPECT_EQ(1, listener1->updates.size());
+//    EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(1002, listener1->updates[0].mState);
+//
+//    // check StateTracker was updated by querying for state
+//    HashableDimensionKey queryKey;
+//    getUidProcessKey(1000 /* uid */, &queryKey);
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey));
+//}
+//
+//TEST(StateTrackerTest, TestStateChangePrimaryFieldAttrChain) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener1);
+//
+//    // Log event.
+//    std::shared_ptr<LogEvent> event =
+//            buildPartialWakelockEvent(1001 /* uid */, "tag1", true /* acquire */);
+//    mgr.onLogEvent(*event);
+//
+//    EXPECT_EQ(1, mgr.getStateTrackersCount());
+//    EXPECT_EQ(1, mgr.getListenersCount(android::util::WAKELOCK_STATE_CHANGED));
+//
+//    // Check listener was updated.
+//    EXPECT_EQ(1, listener1->updates.size());
+//    EXPECT_EQ(3, listener1->updates[0].mKey.getValues().size());
+//    EXPECT_EQ(1001, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(1, listener1->updates[0].mKey.getValues()[1].mValue.int_value);
+//    EXPECT_EQ("tag1", listener1->updates[0].mKey.getValues()[2].mValue.str_value);
+//    EXPECT_EQ(WakelockStateChanged::ACQUIRE, listener1->updates[0].mState);
+//
+//    // Check StateTracker was updated by querying for state.
+//    HashableDimensionKey queryKey;
+//    getPartialWakelockKey(1001 /* uid */, "tag1", &queryKey);
+//    EXPECT_EQ(WakelockStateChanged::ACQUIRE,
+//              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey));
+//
+//    // No state stored for this query key.
+//    HashableDimensionKey queryKey2;
+//    getPartialWakelockKey(1002 /* uid */, "tag1", &queryKey2);
+//    EXPECT_EQ(WakelockStateChanged::RELEASE,
+//              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey2));
+//
+//    // Partial query fails.
+//    HashableDimensionKey queryKey3;
+//    getPartialWakelockKey(1001 /* uid */, &queryKey3);
+//    EXPECT_EQ(WakelockStateChanged::RELEASE,
+//              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey3));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged correctly
+// * updates listener for states with multiple primary keys.
+// */
+//TEST(StateTrackerTest, TestStateChangeMultiplePrimaryFields) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+//
+//    // log event
+//    std::shared_ptr<LogEvent> event =
+//            buildOverlayEvent(1000 /* uid */, "package1", 1);  // state: ENTERED
+//    mgr.onLogEvent(*event);
+//
+//    // check listener was updated
+//    EXPECT_EQ(1, listener1->updates.size());
+//    EXPECT_EQ(1000, listener1->updates[0].mKey.getValues()[0].mValue.int_value);
+//    EXPECT_EQ(1, listener1->updates[0].mState);
+//
+//    // check StateTracker was updated by querying for state
+//    HashableDimensionKey queryKey;
+//    getOverlayKey(1000 /* uid */, "package1", &queryKey);
+//    EXPECT_EQ(OverlayStateChanged::ENTERED,
+//              getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey));
+//}
+//
+///**
+// * Test StateManager's onLogEvent and StateListener's onStateChanged
+// * when there is an error extracting state from log event. Listener is not
+// * updated of state change.
+// */
+//TEST(StateTrackerTest, TestStateChangeEventError) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener1);
+//
+//    // log event
+//    std::shared_ptr<LogEvent> event1 =
+//            buildIncorrectOverlayEvent(1000 /* uid */, "package1", 1 /* state */);
+//    std::shared_ptr<LogEvent> event2 = buildOverlayEventBadStateType(1001 /* uid */, "package2");
+//
+//    // check listener was updated
+//    mgr.onLogEvent(*event1);
+//    EXPECT_EQ(0, listener1->updates.size());
+//    mgr.onLogEvent(*event2);
+//    EXPECT_EQ(0, listener1->updates.size());
+//}
+//
+//TEST(StateTrackerTest, TestStateQuery) {
+//    sp<TestStateListener> listener1 = new TestStateListener();
+//    sp<TestStateListener> listener2 = new TestStateListener();
+//    sp<TestStateListener> listener3 = new TestStateListener();
+//    sp<TestStateListener> listener4 = new TestStateListener();
+//    StateManager mgr;
+//    mgr.registerListener(android::util::SCREEN_STATE_CHANGED, listener1);
+//    mgr.registerListener(android::util::UID_PROCESS_STATE_CHANGED, listener2);
+//    mgr.registerListener(android::util::OVERLAY_STATE_CHANGED, listener3);
+//    mgr.registerListener(android::util::WAKELOCK_STATE_CHANGED, listener4);
+//
+//    std::shared_ptr<LogEvent> event1 = buildUidProcessEvent(
+//            1000,
+//            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
+//    std::shared_ptr<LogEvent> event2 = buildUidProcessEvent(
+//            1001,
+//            android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE);  //  state value:
+//                                                                                //  1003
+//    std::shared_ptr<LogEvent> event3 = buildUidProcessEvent(
+//            1002,
+//            android::app::ProcessStateEnum::PROCESS_STATE_PERSISTENT);  //  state value: 1000
+//    std::shared_ptr<LogEvent> event4 = buildUidProcessEvent(
+//            1001,
+//            android::app::ProcessStateEnum::PROCESS_STATE_TOP);  //  state value: 1002
+//    std::shared_ptr<LogEvent> event5 =
+//            buildScreenEvent(android::view::DisplayStateEnum::DISPLAY_STATE_ON);
+//    std::shared_ptr<LogEvent> event6 =
+//            buildOverlayEvent(1000, "package1", OverlayStateChanged::ENTERED);
+//    std::shared_ptr<LogEvent> event7 =
+//            buildOverlayEvent(1000, "package2", OverlayStateChanged::EXITED);
+//    std::shared_ptr<LogEvent> event8 = buildPartialWakelockEvent(1005, "tag1", true);
+//    std::shared_ptr<LogEvent> event9 = buildPartialWakelockEvent(1005, "tag2", false);
+//
+//    mgr.onLogEvent(*event1);
+//    mgr.onLogEvent(*event2);
+//    mgr.onLogEvent(*event3);
+//    mgr.onLogEvent(*event5);
+//    mgr.onLogEvent(*event5);
+//    mgr.onLogEvent(*event6);
+//    mgr.onLogEvent(*event7);
+//    mgr.onLogEvent(*event8);
+//    mgr.onLogEvent(*event9);
+//
+//    // Query for UidProcessState of uid 1001
+//    HashableDimensionKey queryKey1;
+//    getUidProcessKey(1001, &queryKey1);
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_FOREGROUND_SERVICE,
+//              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+//
+//    // Query for UidProcessState of uid 1004 - not in state map
+//    HashableDimensionKey queryKey2;
+//    getUidProcessKey(1004, &queryKey2);
+//    EXPECT_EQ(-1, getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED,
+//                              queryKey2));  // default state
+//
+//    // Query for UidProcessState of uid 1001 - after change in state
+//    mgr.onLogEvent(*event4);
+//    EXPECT_EQ(android::app::ProcessStateEnum::PROCESS_STATE_TOP,
+//              getStateInt(mgr, android::util::UID_PROCESS_STATE_CHANGED, queryKey1));
+//
+//    // Query for ScreenState
+//    EXPECT_EQ(android::view::DisplayStateEnum::DISPLAY_STATE_ON,
+//              getStateInt(mgr, android::util::SCREEN_STATE_CHANGED, DEFAULT_DIMENSION_KEY));
+//
+//    // Query for OverlayState of uid 1000, package name "package2"
+//    HashableDimensionKey queryKey3;
+//    getOverlayKey(1000, "package2", &queryKey3);
+//    EXPECT_EQ(OverlayStateChanged::EXITED,
+//              getStateInt(mgr, android::util::OVERLAY_STATE_CHANGED, queryKey3));
+//
+//    // Query for WakelockState of uid 1005, tag 2
+//    HashableDimensionKey queryKey4;
+//    getPartialWakelockKey(1005, "tag2", &queryKey4);
+//    EXPECT_EQ(WakelockStateChanged::RELEASE,
+//              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey4));
+//
+//    // Query for WakelockState of uid 1005, tag 1
+//    HashableDimensionKey queryKey5;
+//    getPartialWakelockKey(1005, "tag1", &queryKey5);
+//    EXPECT_EQ(WakelockStateChanged::ACQUIRE,
+//              getStateInt(mgr, android::util::WAKELOCK_STATE_CHANGED, queryKey5));
+//}
 
 }  // namespace statsd
 }  // namespace os
diff --git a/cmds/statsd/tests/statsd_test_util.cpp b/cmds/statsd/tests/statsd_test_util.cpp
index 6958218..2bfce9b 100644
--- a/cmds/statsd/tests/statsd_test_util.cpp
+++ b/cmds/statsd/tests/statsd_test_util.cpp
@@ -409,180 +409,181 @@
     return dimensions;
 }
 
-std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
-    const android::view::DisplayStateEnum state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
-    EXPECT_TRUE(event->write(state));
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(
-        android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
-    EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(
-        android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
-    EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
-    int level, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
-    EXPECT_TRUE(event->write(level));
-    event->init();
-    return event;
-
-}
-
-std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
-        const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
-    event->write(attributions);
-    event->write(jobName);
-    event->write(state);
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
-    const std::vector<AttributionNodeInternal>& attributions,
-    const string& name, uint64_t timestampNs) {
-    return CreateScheduledJobStateChangedEvent(
-            attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
-}
-
-// Create log event when scheduled job finishes.
-std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
-    const std::vector<AttributionNodeInternal>& attributions,
-    const string& name, uint64_t timestampNs) {
-    return CreateScheduledJobStateChangedEvent(
-            attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
-        const WakelockStateChanged::State state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
-    event->write(attributions);
-    event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
-    event->write(wakelockName);
-    event->write(state);
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
-        uint64_t timestampNs) {
-    return CreateWakelockStateChangedEvent(
-        attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
-        uint64_t timestampNs) {
-    return CreateWakelockStateChangedEvent(
-        attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
-    const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(
-        android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
-    event->write(uid);
-    event->write("pkg_name");
-    event->write("class_name");
-    event->write(state);
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
-    return CreateActivityForegroundStateChangedEvent(
-        uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
-    return CreateActivityForegroundStateChangedEvent(
-        uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& name,
-        const SyncStateChanged::State state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
-    event->write(attributions);
-    event->write(name);
-    event->write(state);
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateSyncStartEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& name,
-        uint64_t timestampNs) {
-    return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateSyncEndEvent(
-        const std::vector<AttributionNodeInternal>& attributions, const string& name,
-        uint64_t timestampNs) {
-    return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
-    const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
-    auto logEvent = std::make_unique<LogEvent>(
-        android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
-    logEvent->write(uid);
-    logEvent->write("");
-    logEvent->write(state);
-    logEvent->init();
-    return logEvent;
-}
-
-std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
-    return CreateProcessLifeCycleStateChangedEvent(
-        uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
-}
-
-std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
-    event->write(uid);
-    event->write("eventType");
-    event->write("processName");
-    event->init();
-    return event;
-}
-
-std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
-    int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
-    auto logEvent = std::make_unique<LogEvent>(
-        android::util::ISOLATED_UID_CHANGED, timestampNs);
-    logEvent->write(hostUid);
-    logEvent->write(isolatedUid);
-    logEvent->write(is_create);
-    logEvent->init();
-    return logEvent;
-}
-
-std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
-        int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
-    auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
-    event->write(uid);
-    event->write(state);
-    event->init();
-    return event;
-}
+// TODO(b/149590301): Update these helpers to use new socket schema.
+//std::unique_ptr<LogEvent> CreateScreenStateChangedEvent(
+//    const android::view::DisplayStateEnum state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::SCREEN_STATE_CHANGED, timestampNs);
+//    EXPECT_TRUE(event->write(state));
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateBatterySaverOnEvent(uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(
+//        android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
+//    EXPECT_TRUE(event->write(BatterySaverModeStateChanged::ON));
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateBatterySaverOffEvent(uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(
+//        android::util::BATTERY_SAVER_MODE_STATE_CHANGED, timestampNs);
+//    EXPECT_TRUE(event->write(BatterySaverModeStateChanged::OFF));
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateScreenBrightnessChangedEvent(
+//    int level, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::SCREEN_BRIGHTNESS_CHANGED, timestampNs);
+//    EXPECT_TRUE(event->write(level));
+//    event->init();
+//    return event;
+//
+//}
+//
+//std::unique_ptr<LogEvent> CreateScheduledJobStateChangedEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& jobName,
+//        const ScheduledJobStateChanged::State state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::SCHEDULED_JOB_STATE_CHANGED, timestampNs);
+//    event->write(attributions);
+//    event->write(jobName);
+//    event->write(state);
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateStartScheduledJobEvent(
+//    const std::vector<AttributionNodeInternal>& attributions,
+//    const string& name, uint64_t timestampNs) {
+//    return CreateScheduledJobStateChangedEvent(
+//            attributions, name, ScheduledJobStateChanged::STARTED, timestampNs);
+//}
+//
+//// Create log event when scheduled job finishes.
+//std::unique_ptr<LogEvent> CreateFinishScheduledJobEvent(
+//    const std::vector<AttributionNodeInternal>& attributions,
+//    const string& name, uint64_t timestampNs) {
+//    return CreateScheduledJobStateChangedEvent(
+//            attributions, name, ScheduledJobStateChanged::FINISHED, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateWakelockStateChangedEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+//        const WakelockStateChanged::State state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::WAKELOCK_STATE_CHANGED, timestampNs);
+//    event->write(attributions);
+//    event->write(android::os::WakeLockLevelEnum::PARTIAL_WAKE_LOCK);
+//    event->write(wakelockName);
+//    event->write(state);
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateAcquireWakelockEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+//        uint64_t timestampNs) {
+//    return CreateWakelockStateChangedEvent(
+//        attributions, wakelockName, WakelockStateChanged::ACQUIRE, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateReleaseWakelockEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& wakelockName,
+//        uint64_t timestampNs) {
+//    return CreateWakelockStateChangedEvent(
+//        attributions, wakelockName, WakelockStateChanged::RELEASE, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateActivityForegroundStateChangedEvent(
+//    const int uid, const ActivityForegroundStateChanged::State state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(
+//        android::util::ACTIVITY_FOREGROUND_STATE_CHANGED, timestampNs);
+//    event->write(uid);
+//    event->write("pkg_name");
+//    event->write("class_name");
+//    event->write(state);
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateMoveToBackgroundEvent(const int uid, uint64_t timestampNs) {
+//    return CreateActivityForegroundStateChangedEvent(
+//        uid, ActivityForegroundStateChanged::BACKGROUND, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateMoveToForegroundEvent(const int uid, uint64_t timestampNs) {
+//    return CreateActivityForegroundStateChangedEvent(
+//        uid, ActivityForegroundStateChanged::FOREGROUND, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncStateChangedEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& name,
+//        const SyncStateChanged::State state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::SYNC_STATE_CHANGED, timestampNs);
+//    event->write(attributions);
+//    event->write(name);
+//    event->write(state);
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncStartEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& name,
+//        uint64_t timestampNs) {
+//    return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::ON, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateSyncEndEvent(
+//        const std::vector<AttributionNodeInternal>& attributions, const string& name,
+//        uint64_t timestampNs) {
+//    return CreateSyncStateChangedEvent(attributions, name, SyncStateChanged::OFF, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateProcessLifeCycleStateChangedEvent(
+//    const int uid, const ProcessLifeCycleStateChanged::State state, uint64_t timestampNs) {
+//    auto logEvent = std::make_unique<LogEvent>(
+//        android::util::PROCESS_LIFE_CYCLE_STATE_CHANGED, timestampNs);
+//    logEvent->write(uid);
+//    logEvent->write("");
+//    logEvent->write(state);
+//    logEvent->init();
+//    return logEvent;
+//}
+//
+//std::unique_ptr<LogEvent> CreateAppCrashEvent(const int uid, uint64_t timestampNs) {
+//    return CreateProcessLifeCycleStateChangedEvent(
+//        uid, ProcessLifeCycleStateChanged::CRASHED, timestampNs);
+//}
+//
+//std::unique_ptr<LogEvent> CreateAppCrashOccurredEvent(const int uid, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::APP_CRASH_OCCURRED, timestampNs);
+//    event->write(uid);
+//    event->write("eventType");
+//    event->write("processName");
+//    event->init();
+//    return event;
+//}
+//
+//std::unique_ptr<LogEvent> CreateIsolatedUidChangedEvent(
+//    int isolatedUid, int hostUid, bool is_create, uint64_t timestampNs) {
+//    auto logEvent = std::make_unique<LogEvent>(
+//        android::util::ISOLATED_UID_CHANGED, timestampNs);
+//    logEvent->write(hostUid);
+//    logEvent->write(isolatedUid);
+//    logEvent->write(is_create);
+//    logEvent->init();
+//    return logEvent;
+//}
+//
+//std::unique_ptr<LogEvent> CreateUidProcessStateChangedEvent(
+//        int uid, const android::app::ProcessStateEnum state, uint64_t timestampNs) {
+//    auto event = std::make_unique<LogEvent>(android::util::UID_PROCESS_STATE_CHANGED, timestampNs);
+//    event->write(uid);
+//    event->write(state);
+//    event->init();
+//    return event;
+//}
 
 sp<StatsLogProcessor> CreateStatsLogProcessor(const int64_t timeBaseNs, const int64_t currentTimeNs,
                                               const StatsdConfig& config, const ConfigKey& key,
diff --git a/cmds/telecom/src/com/android/commands/telecom/Telecom.java b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
index 9707405..fe270a4 100644
--- a/cmds/telecom/src/com/android/commands/telecom/Telecom.java
+++ b/cmds/telecom/src/com/android/commands/telecom/Telecom.java
@@ -46,6 +46,10 @@
      * @param args The command-line arguments
      */
     public static void main(String[] args) {
+        // Initialize the telephony module.
+        // TODO: Do it in zygote and RuntimeInit. b/148897549
+        ActivityThread.initializeMainlineModules();
+
       (new Telecom()).run(args);
     }
 
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b7a35f7..0a138cf 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -960,7 +960,7 @@
             return false;
         }
         List<GestureDescription.GestureStep> steps =
-                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 100);
+                MotionEventGenerator.getGestureStepsFromGestureDescription(gesture, 16);
         try {
             synchronized (mLock) {
                 mGestureStatusCallbackSequence++;
@@ -2414,4 +2414,55 @@
             return mTimestamp;
         };
     }
+
+    /**
+     * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
+     * function requests that touch interactions starting in the specified region of the screen
+     * bypass the gesture detector. There can only be one gesture detection passthrough region per
+     * display. Requesting a new gesture detection passthrough region clears the existing one. To
+     * disable this passthrough and return to the original behavior, pass in an empty region. When
+     * {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this
+     * function has no effect.
+     *
+     * @param displayId The display on which to set this region.
+     * @param region the region of the screen.
+     */
+    public void setGestureDetectionPassthroughRegion(int displayId, @NonNull Region region) {
+        Preconditions.checkNotNull(region, "region cannot be null");
+        final IAccessibilityServiceConnection connection =
+                AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+        if (connection != null) {
+            try {
+                connection.setGestureDetectionPassthroughRegion(displayId, region);
+            } catch (RemoteException re) {
+                throw new RuntimeException(re);
+            }
+        }
+    }
+
+    /**
+     * When {@link AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is enabled, this
+     * function requests that touch interactions starting in the specified region of the screen
+     * bypass the touch explorer and go straight to the view hierarchy. There can only be one touch
+     * exploration passthrough region per display. Requesting a new touch explorationpassthrough
+     * region clears the existing one. To disable this passthrough and return to the original
+     * behavior, pass in an empty region. When {@link
+     * AccessibilityServiceInfo#FLAG_REQUEST_TOUCH_EXPLORATION_MODE} is disabled this function has
+     * no effect.
+     *
+     * @param displayId The display on which to set this region.
+     * @param region the region of the screen .
+     */
+    public void setTouchExplorationPassthroughRegion(int displayId, @NonNull Region region) {
+        Preconditions.checkNotNull(region, "region cannot be null");
+        final IAccessibilityServiceConnection connection =
+                AccessibilityInteractionClient.getInstance().getConnection(mConnectionId);
+        if (connection != null) {
+            try {
+                connection.setTouchExplorationPassthroughRegion(displayId, region);
+            } catch (RemoteException re) {
+                throw new RuntimeException(re);
+            }
+        }
+    }
 }
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index c1e2195..3b0667d 100644
--- a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
@@ -27,6 +27,7 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
@@ -34,6 +35,7 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
 import android.hardware.fingerprint.FingerprintManager;
 import android.os.Build;
 import android.os.Parcel;
@@ -786,12 +788,34 @@
      *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
      * </p>
      * @return The animated image resource id.
+     * @hide
      */
     public int getAnimatedImageRes() {
         return mAnimatedImageRes;
     }
 
     /**
+     * The animated image drawable.
+     * <p>
+     *    <strong>Statically set from
+     *    {@link AccessibilityService#SERVICE_META_DATA meta-data}.</strong>
+     * </p>
+     * @return The animated image drawable.
+     */
+    @Nullable
+    public Drawable loadAnimatedImage(@NonNull Context context)  {
+        if (mAnimatedImageRes == /* invalid */ 0) {
+            return null;
+        }
+
+        final PackageManager packageManager = context.getPackageManager();
+        final String packageName = mComponentName.getPackageName();
+        final ApplicationInfo applicationInfo = mResolveInfo.serviceInfo.applicationInfo;
+
+        return packageManager.getDrawable(packageName, mAnimatedImageRes, applicationInfo);
+    }
+
+    /**
      * Whether this service can retrieve the current window's content.
      * <p>
      *    <strong>Statically set from
diff --git a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
index 9912d2b..6209679 100644
--- a/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
+++ b/core/java/android/accessibilityservice/AccessibilityShortcutInfo.java
@@ -22,10 +22,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Xml;
 
@@ -193,12 +195,32 @@
      * The animated image resource id of the accessibility shortcut target.
      *
      * @return The animated image resource id.
+     *
+     * @hide
      */
     public int getAnimatedImageRes() {
         return mAnimatedImageRes;
     }
 
     /**
+     * The animated image drawable of the accessibility shortcut target.
+     *
+     * @return The animated image drawable.
+     */
+    @Nullable
+    public Drawable loadAnimatedImage(@NonNull Context context) {
+        if (mAnimatedImageRes == /* invalid */ 0) {
+            return null;
+        }
+
+        final PackageManager packageManager = context.getPackageManager();
+        final String packageName = mComponentName.getPackageName();
+        final ApplicationInfo applicationInfo = mActivityInfo.applicationInfo;
+
+        return packageManager.getDrawable(packageName, mAnimatedImageRes, applicationInfo);
+    }
+
+    /**
      * The localized html description of the accessibility shortcut target.
      *
      * @return The localized html description.
diff --git a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
index 9177d4d..0b3b9b2 100644
--- a/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
+++ b/core/java/android/accessibilityservice/IAccessibilityServiceConnection.aidl
@@ -111,4 +111,8 @@
     int getWindowIdForLeashToken(IBinder token);
 
     void takeScreenshot(int displayId, in RemoteCallback callback);
+
+    void setGestureDetectionPassthroughRegion(int displayId, in Region region);
+
+    void setTouchExplorationPassthroughRegion(int displayId, in Region region);
 }
diff --git a/core/java/android/accessibilityservice/OWNERS b/core/java/android/accessibilityservice/OWNERS
index 265674a..c6f42f7 100644
--- a/core/java/android/accessibilityservice/OWNERS
+++ b/core/java/android/accessibilityservice/OWNERS
@@ -1,3 +1,4 @@
 svetoslavganov@google.com
 pweaver@google.com
 rhedjao@google.com
+qasid@google.com
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 2838ad8..0293346 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -694,7 +694,7 @@
 
     /** @hide Should this process state be considered a background state? */
     public static final boolean isProcStateBackground(int procState) {
-        return procState >= PROCESS_STATE_TRANSIENT_BACKGROUND;
+        return procState > PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
     }
 
     /** @hide Is this a foreground service type? */
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index f6bbc68..8f02f15 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -97,15 +97,77 @@
 import java.util.function.Supplier;
 
 /**
- * AppOps are mappings of [package/uid, op-name] -> [mode]. The list of existing appops is defined
- * by the system and cannot be amended by apps. Only system apps can change appop-modes.
+ * App-ops are used for two purposes: Access control and tracking.
  *
- * <p>Beside a mode the system tracks when an op was {@link #noteOp noted}. The tracked data can
- * only be read by system components.
+ * <p>App-ops cover a wide variety of functionality from helping with runtime permissions access
+ * control and tracking to battery consumption tracking.
  *
- * <p>Installed apps can usually only listen to changes and events on their own ops. E.g.
- * {@link AppOpsCollector} allows to get a callback each time an app called {@link #noteOp} or
- * {@link #startOp} for an op belonging to the app.
+ * <h2>Access control</h2>
+ *
+ * <p>App-ops can either be controlled for each uid or for each package. Which one is used depends
+ * on the API provider maintaining this app-op. For any security or privacy related app-op the
+ * provider needs to control the app-op for per uid as all security and privacy is based on uid in
+ * Android.
+ *
+ * <p>To control access the app-op can be set to a mode to:
+ * <dl>
+ *     <dt>{@link #MODE_DEFAULT}
+ *     <dd>Default behavior, might differ from app-op or app-op
+ *     <dt>{@link #MODE_ALLOWED}
+ *     <dd>Allow the access
+ *     <dt>{@link #MODE_IGNORED}
+ *     <dd>Don't allow the access, i.e. don't perform the requested action or return no or dummy
+ *     data
+ *     <dt>{@link #MODE_ERRORED}
+ *     <dd>Throw a {@link SecurityException} on access. This can be suppressed by using a
+ *     {@code ...noThrow} method to check the mode
+ * </dl>
+ *
+ * <p>API providers need to check the mode returned by {@link #noteOp} if they are are allowing
+ * access to operations gated by the app-op. {@link #unsafeCheckOp} should be used to check the
+ * mode if no access is granted. E.g. this can be used for displaying app-op state in the UI or
+ * when checking the state before later calling {@link #noteOp} anyway.
+ *
+ * <p>If an operation refers to a time span (e.g. a audio-recording session) the API provider
+ * should use {@link #startOp} and {@link #finishOp} instead of {@link #noteOp}.
+ *
+ * <h3>Runtime permissions and app-ops</h3>
+ *
+ * <p>Each platform defined runtime permission (beside background modifiers) has an associated app
+ * op which is used for tracking but also to allow for silent failures. I.e. if the runtime
+ * permission is denied the caller gets a {@link SecurityException}, but if the permission is
+ * granted and the app-op is {@link #MODE_IGNORED} then the callers gets dummy behavior, e.g.
+ * location callbacks would not happen.
+ *
+ * <h3>App-op permissions</h3>
+ *
+ * <p>App-ops permissions are platform defined permissions that can be overridden. The security
+ * check for app-op permissions should by {@link #MODE_DEFAULT default} check the permission grant
+ * state. If the app-op state is set to {@link #MODE_ALLOWED} or {@link #MODE_IGNORED} the app-op
+ * state should be checked instead of the permission grant state.
+ *
+ * <p>This functionality allows to grant access by default to apps fulfilling the requirements for
+ * a certain permission level. Still the behavior can be overridden when needed.
+ *
+ * <h2>Tracking</h2>
+ *
+ * <p>App-ops track many important events, including all accesses to runtime permission protected
+ * APIs. This is done by tracking when an app-op was {@link #noteOp noted} or
+ * {@link #startOp started}. The tracked data can only be read by system components.
+ *
+ * <p><b>Only {@link #noteOp}/{@link #startOp} are tracked; {@link #unsafeCheckOp} is not tracked.
+ * Hence it is important to eventually call {@link #noteOp} or {@link #startOp} when providing
+ * access to protected operations or data.</b>
+ *
+ * <p>Some apps are forwarding access to other apps. E.g. an app might get the location from the
+ * system's location provider and then send the location further to a 3rd app. In this case the
+ * app passing on the data needs to call {@link #noteProxyOp} to signal the access proxying. This
+ * might also make sense inside of a single app if the access is forwarded between two features of
+ * the app.
+ *
+ * <p>An app can register an {@link AppOpsCollector} to get informed about what accesses the
+ * system is tracking for it. As each runtime permission has an associated app-op this API is
+ * particularly useful for an app that want to find unexpected private data accesses.
  */
 @SystemService(Context.APP_OPS_SERVICE)
 public class AppOpsManager {
@@ -121,28 +183,6 @@
     @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q)
     public static final long CALL_BACK_ON_CHANGED_LISTENER_WITH_SWITCHED_OP_CHANGE = 148180766L;
 
-    /**
-     * <p>App ops allows callers to:</p>
-     *
-     * <ul>
-     * <li> Note when operations are happening, and find out if they are allowed for the current
-     * caller.</li>
-     * <li> Disallow specific apps from doing specific operations.</li>
-     * <li> Collect all of the current information about operations that have been executed or
-     * are not being allowed.</li>
-     * <li> Monitor for changes in whether an operation is allowed.</li>
-     * </ul>
-     *
-     * <p>Each operation is identified by a single integer; these integers are a fixed set of
-     * operations, enumerated by the OP_* constants.
-     *
-     * <p></p>When checking operations, the result is a "mode" integer indicating the current
-     * setting for the operation under that caller: MODE_ALLOWED, MODE_IGNORED (don't execute
-     * the operation but fake its behavior enough so that the caller doesn't crash),
-     * MODE_ERRORED (throw a SecurityException back to the caller; the normal operation calls
-     * will do this for you).
-     */
-
     final Context mContext;
 
     @UnsupportedAppUsage
@@ -995,10 +1035,12 @@
     public static final int OP_ACTIVATE_PLATFORM_VPN = 94;
     /** @hide */
     public static final int OP_LOADER_USAGE_STATS = 95;
+    /** @hide Access telephony call audio */
+    public static final int OP_ACCESS_CALL_AUDIO = 96;
 
     /** @hide */
     @UnsupportedAppUsage
-    public static final int _NUM_OP = 96;
+    public static final int _NUM_OP = 97;
 
     /** Access to coarse location information. */
     public static final String OPSTR_COARSE_LOCATION = "android:coarse_location";
@@ -1093,7 +1135,7 @@
     /** Required to draw on top of other apps. */
     public static final String OPSTR_SYSTEM_ALERT_WINDOW
             = "android:system_alert_window";
-    /** Required to write/modify/update system settingss. */
+    /** Required to write/modify/update system settings. */
     public static final String OPSTR_WRITE_SETTINGS
             = "android:write_settings";
     /** @hide Get device accounts. */
@@ -1289,6 +1331,9 @@
     @SystemApi
     public static final String OPSTR_MANAGE_EXTERNAL_STORAGE =
             "android:manage_external_storage";
+    /** @hide Access telephony call audio */
+    @SystemApi
+    public static final String OPSTR_ACCESS_CALL_AUDIO = "android:access_call_audio";
 
     /** @hide Communicate cross-profile within the same profile group. */
     @SystemApi
@@ -1378,6 +1423,7 @@
             OP_MANAGE_EXTERNAL_STORAGE,
             OP_INTERACT_ACROSS_PROFILES,
             OP_LOADER_USAGE_STATS,
+            OP_ACCESS_CALL_AUDIO,
     };
 
     /**
@@ -1485,6 +1531,7 @@
             OP_INTERACT_ACROSS_PROFILES,        //INTERACT_ACROSS_PROFILES
             OP_ACTIVATE_PLATFORM_VPN,           // ACTIVATE_PLATFORM_VPN
             OP_LOADER_USAGE_STATS,              // LOADER_USAGE_STATS
+            OP_ACCESS_CALL_AUDIO,               // ACCESS_CALL_AUDIO
     };
 
     /**
@@ -1587,6 +1634,7 @@
             OPSTR_INTERACT_ACROSS_PROFILES,
             OPSTR_ACTIVATE_PLATFORM_VPN,
             OPSTR_LOADER_USAGE_STATS,
+            OPSTR_ACCESS_CALL_AUDIO,
     };
 
     /**
@@ -1690,6 +1738,7 @@
             "INTERACT_ACROSS_PROFILES",
             "ACTIVATE_PLATFORM_VPN",
             "LOADER_USAGE_STATS",
+            "ACCESS_CALL_AUDIO",
     };
 
     /**
@@ -1794,6 +1843,7 @@
             android.Manifest.permission.INTERACT_ACROSS_PROFILES,
             null, // no permission for OP_ACTIVATE_PLATFORM_VPN
             android.Manifest.permission.LOADER_USAGE_STATS,
+            Manifest.permission.ACCESS_CALL_AUDIO,
     };
 
     /**
@@ -1898,6 +1948,7 @@
             null, // INTERACT_ACROSS_PROFILES
             null, // ACTIVATE_PLATFORM_VPN
             null, // LOADER_USAGE_STATS
+            null, // ACCESS_CALL_AUDIO
     };
 
     /**
@@ -2001,6 +2052,7 @@
             false, // INTERACT_ACROSS_PROFILES
             false, // ACTIVATE_PLATFORM_VPN
             false, // LOADER_USAGE_STATS
+            false, // ACCESS_CALL_AUDIO
     };
 
     /**
@@ -2103,6 +2155,7 @@
             AppOpsManager.MODE_DEFAULT, // INTERACT_ACROSS_PROFILES
             AppOpsManager.MODE_IGNORED, // ACTIVATE_PLATFORM_VPN
             AppOpsManager.MODE_DEFAULT, // LOADER_USAGE_STATS
+            AppOpsManager.MODE_DEFAULT, // ACCESS_CALL_AUDIO
     };
 
     /**
@@ -2209,6 +2262,7 @@
             false, // INTERACT_ACROSS_PROFILES
             false, // ACTIVATE_PLATFORM_VPN
             false, // LOADER_USAGE_STATS
+            false, // ACCESS_CALL_AUDIO
     };
 
     /**
@@ -6115,7 +6169,7 @@
      */
     public interface OnOpActiveChangedListener {
         /**
-         * Called when the active state of an app op changes.
+         * Called when the active state of an app-op changes.
          *
          * @param op The operation that changed.
          * @param packageName The package performing the operation.
@@ -6406,7 +6460,7 @@
     @SystemApi
     @TestApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
-    public void setUidMode(String appOp, int uid, @Mode int mode) {
+    public void setUidMode(@NonNull String appOp, int uid, @Mode int mode) {
         try {
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
         } catch (RemoteException e) {
@@ -6461,7 +6515,8 @@
     @TestApi
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MANAGE_APP_OPS_MODES)
-    public void setMode(String op, int uid, String packageName, @Mode int mode) {
+    public void setMode(@NonNull String op, int uid, @Nullable String packageName,
+            @Mode int mode) {
         try {
             mService.setMode(strOpToOp(op), uid, packageName, mode);
         } catch (RemoteException e) {
@@ -6504,16 +6559,17 @@
     }
 
     /**
-     * Gets the app op name associated with a given permission.
-     * The app op name is one of the public constants defined
+     * Gets the app-op name associated with a given permission.
+     *
+     * <p>The app-op name is one of the public constants defined
      * in this class such as {@link #OPSTR_COARSE_LOCATION}.
      * This API is intended to be used for mapping runtime
-     * permissions to the corresponding app op.
+     * permissions to the corresponding app-op.
      *
      * @param permission The permission.
-     * @return The app op associated with the permission or null.
+     * @return The app-op associated with the permission or {@code null}.
      */
-    public static String permissionToOp(String permission) {
+    public static @Nullable String permissionToOp(@NonNull String permission) {
         final Integer opCode = sPermToOp.get(permission);
         if (opCode == null) {
             return null;
@@ -6631,7 +6687,7 @@
     }
 
     /**
-     * Start watching for changes to the active state of app ops. An app op may be
+     * Start watching for changes to the active state of app-ops. An app-op may be
      * long running and it has a clear start and stop delimiters. If an op is being
      * started or stopped by any package you will get a callback. To change the
      * watched ops for a registered callback you need to unregister and register it
@@ -6690,7 +6746,7 @@
     }
 
     /**
-     * Stop watching for changes to the active state of an app op. An app op may be
+     * Stop watching for changes to the active state of an app-op. An app-op may be
      * long running and it has a clear start and stop delimiters. Unregistering a
      * non-registered callback has no effect.
      *
@@ -6921,7 +6977,8 @@
      * @param op The operation to note.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
-     * @param featureId The feature in the app or {@code null} for default feature
+     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
+     * null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -6996,6 +7053,8 @@
      * @param op The operation to note.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
+     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
+     * null} for default feature
      * @param message A message describing the reason the op was noted
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7003,8 +7062,8 @@
      * causing the app to crash).
      */
     public int noteOpNoThrow(@NonNull String op, int uid, @NonNull String packageName,
-            @Nullable String feature, @Nullable String message) {
-        return noteOpNoThrow(strOpToOp(op), uid, packageName, feature, message);
+            @Nullable String featureId, @Nullable String message) {
+        return noteOpNoThrow(strOpToOp(op), uid, packageName, featureId, message);
     }
 
     /**
@@ -7273,11 +7332,9 @@
     }
 
     /**
-     * Do a quick check to validate if a package name belongs to a UID.
-     *
-     * @throws SecurityException if the package name doesn't belong to the given
-     *             UID, or if ownership cannot be verified.
+     * @deprecated Use {@link PackageManager#getPackageUid} instead
      */
+    @Deprecated
     public void checkPackage(int uid, @NonNull String packageName) {
         try {
             if (mService.checkPackage(uid, packageName) != MODE_ALLOWED) {
@@ -7396,7 +7453,8 @@
      * @param op The operation to start.  One of the OPSTR_* constants.
      * @param uid The user id of the application attempting to perform the operation.
      * @param packageName The name of the application attempting to perform the operation.
-     * @param featureId The feature in the app or {@code null} for default feature
+     * @param featureId The {@link Context#createFeatureContext feature} in the package or {@code
+     * null} for default feature
      * @param message Description why op was started
      *
      * @return Returns {@link #MODE_ALLOWED} if the operation is allowed, or
@@ -7587,7 +7645,8 @@
     }
 
     /**
-     * Checks whether the given op for a package is active.
+     * Checks whether the given op for a package is active, i.e. did someone call {@link #startOp}
+     * without {@link #finishOp} yet.
      * <p>
      * If you don't hold the {@code android.Manifest.permission#WATCH_APPOPS}
      * permission you can query only for your UID.
@@ -7917,18 +7976,19 @@
     }
 
     /**
-     * Callback an app can choose to {@link #setNotedAppOpsCollector register} to monitor it's noted
-     * appops. I.e. each time any app calls {@link #noteOp} or {@link #startOp} one of the callback
-     * methods of this object is called.
+     * Callback an app can {@link #setNotedAppOpsCollector register} to monitor the app-ops the
+     * system has tracked for it. I.e. each time any app calls {@link #noteOp} or {@link #startOp}
+     * one of the callback methods of this object is called.
      *
-     * <p><b>Only appops related to dangerous permissions are collected.</b>
+     * <p><b>There will be a callback for all app-ops related to runtime permissions, but not
+     * necessarily for all other app-ops.
      *
      * <pre>
      * setNotedAppOpsCollector(new AppOpsCollector() {
      *     ArraySet<Pair<String, String>> opsNotedForThisProcess = new ArraySet<>();
      *
      *     private synchronized void addAccess(String op, String accessLocation) {
-     *         // Ops are often noted when permission protected APIs were called.
+     *         // Ops are often noted when runtime permission protected APIs were called.
      *         // In this case permissionToOp() allows to resolve the permission<->op
      *         opsNotedForThisProcess.add(new Pair(accessType, accessLocation));
      *     }
@@ -7970,20 +8030,21 @@
         }
 
         /**
-         * Called when an app-op was noted for this package inside of a two-way binder-call.
+         * Called when an app-op was {@link #noteOp noted} for this package inside of a synchronous
+         * API call, i.e. a API call that returned data or waited until the action was performed.
          *
-         * <p>Called on the calling thread just after executing the binder-call. This allows
-         * the app to e.g. collect stack traces to figure out where the access came from.
+         * <p>Called on the calling thread before the API returns. This allows the app to e.g.
+         * collect stack traces to figure out where the access came from.
          *
          * @param op The op noted
          */
         public abstract void onNoted(@NonNull SyncNotedAppOp op);
 
         /**
-         * Called when this app noted an app-op for its own package.
+         * Called when this app noted an app-op for its own package,
          *
-         * <p>Called on the thread the noted the op. This allows the app to e.g. collect stack
-         * traces to figure out where the access came from.
+         * <p>This is very similar to {@link #onNoted} only that the tracking was not caused by the
+         * API provider in a separate process, but by one in the app's own process.
          *
          * @param op The op noted
          */
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index cd05e2c..e781ac6 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -3334,4 +3334,35 @@
             throw e.rethrowAsRuntimeException();
         }
     }
+
+    public void setMimeGroup(String mimeGroup, Set<String> mimeTypes) {
+        try {
+            mPM.setMimeGroup(mContext.getPackageName(), mimeGroup,
+                    new ArrayList<String>(mimeTypes));
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    @Override
+    public void clearMimeGroup(String mimeGroup) {
+        try {
+            mPM.clearMimeGroup(mContext.getPackageName(), mimeGroup);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
+
+    @Override
+    public Set<String> getMimeGroup(String group) {
+        try {
+            List<String> mimeGroup = mPM.getMimeGroup(mContext.getPackageName(), group);
+            if (mimeGroup == null) {
+                return null;
+            }
+            return new ArraySet<>(mimeGroup);
+        } catch (RemoteException e) {
+            throw e.rethrowAsRuntimeException();
+        }
+    }
 }
diff --git a/core/java/android/app/AsyncNotedAppOp.java b/core/java/android/app/AsyncNotedAppOp.java
index 130e2ec..6b1afda 100644
--- a/core/java/android/app/AsyncNotedAppOp.java
+++ b/core/java/android/app/AsyncNotedAppOp.java
@@ -256,10 +256,10 @@
     };
 
     @DataClass.Generated(
-            time = 1580158740502L,
+            time = 1581728574427L,
             codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/core/java/android/app/AsyncNotedAppOp.java",
-            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=95L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
+            inputSignatures = "private final @android.annotation.IntRange(from=0L, to=96L) int mOpCode\nprivate final @android.annotation.IntRange(from=0L) int mNotingUid\nprivate final @android.annotation.Nullable java.lang.String mFeatureId\nprivate final @android.annotation.NonNull java.lang.String mMessage\nprivate final @android.annotation.IntRange(from=0L) long mTime\npublic @android.annotation.NonNull java.lang.String getOp()\nclass AsyncNotedAppOp extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genAidl=true, genHiddenConstructor=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 6b5bfda..8df26cb 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -16,6 +16,9 @@
 
 package android.app;
 
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.StrictMode.vmIncorrectContextUseEnabled;
+
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -64,6 +67,7 @@
 import android.os.Looper;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.StrictMode;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -247,6 +251,7 @@
 
     private boolean mIsSystemOrSystemUiContext;
     private boolean mIsUiContext;
+    private boolean mIsAssociatedWithDisplay;
 
     @GuardedBy("mSync")
     private File mDatabasesDir;
@@ -1891,9 +1896,20 @@
 
     @Override
     public Object getSystemService(String name) {
-        if (isUiComponent(name) && !isUiContext()) {
-            Log.w(TAG, name + " should be accessed from Activity or other visual Context");
+        // Check incorrect Context usage.
+        if (isUiComponent(name) && !isUiContext() && vmIncorrectContextUseEnabled()) {
+            final String errorMessage = "Tried to access visual service " + name
+                    + " from a non-visual Context.";
+            final String message = "Visual services, such as WindowManager, WallpaperService or "
+                    + "LayoutInflater should be accessed from Activity or other visual Context. "
+                    + "Use an Activity or a Context created with "
+                    + "Context#createWindowContext(int, Bundle), which are adjusted to the "
+                    + "configuration and visual bounds of an area on screen.";
+            final Exception exception = new IllegalAccessException(errorMessage);
+            StrictMode.onIncorrectContextUsed(message, exception);
+            Log.e(TAG, errorMessage + message, exception);
         }
+
         return SystemServiceRegistry.getSystemService(this, name);
     }
 
@@ -1902,8 +1918,17 @@
         return SystemServiceRegistry.getSystemServiceName(serviceClass);
     }
 
-    boolean isUiContext() {
-        return mIsSystemOrSystemUiContext || mIsUiContext;
+    private boolean isUiContext() {
+        return mIsSystemOrSystemUiContext || mIsUiContext || isSystemOrSystemUI();
+    }
+
+    /**
+     * Temporary workaround to permit incorrect usages of Context by SystemUI.
+     * TODO(b/149790106): Fix usages and remove.
+     */
+    private boolean isSystemOrSystemUI() {
+        return ActivityThread.isSystem() || checkPermission("android.permission.STATUS_BAR_SERVICE",
+                Binder.getCallingPid(), Binder.getCallingUid()) == PERMISSION_GRANTED;
     }
 
     private static boolean isUiComponent(String name) {
@@ -1925,7 +1950,7 @@
             final int appId = UserHandle.getAppId(uid);
             if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
                 Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
-                return PackageManager.PERMISSION_GRANTED;
+                return PERMISSION_GRANTED;
             }
             Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
                     + permission);
@@ -1989,7 +2014,7 @@
     private void enforce(
             String permission, int resultOfCheck,
             boolean selfToo, int uid, String message) {
-        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
+        if (resultOfCheck != PERMISSION_GRANTED) {
             throw new SecurityException(
                     (message != null ? (message + ": ") : "") +
                     (selfToo
@@ -2116,15 +2141,15 @@
         if ((modeFlags&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
             if (readPermission == null
                     || checkPermission(readPermission, pid, uid)
-                    == PackageManager.PERMISSION_GRANTED) {
-                return PackageManager.PERMISSION_GRANTED;
+                    == PERMISSION_GRANTED) {
+                return PERMISSION_GRANTED;
             }
         }
         if ((modeFlags&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
             if (writePermission == null
                     || checkPermission(writePermission, pid, uid)
-                    == PackageManager.PERMISSION_GRANTED) {
-                return PackageManager.PERMISSION_GRANTED;
+                    == PERMISSION_GRANTED) {
+                return PERMISSION_GRANTED;
             }
         }
         return uri != null ? checkUriPermission(uri, pid, uid, modeFlags)
@@ -2157,7 +2182,7 @@
     private void enforceForUri(
             int modeFlags, int resultOfCheck, boolean selfToo,
             int uid, Uri uri, String message) {
-        if (resultOfCheck != PackageManager.PERMISSION_GRANTED) {
+        if (resultOfCheck != PERMISSION_GRANTED) {
             throw new SecurityException(
                     (message != null ? (message + ": ") : "") +
                     (selfToo
@@ -2373,6 +2398,7 @@
                 null, getDisplayAdjustments(displayId).getCompatibilityInfo(),
                 mResources.getLoaders()));
         context.mDisplay = display;
+        context.mIsAssociatedWithDisplay = true;
         return context;
     }
 
@@ -2390,6 +2416,7 @@
         ContextImpl context = new ContextImpl(this, mMainThread, mPackageInfo, mFeatureId,
                 mSplitName, token, mUser, mFlags, mClassLoader, null);
         context.mIsUiContext = true;
+        context.mIsAssociatedWithDisplay = true;
         return context;
     }
 
@@ -2440,6 +2467,19 @@
 
     @Override
     public Display getDisplay() {
+        if (!mIsSystemOrSystemUiContext && !mIsAssociatedWithDisplay && !isSystemOrSystemUI()) {
+            throw new UnsupportedOperationException("Tried to obtain display from a Context not "
+                    + "associated with  one. Only visual Contexts (such as Activity or one created "
+                    + "with Context#createWindowContext) or ones created with "
+                    + "Context#createDisplayContext are associated with displays. Other types of "
+                    + "Contexts are typically related to background entities and may return an "
+                    + "arbitrary display.");
+        }
+        return getDisplayNoVerify();
+    }
+
+    @Override
+    public Display getDisplayNoVerify() {
         if (mDisplay == null) {
             return mResourcesManager.getAdjustedDisplay(Display.DEFAULT_DISPLAY,
                     mResources);
@@ -2450,13 +2490,14 @@
 
     @Override
     public int getDisplayId() {
-        final Display display = getDisplay();
+        final Display display = getDisplayNoVerify();
         return display != null ? display.getDisplayId() : Display.DEFAULT_DISPLAY;
     }
 
     @Override
     public void updateDisplay(int displayId) {
         mDisplay = mResourcesManager.getAdjustedDisplay(displayId, mResources);
+        mIsAssociatedWithDisplay = true;
     }
 
     @Override
@@ -2630,6 +2671,7 @@
         ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null,
                 activityInfo.splitName, activityToken, null, 0, classLoader, null);
         context.mIsUiContext = true;
+        context.mIsAssociatedWithDisplay = true;
 
         // Clamp display ID to DEFAULT_DISPLAY if it is INVALID_DISPLAY.
         displayId = (displayId != Display.INVALID_DISPLAY) ? displayId : Display.DEFAULT_DISPLAY;
diff --git a/core/java/android/app/DexLoadReporter.java b/core/java/android/app/DexLoadReporter.java
index 229bee5..5bc9992 100644
--- a/core/java/android/app/DexLoadReporter.java
+++ b/core/java/android/app/DexLoadReporter.java
@@ -28,9 +28,8 @@
 
 import java.io.File;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
 /**
@@ -87,50 +86,32 @@
     }
 
     @Override
-    public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) {
-        if (classLoadersChain.size() != classPaths.size()) {
-            Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch");
-            return;
-        }
-        if (classPaths.isEmpty()) {
-            Slog.wtf(TAG, "Bad call to DexLoadReporter: empty dex paths");
-            return;
-        }
-
-        // The first element of classPaths is the list of dex files that should be registered.
-        // The classpath is represented as a list of dex files separated by File.pathSeparator.
-        String[] dexPathsForRegistration = classPaths.get(0).split(File.pathSeparator);
-        if (dexPathsForRegistration.length == 0) {
-            // No dex files to register.
+    public void report(Map<String, String> classLoaderContextMap) {
+        if (classLoaderContextMap.isEmpty()) {
+            Slog.wtf(TAG, "Bad call to DexLoadReporter: empty classLoaderContextMap");
             return;
         }
 
         // Notify the package manager about the dex loads unconditionally.
         // The load might be for either a primary or secondary dex file.
-        notifyPackageManager(classLoadersChain, classPaths);
+        notifyPackageManager(classLoaderContextMap);
         // Check for secondary dex files and register them for profiling if possible.
         // Note that we only register the dex paths belonging to the first class loader.
-        registerSecondaryDexForProfiling(dexPathsForRegistration);
+        registerSecondaryDexForProfiling(classLoaderContextMap.keySet());
     }
 
-    private void notifyPackageManager(List<ClassLoader> classLoadersChain,
-            List<String> classPaths) {
+    private void notifyPackageManager(Map<String, String> classLoaderContextMap) {
         // Get the class loader names for the binder call.
-        List<String> classLoadersNames = new ArrayList<>(classPaths.size());
-        for (ClassLoader classLoader : classLoadersChain) {
-            classLoadersNames.add(classLoader.getClass().getName());
-        }
         String packageName = ActivityThread.currentPackageName();
         try {
-            ActivityThread.getPackageManager().notifyDexLoad(
-                    packageName, classLoadersNames, classPaths,
-                    VMRuntime.getRuntime().vmInstructionSet());
+            ActivityThread.getPackageManager().notifyDexLoad(packageName,
+                    classLoaderContextMap, VMRuntime.getRuntime().vmInstructionSet());
         } catch (RemoteException re) {
             Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re);
         }
     }
 
-    private void registerSecondaryDexForProfiling(String[] dexPaths) {
+    private void registerSecondaryDexForProfiling(Set<String> dexPaths) {
         if (!SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) {
             return;
         }
diff --git a/core/java/android/app/IActivityTaskManager.aidl b/core/java/android/app/IActivityTaskManager.aidl
index 180507c..3c475c1 100644
--- a/core/java/android/app/IActivityTaskManager.aidl
+++ b/core/java/android/app/IActivityTaskManager.aidl
@@ -315,11 +315,6 @@
     void positionTaskInStack(int taskId, int stackId, int position);
     void reportSizeConfigurations(in IBinder token, in int[] horizontalSizeConfiguration,
             in int[] verticalSizeConfigurations, in int[] smallestWidthConfigurations);
-    /**
-     * Dismisses split-screen multi-window mode.
-     * {@param toTop} If true the current primary split-screen stack will be placed or left on top.
-     */
-    void dismissSplitScreenMode(boolean toTop);
 
     /**
      * Dismisses PiP
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 526c0b3..948546b 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -88,6 +88,7 @@
     void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList);
     void createNotificationChannels(String pkg, in ParceledListSlice channelsList);
     void createNotificationChannelsForPackage(String pkg, int uid, in ParceledListSlice channelsList);
+    ParceledListSlice getConversations(boolean onlyImportant);
     ParceledListSlice getConversationsForPackage(String pkg, int uid);
     ParceledListSlice getNotificationChannelGroupsForPackage(String pkg, int uid, boolean includeDeleted);
     NotificationChannelGroup getNotificationChannelGroupForPackage(String groupId, String pkg, int uid);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 576b56f..32e7d84 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -6046,21 +6046,18 @@
 
         /**
          * Removes RemoteViews that were created for compatibility from {@param n}, if they did not
-         * change. Also removes extenders on low ram devices, as
-         * {@link android.service.notification.NotificationListenerService} services are disabled.
+         * change.
          *
          * @return {@param n}, if no stripping is needed, otherwise a stripped clone of {@param n}.
          *
          * @hide
          */
-        public static Notification maybeCloneStrippedForDelivery(Notification n, boolean isLowRam,
-                Context context) {
+        public static Notification maybeCloneStrippedForDelivery(Notification n) {
             String templateClass = n.extras.getString(EXTRA_TEMPLATE);
 
             // Only strip views for known Styles because we won't know how to
             // re-create them otherwise.
-            if (!isLowRam
-                    && !TextUtils.isEmpty(templateClass)
+            if (!TextUtils.isEmpty(templateClass)
                     && getNotificationStyleClass(templateClass) == null) {
                 return n;
             }
@@ -6077,8 +6074,7 @@
                             n.headsUpContentView.getSequenceNumber();
 
             // Nothing to do here, no need to clone.
-            if (!isLowRam
-                    && !stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
+            if (!stripContentView && !stripBigContentView && !stripHeadsUpContentView) {
                 return n;
             }
 
@@ -6095,15 +6091,6 @@
                 clone.headsUpContentView = null;
                 clone.extras.remove(EXTRA_REBUILD_HEADS_UP_CONTENT_VIEW_ACTION_COUNT);
             }
-            if (isLowRam) {
-                String[] allowedServices = context.getResources().getStringArray(
-                        R.array.config_allowedManagedServicesOnLowRamDevices);
-                if (allowedServices.length == 0) {
-                    clone.extras.remove(Notification.TvExtender.EXTRA_TV_EXTENDER);
-                    clone.extras.remove(WearableExtender.EXTRA_WEARABLE_EXTENSIONS);
-                    clone.extras.remove(CarExtender.EXTRA_CAR_EXTENDER);
-                }
-            }
             return clone;
         }
 
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 528b508..88edb05 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -592,10 +592,7 @@
         }
 
         notification.reduceImageSizes(mContext);
-
-        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
-        boolean isLowRam = am.isLowRamDevice();
-        return Builder.maybeCloneStrippedForDelivery(notification, isLowRam, mContext);
+        return Builder.maybeCloneStrippedForDelivery(notification);
     }
 
     private void fixLegacySmallIcon(Notification n, String pkg) {
diff --git a/core/java/android/app/SharedElementCallback.java b/core/java/android/app/SharedElementCallback.java
index 0287564..8eb7e72 100644
--- a/core/java/android/app/SharedElementCallback.java
+++ b/core/java/android/app/SharedElementCallback.java
@@ -19,7 +19,6 @@
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.ColorSpace;
-import android.graphics.GraphicBuffer;
 import android.graphics.Matrix;
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
@@ -48,8 +47,8 @@
 public abstract class SharedElementCallback {
     private Matrix mTempMatrix;
     private static final String BUNDLE_SNAPSHOT_BITMAP = "sharedElement:snapshot:bitmap";
-    private static final String BUNDLE_SNAPSHOT_GRAPHIC_BUFFER =
-            "sharedElement:snapshot:graphicBuffer";
+    private static final String BUNDLE_SNAPSHOT_HARDWARE_BUFFER =
+            "sharedElement:snapshot:hardwareBuffer";
     private static final String BUNDLE_SNAPSHOT_COLOR_SPACE = "sharedElement:snapshot:colorSpace";
     private static final String BUNDLE_SNAPSHOT_IMAGE_SCALETYPE = "sharedElement:snapshot:imageScaleType";
     private static final String BUNDLE_SNAPSHOT_IMAGE_MATRIX = "sharedElement:snapshot:imageMatrix";
@@ -186,8 +185,8 @@
                     if (bitmap.getConfig() != Bitmap.Config.HARDWARE) {
                         bundle.putParcelable(BUNDLE_SNAPSHOT_BITMAP, bitmap);
                     } else {
-                        GraphicBuffer graphicBuffer = bitmap.createGraphicBufferHandle();
-                        bundle.putParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER, graphicBuffer);
+                        HardwareBuffer hardwareBuffer = bitmap.getHardwareBuffer();
+                        bundle.putParcelable(BUNDLE_SNAPSHOT_HARDWARE_BUFFER, hardwareBuffer);
                         ColorSpace cs = bitmap.getColorSpace();
                         if (cs != null) {
                             bundle.putInt(BUNDLE_SNAPSHOT_COLOR_SPACE, cs.getId());
@@ -235,7 +234,7 @@
         View view = null;
         if (snapshot instanceof Bundle) {
             Bundle bundle = (Bundle) snapshot;
-            GraphicBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_GRAPHIC_BUFFER);
+            HardwareBuffer buffer = bundle.getParcelable(BUNDLE_SNAPSHOT_HARDWARE_BUFFER);
             Bitmap bitmap = bundle.getParcelable(BUNDLE_SNAPSHOT_BITMAP);
             if (buffer == null && bitmap == null) {
                 return null;
@@ -246,8 +245,7 @@
                 if (colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length) {
                     colorSpace = ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]);
                 }
-                bitmap = Bitmap.wrapHardwareBuffer(HardwareBuffer.createFromGraphicBuffer(buffer),
-                                                   colorSpace);
+                bitmap = Bitmap.wrapHardwareBuffer(buffer, colorSpace);
             }
             ImageView imageView = new ImageView(context);
             view = imageView;
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 655dd9b..be87f5c 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -148,6 +148,7 @@
 import android.os.IPowerManager;
 import android.os.IRecoverySystem;
 import android.os.ISystemUpdateManager;
+import android.os.IThermalService;
 import android.os.IUserManager;
 import android.os.IncidentManager;
 import android.os.PowerManager;
@@ -185,6 +186,7 @@
 import android.telephony.TelephonyRegistryManager;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.Slog;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.WindowManager;
@@ -221,6 +223,8 @@
 public final class SystemServiceRegistry {
     private static final String TAG = "SystemServiceRegistry";
 
+    private static final boolean ENABLE_SERVICE_NOT_FOUND_WTF = true;
+
     // Service registry information.
     // This information is never changed once static initialization has completed.
     private static final Map<Class<?>, String> SYSTEM_SERVICE_NAMES =
@@ -576,10 +580,12 @@
                 new CachedServiceFetcher<PowerManager>() {
             @Override
             public PowerManager createService(ContextImpl ctx) throws ServiceNotFoundException {
-                IBinder b = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
-                IPowerManager service = IPowerManager.Stub.asInterface(b);
-                return new PowerManager(ctx.getOuterContext(),
-                        service, ctx.mMainThread.getHandler());
+                IBinder powerBinder = ServiceManager.getServiceOrThrow(Context.POWER_SERVICE);
+                IPowerManager powerService = IPowerManager.Stub.asInterface(powerBinder);
+                IBinder thermalBinder = ServiceManager.getServiceOrThrow(Context.THERMAL_SERVICE);
+                IThermalService thermalService = IThermalService.Stub.asInterface(thermalBinder);
+                return new PowerManager(ctx.getOuterContext(), powerService, thermalService,
+                        ctx.mMainThread.getHandler());
             }});
 
         registerService(Context.RECOVERY_SERVICE, RecoverySystem.class,
@@ -1370,8 +1376,29 @@
      * @hide
      */
     public static Object getSystemService(ContextImpl ctx, String name) {
-        ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
-        return fetcher != null ? fetcher.getService(ctx) : null;
+        if (name == null) {
+            return null;
+        }
+        final ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
+        if (ENABLE_SERVICE_NOT_FOUND_WTF && fetcher == null) {
+            // This should be a caller bug.
+            Slog.wtf(TAG, "Unknown manager requested: " + name);
+            return null;
+        }
+
+        final Object ret = fetcher.getService(ctx);
+        if (ENABLE_SERVICE_NOT_FOUND_WTF && ret == null) {
+            // Some services do return null in certain situations, so don't do WTF for them.
+            switch (name) {
+                case Context.CONTENT_CAPTURE_MANAGER_SERVICE:
+                case Context.APP_PREDICTION_SERVICE:
+                case Context.INCREMENTAL_SERVICE:
+                    return null;
+            }
+            Slog.wtf(TAG, "Manager wrapper not available: " + name);
+            return null;
+        }
+        return ret;
     }
 
     /**
@@ -1379,7 +1406,15 @@
      * @hide
      */
     public static String getSystemServiceName(Class<?> serviceClass) {
-        return SYSTEM_SERVICE_NAMES.get(serviceClass);
+        if (serviceClass == null) {
+            return null;
+        }
+        final String serviceName = SYSTEM_SERVICE_NAMES.get(serviceClass);
+        if (ENABLE_SERVICE_NOT_FOUND_WTF && serviceName == null) {
+            // This should be a caller bug.
+            Slog.wtf(TAG, "Unknown manager requested: " + serviceClass.getCanonicalName());
+        }
+        return serviceName;
     }
 
     /**
@@ -1676,7 +1711,9 @@
                         try {
                             cache.wait();
                         } catch (InterruptedException e) {
-                            Log.w(TAG, "getService() interrupted");
+                            // This shouldn't normally happen, but if someone interrupts the
+                            // thread, it will.
+                            Slog.wtf(TAG, "getService() interrupted");
                             Thread.currentThread().interrupt();
                             return null;
                         }
diff --git a/core/java/android/app/TaskEmbedder.java b/core/java/android/app/TaskEmbedder.java
index 761b225..5ebcc46 100644
--- a/core/java/android/app/TaskEmbedder.java
+++ b/core/java/android/app/TaskEmbedder.java
@@ -597,7 +597,7 @@
         if (mTmpDisplayMetrics == null) {
             mTmpDisplayMetrics = new DisplayMetrics();
         }
-        mContext.getDisplay().getMetrics(mTmpDisplayMetrics);
+        mContext.getDisplayNoVerify().getRealMetrics(mTmpDisplayMetrics);
         return mTmpDisplayMetrics.densityDpi;
     }
 
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 5f74d2e..d9405e1 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -2097,7 +2097,7 @@
 
         public ColorManagementProxy(@NonNull Context context) {
             // Get a list of supported wide gamut color spaces.
-            Display display = context.getDisplay();
+            Display display = context.getDisplayNoVerify();
             if (display != null) {
                 mSupportedColorSpaces.addAll(Arrays.asList(display.getSupportedWideColorGamut()));
             }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index d08dbc6..b219394 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -33,6 +33,7 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.annotation.UserHandleAware;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.Activity;
@@ -1416,6 +1417,7 @@
      * @see #setFactoryResetProtectionPolicy
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION)
     @SystemApi
     public static final String ACTION_RESET_PROTECTION_POLICY_CHANGED =
             "android.app.action.RESET_PROTECTION_POLICY_CHANGED";
@@ -5739,6 +5741,25 @@
     }
 
     /**
+     * Returns whether the admin has enabled always-on VPN lockdown for the current user.
+     *
+     * Only callable by the system.
+    * @hide
+    */
+    @UserHandleAware
+    public boolean isAlwaysOnVpnLockdownEnabled() {
+        throwIfParentInstance("isAlwaysOnVpnLockdownEnabled");
+        if (mService != null) {
+            try {
+                return mService.isAlwaysOnVpnLockdownEnabledForUser(myUserId());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
+
+    /**
      * Called by device or profile owner to query the set of packages that are allowed to access
      * the network directly when always-on VPN is in lockdown mode but not connected. Returns
      * {@code null} when always-on VPN is not active or not in lockdown mode.
@@ -5785,6 +5806,26 @@
     }
 
     /**
+     * Returns the VPN package name if the admin has enabled always-on VPN on the current user,
+     * or {@code null} if none is set.
+     *
+     * Only callable by the system.
+     * @hide
+     */
+    @UserHandleAware
+    public @Nullable String getAlwaysOnVpnPackage() {
+        throwIfParentInstance("getAlwaysOnVpnPackage");
+        if (mService != null) {
+            try {
+                return mService.getAlwaysOnVpnPackageForUser(myUserId());
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+        return null;
+    }
+
+    /**
      * Called by an application that is administering the device to disable all cameras on the
      * device, for this user. After setting this, no applications running as this user will be able
      * to access any cameras on the device.
@@ -8948,49 +8989,6 @@
     }
 
     /**
-     * Called by device owners to request a location provider to change its allowed state. For a
-     * provider to be enabled requires both that the master location setting is enabled, and that
-     * the provider itself is allowed. Most location providers are always allowed. Some location
-     * providers may have user consents or terms and conditions that must be accepted, or some other
-     * type of blocker before they are allowed however. Every location provider is responsible for
-     * its own allowed state.
-     *
-     * <p>This method requests that a location provider change its allowed state. For providers that
-     * are always allowed and have no state to change, this will have no effect. If the provider
-     * does require some consent, terms and conditions, or other blocking state, using this API
-     * implies that the device owner is agreeing/disagreeing to any consents, terms and conditions,
-     * etc, and the provider should make a best effort to adjust it's allowed state accordingly.
-     *
-     * <p>Location providers are generally only responsible for the current user, and callers must
-     * assume that this method will only affect provider state for the current user. Callers are
-     * responsible for tracking current user changes and re-updating provider state as necessary.
-     *
-     * <p>While providers are expected to make a best effort to honor this request, it is not a
-     * given that all providers will support such a request. If a provider does change its state as
-     * a result of this request, that may happen asynchronously after some delay. Test location
-     * providers set through {@link android.location.LocationManager#addTestProvider} will respond
-     * to this request to aide in testing.
-     *
-     * @param admin          Which {@link DeviceAdminReceiver} this request is associated with
-     * @param provider       A location provider as listed by
-     *                       {@link android.location.LocationManager#getAllProviders()}
-     * @param providerAllowed Whether the location provider is being requested to enable or disable
-     *                       itself
-     * @throws SecurityException if {@code admin} is not a device owner.
-     */
-    public void requestSetLocationProviderAllowed(@NonNull ComponentName admin,
-            @NonNull String provider, boolean providerAllowed) {
-        throwIfParentInstance("requestSetLocationProviderAllowed");
-        if (mService != null) {
-            try {
-                mService.requestSetLocationProviderAllowed(admin, provider, providerAllowed);
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
-        }
-    }
-
-    /**
      * Called by profile or device owners to update {@link android.provider.Settings.Secure}
      * settings. Validation that the value of the setting is in the correct form for the setting
      * type should be performed by the caller.
@@ -9934,20 +9932,27 @@
     }
 
     /**
-     * Called by device owner to control the security logging feature.
+     * Called by device owner or a profile owner of an organization-owned managed profile to
+     * control the security logging feature.
      *
      * <p> Security logs contain various information intended for security auditing purposes.
-     * See {@link SecurityEvent} for details.
+     * When security logging is enabled by a profile owner of
+     * an organization-owned managed profile, certain security logs are not visible (for example
+     * personal app launch events) or they will be redacted (for example, details of the physical
+     * volume mount events). Please see {@link SecurityEvent} for details.
      *
      * <p><strong>Note:</strong> The device owner won't be able to retrieve security logs if there
      * are unaffiliated secondary users or profiles on the device, regardless of whether the
      * feature is enabled. Logs will be discarded if the internal buffer fills up while waiting for
      * all users to become affiliated. Therefore it's recommended that affiliation ids are set for
-     * new users as soon as possible after provisioning via {@link #setAffiliationIds}.
+     * new users as soon as possible after provisioning via {@link #setAffiliationIds}. Profile
+     * owner of organization-owned managed profile is not subject to this restriction since all
+     * privacy-sensitive events happening outside the managed profile would have been redacted
+     * already.
      *
-     * @param admin Which device owner this request is associated with.
+     * @param admin Which device admin this request is associated with.
      * @param enabled whether security logging should be enabled or not.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * @throws SecurityException if {@code admin} is not allowed to control security logging.
      * @see #setAffiliationIds
      * @see #retrieveSecurityLogs
      */
@@ -9961,14 +9966,14 @@
     }
 
     /**
-     * Return whether security logging is enabled or not by the device owner.
+     * Return whether security logging is enabled or not by the admin.
      *
-     * <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
-     * thrown.
+     * <p>Can only be called by the device owner or a profile owner of an organization-owned
+     * managed profile, otherwise a {@link SecurityException} will be thrown.
      *
-     * @param admin Which device owner this request is associated with.
+     * @param admin Which device admin this request is associated with.
      * @return {@code true} if security logging is enabled by device owner, {@code false} otherwise.
-     * @throws SecurityException if {@code admin} is not a device owner.
+     * @throws SecurityException if {@code admin} is not allowed to control security logging.
      */
     public boolean isSecurityLoggingEnabled(@Nullable ComponentName admin) {
         throwIfParentInstance("isSecurityLoggingEnabled");
@@ -9980,20 +9985,21 @@
     }
 
     /**
-     * Called by device owner to retrieve all new security logging entries since the last call to
-     * this API after device boots.
+     * Called by device owner or profile owner of an organization-owned managed profile to retrieve
+     * all new security logging entries since the last call to this API after device boots.
      *
      * <p> Access to the logs is rate limited and it will only return new logs after the device
      * owner has been notified via {@link DeviceAdminReceiver#onSecurityLogsAvailable}.
      *
-     * <p>If there is any other user or profile on the device, it must be affiliated with the
-     * device. Otherwise a {@link SecurityException} will be thrown. See {@link #isAffiliatedUser}.
+     * <p> When called by a device owner, if there is any other user or profile on the device,
+     * it must be affiliated with the device. Otherwise a {@link SecurityException} will be thrown.
+     * See {@link #isAffiliatedUser}.
      *
-     * @param admin Which device owner this request is associated with.
+     * @param admin Which device admin this request is associated with.
      * @return the new batch of security logs which is a list of {@link SecurityEvent},
      * or {@code null} if rate limitation is exceeded or if logging is currently disabled.
-     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
-     * profile or secondary user that is not affiliated with the device.
+     * @throws SecurityException if {@code admin} is not allowed to access security logging,
+     * or there is at least one profile or secondary user that is not affiliated with the device.
      * @see #isAffiliatedUser
      * @see DeviceAdminReceiver#onSecurityLogsAvailable
      */
@@ -10126,21 +10132,23 @@
     }
 
     /**
-     * Called by device owners to retrieve device logs from before the device's last reboot.
+     * Called by device owner or profile owner of an organization-owned managed profile to retrieve
+     * device logs from before the device's last reboot.
      * <p>
      * <strong> This API is not supported on all devices. Calling this API on unsupported devices
      * will result in {@code null} being returned. The device logs are retrieved from a RAM region
      * which is not guaranteed to be corruption-free during power cycles, as a result be cautious
      * about data corruption when parsing. </strong>
      *
-     * <p>If there is any other user or profile on the device, it must be affiliated with the
-     * device. Otherwise a {@link SecurityException} will be thrown. See {@link #isAffiliatedUser}.
+     * <p> When called by a device owner, if there is any other user or profile on the device,
+     * it must be affiliated with the device. Otherwise a {@link SecurityException} will be thrown.
+     * See {@link #isAffiliatedUser}.
      *
-     * @param admin Which device owner this request is associated with.
+     * @param admin Which device admin this request is associated with.
      * @return Device logs from before the latest reboot of the system, or {@code null} if this API
      *         is not supported on the device.
-     * @throws SecurityException if {@code admin} is not a device owner, or there is at least one
-     * profile or secondary user that is not affiliated with the device.
+     * @throws SecurityException if {@code admin} is not allowed to access security logging, or
+     * there is at least one profile or secondary user that is not affiliated with the device.
      * @see #isAffiliatedUser
      * @see #retrieveSecurityLogs
      */
@@ -11989,4 +11997,21 @@
         }
         return 0;
     }
+
+    /**
+     * Returns {@code true} when {@code userId} has a profile owner that is capable of resetting
+     * password in RUNNING_LOCKED state. For that it should have at least one direct boot aware
+     * component and have an active password reset token. Can only be called by the system.
+     * @hide
+     */
+    public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
+        if (mService != null) {
+            try {
+                return mService.canProfileOwnerResetPasswordWhenLocked(userId);
+            } catch (RemoteException re) {
+                throw re.rethrowFromSystemServer();
+            }
+        }
+        return false;
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 84332ca..da48663 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -196,7 +196,9 @@
 
     boolean setAlwaysOnVpnPackage(in ComponentName who, String vpnPackage, boolean lockdown, in List<String> lockdownWhitelist);
     String getAlwaysOnVpnPackage(in ComponentName who);
+    String getAlwaysOnVpnPackageForUser(int userHandle);
     boolean isAlwaysOnVpnLockdownEnabled(in ComponentName who);
+    boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle);
     List<String> getAlwaysOnVpnLockdownWhitelist(in ComponentName who);
 
     void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
@@ -270,7 +272,6 @@
     boolean hasLockdownAdminConfiguredNetworks(in ComponentName who);
 
     void setLocationEnabled(in ComponentName who, boolean locationEnabled);
-    void requestSetLocationProviderAllowed(in ComponentName who, in String provider, boolean providerAllowed);
 
     boolean setTime(in ComponentName who, long millis);
     boolean setTimeZone(in ComponentName who, String timeZone);
@@ -478,4 +479,5 @@
 
     long getManagedProfileMaximumTimeOff(in ComponentName admin);
     void setManagedProfileMaximumTimeOff(in ComponentName admin, long timeoutMs);
+    boolean canProfileOwnerResetPasswordWhenLocked(in int userId);
 }
diff --git a/core/java/android/app/admin/SecurityLog.java b/core/java/android/app/admin/SecurityLog.java
index 91cf120..fb7f573 100644
--- a/core/java/android/app/admin/SecurityLog.java
+++ b/core/java/android/app/admin/SecurityLog.java
@@ -23,11 +23,13 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.util.EventLog.Event;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Objects;
 
@@ -104,7 +106,8 @@
     /**
      * Indicates that a shell command was issued over ADB via {@code adb shell <command>}
      * The log entry contains a {@code String} payload containing the shell command, accessible
-     * via {@link SecurityEvent#getData()}.
+     * via {@link SecurityEvent#getData()}. If security logging is enabled on organization-owned
+     * managed profile devices, the shell command will be redacted to an empty string.
      */
     public static final int TAG_ADB_SHELL_CMD = SecurityLogTags.SECURITY_ADB_SHELL_COMMAND;
 
@@ -133,6 +136,8 @@
      * <li> [3] app pid ({@code Integer})
      * <li> [4] seinfo tag ({@code String})
      * <li> [5] SHA-256 hash of the base APK in hexadecimal ({@code String})
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_APP_PROCESS_START = SecurityLogTags.SECURITY_APP_PROCESS_START;
 
@@ -205,7 +210,8 @@
      * following information about the event, encapsulated in an {@link Object} array and
      * accessible via {@link SecurityEvent#getData()}:
      * <li> [0] mount point ({@code String})
-     * <li> [1] volume label ({@code String}).
+     * <li> [1] volume label ({@code String}). Redacted to empty string on organization-owned
+     *     managed profile devices.
      */
     public static final int TAG_MEDIA_MOUNT = SecurityLogTags.SECURITY_MEDIA_MOUNTED;
 
@@ -214,7 +220,8 @@
      * following information about the event, encapsulated in an {@link Object} array and
      * accessible via {@link SecurityEvent#getData()}:
      * <li> [0] mount point ({@code String})
-     * <li> [1] volume label ({@code String}).
+     * <li> [1] volume label ({@code String}). Redacted to empty string on organization-owned
+     *     managed profile devices.
      */
     public static final int TAG_MEDIA_UNMOUNT = SecurityLogTags.SECURITY_MEDIA_UNMOUNTED;
 
@@ -340,6 +347,9 @@
      * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
      * <li> [1] alias of the key ({@code String})
      * <li> [2] requesting process uid ({@code Integer}).
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_KEY_GENERATED =
             SecurityLogTags.SECURITY_KEY_GENERATED;
@@ -351,6 +361,9 @@
      * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
      * <li> [1] alias of the key ({@code String})
      * <li> [2] requesting process uid ({@code Integer}).
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_KEY_IMPORT = SecurityLogTags.SECURITY_KEY_IMPORTED;
 
@@ -361,6 +374,9 @@
      * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
      * <li> [1] alias of the key ({@code String})
      * <li> [2] requesting process uid ({@code Integer}).
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_KEY_DESTRUCTION = SecurityLogTags.SECURITY_KEY_DESTROYED;
 
@@ -370,6 +386,11 @@
      * {@link Object} array and accessible via {@link SecurityEvent#getData()}:
      * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
      * <li> [1] subject of the certificate ({@code String}).
+     * <li> [2] which user the certificate is installed for ({@code Integer}), only available from
+     *   version {@link android.os.Build.VERSION_CODES#R}.
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_CERT_AUTHORITY_INSTALLED =
             SecurityLogTags.SECURITY_CERT_AUTHORITY_INSTALLED;
@@ -380,6 +401,11 @@
      * {@link Object} array and accessible via {@link SecurityEvent#getData()}:
      * <li> [0] result ({@code Integer}, 0 if operation failed, 1 if succeeded)
      * <li> [1] subject of the certificate ({@code String}).
+     * <li> [2] which user the certificate is removed from ({@code Integer}), only available from
+     *   version {@link android.os.Build.VERSION_CODES#R}.
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_CERT_AUTHORITY_REMOVED =
             SecurityLogTags.SECURITY_CERT_AUTHORITY_REMOVED;
@@ -422,6 +448,9 @@
      * {@link SecurityEvent#getData()}:
      * <li> [0] alias of the key ({@code String})
      * <li> [1] owner application uid ({@code Integer}).
+     *
+     * If security logging is enabled on organization-owned managed profile devices, only events
+     * happening inside the managed profile will be visible.
      */
     public static final int TAG_KEY_INTEGRITY_VIOLATION =
             SecurityLogTags.SECURITY_KEY_INTEGRITY_VIOLATION;
@@ -535,6 +564,16 @@
             return mEvent.getData();
         }
 
+        /** @hide */
+        public int getIntegerData(int index) {
+            return (Integer) ((Object[]) mEvent.getData())[index];
+        }
+
+        /** @hide */
+        public String getStringData(int index) {
+            return (String) ((Object[]) mEvent.getData())[index];
+        }
+
         /**
          * @hide
          */
@@ -554,7 +593,7 @@
          * Returns severity level for the event.
          */
         public @SecurityLogLevel int getLogLevel() {
-            switch (mEvent.getTag()) {
+            switch (getTag()) {
                 case TAG_ADB_SHELL_INTERACTIVE:
                 case TAG_ADB_SHELL_CMD:
                 case TAG_SYNC_RECV_FILE:
@@ -608,6 +647,75 @@
             return array.length >= 1 && array[0] instanceof Integer && (Integer) array[0] != 0;
         }
 
+        /**
+         * Returns a copy of the security event suitable to be consumed by the provided user.
+         * This method will either return the original event itself if the event does not contain
+         * any sensitive data; or a copy of itself but with sensitive information redacted; or
+         * {@code null} if the entire event should not be accessed by the given user.
+         *
+         * @param accessingUser which user this security event is to be accessed, must be a
+         *     concrete user id.
+         * @hide
+         */
+        public SecurityEvent redact(int accessingUser) {
+            // Which user the event is associated with, for the purpose of log redaction.
+            final int userId;
+            switch (getTag()) {
+                case SecurityLog.TAG_ADB_SHELL_CMD:
+                    return new SecurityEvent(getId(), mEvent.withNewData("").getBytes());
+                case SecurityLog.TAG_MEDIA_MOUNT:
+                case SecurityLog.TAG_MEDIA_UNMOUNT:
+                    // Partial redaction
+                    String mountPoint;
+                    try {
+                        mountPoint = getStringData(0);
+                    } catch (Exception e) {
+                        return null;
+                    }
+                    return new SecurityEvent(getId(),
+                            mEvent.withNewData(new Object[] {mountPoint, ""}).getBytes());
+                case SecurityLog.TAG_APP_PROCESS_START:
+                    try {
+                        userId = UserHandle.getUserId(getIntegerData(2));
+                    } catch (Exception e) {
+                        return null;
+                    }
+                    break;
+                case SecurityLog.TAG_CERT_AUTHORITY_INSTALLED:
+                case SecurityLog.TAG_CERT_AUTHORITY_REMOVED:
+                    try {
+                        userId = getIntegerData(2);
+                    } catch (Exception e) {
+                        return null;
+                    }
+                    break;
+                case SecurityLog.TAG_KEY_GENERATED:
+                case SecurityLog.TAG_KEY_IMPORT:
+                case SecurityLog.TAG_KEY_DESTRUCTION:
+                    try {
+                        userId = UserHandle.getUserId(getIntegerData(2));
+                    } catch (Exception e) {
+                        return null;
+                    }
+                    break;
+                case SecurityLog.TAG_KEY_INTEGRITY_VIOLATION:
+                    try {
+                        userId = UserHandle.getUserId(getIntegerData(1));
+                    } catch (Exception e) {
+                        return null;
+                    }
+                    break;
+                default:
+                    userId = UserHandle.USER_NULL;
+            }
+            // If the event is not user-specific, or matches the accessing user, return it
+            // unmodified, else redact by returning null
+            if (userId == UserHandle.USER_NULL || accessingUser == userId) {
+                return this;
+            } else {
+                return null;
+            }
+        }
 
         @Override
         public int describeContents() {
@@ -657,6 +765,30 @@
             return other != null && mEvent.equals(other.mEvent);
         }
     }
+
+    /**
+     * Redacts events in-place according to which user will consume the events.
+     *
+     * @param accessingUser which user will consume the redacted events, or UserHandle.USER_ALL if
+     *     redaction should be skipped.
+     * @hide
+     */
+    public static void redactEvents(ArrayList<SecurityEvent> logList, int accessingUser) {
+        if (accessingUser == UserHandle.USER_ALL) return;
+        int end = 0;
+        for (int i = 0; i < logList.size(); i++) {
+            SecurityEvent event = logList.get(i);
+            event = event.redact(accessingUser);
+            if (event != null) {
+                logList.set(end, event);
+                end++;
+            }
+        }
+        for (int i = logList.size() - 1; i >= end; i--) {
+            logList.remove(i);
+        }
+    }
+
     /**
      * Retrieve all security logs and return immediately.
      * @hide
diff --git a/core/java/android/app/admin/SecurityLogTags.logtags b/core/java/android/app/admin/SecurityLogTags.logtags
index 4e67fe2..100fd4c 100644
--- a/core/java/android/app/admin/SecurityLogTags.logtags
+++ b/core/java/android/app/admin/SecurityLogTags.logtags
@@ -33,8 +33,8 @@
 210026 security_key_destroyed                   (success|1),(key_id|3),(uid|1)
 210027 security_user_restriction_added          (package|3),(admin_user|1),(restriction|3)
 210028 security_user_restriction_removed        (package|3),(admin_user|1),(restriction|3)
-210029 security_cert_authority_installed        (success|1),(subject|3)
-210030 security_cert_authority_removed          (success|1),(subject|3)
+210029 security_cert_authority_installed        (success|1),(subject|3),(target_user|1)
+210030 security_cert_authority_removed          (success|1),(subject|3),(target_user|1)
 210031 security_crypto_self_test_completed      (success|1)
 210032 security_key_integrity_violation         (key_id|3),(uid|1)
 210033 security_cert_validation_failure         (reason|3)
diff --git a/core/java/android/app/compat/ChangeIdStateCache.java b/core/java/android/app/compat/ChangeIdStateCache.java
new file mode 100644
index 0000000..9ef63f6
--- /dev/null
+++ b/core/java/android/app/compat/ChangeIdStateCache.java
@@ -0,0 +1,86 @@
+/*
+ * 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.app.compat;
+
+import android.app.PropertyInvalidatedCache;
+import android.content.Context;
+import android.os.Binder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+import com.android.internal.compat.IPlatformCompat;
+
+/**
+ * Handles caching of calls to {@link com.android.internal.compat.IPlatformCompat}
+ * @hide
+ */
+public final class ChangeIdStateCache
+        extends PropertyInvalidatedCache<ChangeIdStateQuery, Boolean> {
+    private static final String CACHE_KEY = "cache_key.is_compat_change_enabled";
+    private static final int MAX_ENTRIES = 20;
+    private static boolean sDisabled = false;
+
+    /** @hide */
+    public ChangeIdStateCache() {
+        super(MAX_ENTRIES, CACHE_KEY);
+    }
+
+    /**
+     * Disable cache.
+     *
+     * <p>Should only be used in unit tests.
+     * @hide
+     */
+    public static void disable() {
+        sDisabled = true;
+    }
+
+    /**
+     * Invalidate the cache.
+     *
+     * <p>Can only be called by the system server process.
+     * @hide
+     */
+    public static void invalidate() {
+        if (!sDisabled) {
+            PropertyInvalidatedCache.invalidateCache(CACHE_KEY);
+        }
+    }
+
+    @Override
+    protected Boolean recompute(ChangeIdStateQuery query) {
+        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
+                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
+        final long token = Binder.clearCallingIdentity();
+        try {
+            if (query.type == ChangeIdStateQuery.QUERY_BY_PACKAGE_NAME) {
+                return platformCompat.isChangeEnabledByPackageName(query.changeId,
+                                                                   query.packageName,
+                                                                   query.userId);
+            } else if (query.type == ChangeIdStateQuery.QUERY_BY_UID) {
+                return platformCompat.isChangeEnabledByUid(query.changeId, query.uid);
+            } else {
+                throw new IllegalArgumentException("Invalid query type: " + query.type);
+            }
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        throw new IllegalStateException("Could not recompute value!");
+    }
+}
diff --git a/core/java/android/app/compat/ChangeIdStateQuery.java b/core/java/android/app/compat/ChangeIdStateQuery.java
new file mode 100644
index 0000000..2c4c120
--- /dev/null
+++ b/core/java/android/app/compat/ChangeIdStateQuery.java
@@ -0,0 +1,87 @@
+/*
+ * 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.app.compat;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+
+/**
+ * A key type for caching calls to {@link com.android.internal.compat.IPlatformCompat}
+ *
+ * <p>For {@link com.android.internal.compat.IPlatformCompat#isChangeEnabledByPackageName}
+ * and {@link com.android.internal.compat.IPlatformCompat#isChangeEnabledByUid}
+ *
+ * @hide
+ */
+final class ChangeIdStateQuery {
+
+    static final int QUERY_BY_PACKAGE_NAME = 0;
+    static final int QUERY_BY_UID = 1;
+    @IntDef({QUERY_BY_PACKAGE_NAME, QUERY_BY_UID})
+    @Retention(RetentionPolicy.SOURCE)
+    @interface QueryType {}
+
+    public @QueryType int type;
+    public long changeId;
+    public String packageName;
+    public int uid;
+    public int userId;
+
+    private ChangeIdStateQuery(@QueryType int type, long changeId, String packageName,
+                               int uid, int userId) {
+        this.type = type;
+        this.changeId = changeId;
+        this.packageName = packageName;
+        this.uid = uid;
+        this.userId = userId;
+    }
+
+    static ChangeIdStateQuery byPackageName(long changeId, @NonNull String packageName,
+                                            int userId) {
+        return new ChangeIdStateQuery(QUERY_BY_PACKAGE_NAME, changeId, packageName, 0, userId);
+    }
+
+    static ChangeIdStateQuery byUid(long changeId, int uid) {
+        return new ChangeIdStateQuery(QUERY_BY_UID, changeId, null, uid, 0);
+    }
+
+    @Override
+    public boolean equals(Object other) {
+        if (this == other) {
+            return true;
+        }
+        if ((other == null) || !(other instanceof ChangeIdStateQuery)) {
+            return false;
+        }
+        final ChangeIdStateQuery that = (ChangeIdStateQuery) other;
+        return this.type == that.type
+            && this.changeId == that.changeId
+            && Objects.equals(this.packageName, that.packageName)
+            && this.uid == that.uid
+            && this.userId == that.userId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, changeId, packageName, uid, userId);
+    }
+}
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index e289a27..0d5e45f 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -19,14 +19,8 @@
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.compat.Compatibility;
-import android.content.Context;
-import android.os.Binder;
-import android.os.RemoteException;
-import android.os.ServiceManager;
 import android.os.UserHandle;
 
-import com.android.internal.compat.IPlatformCompat;
-
 /**
  * CompatChanges APIs - to be used by platform code only (including mainline
  * modules).
@@ -35,6 +29,7 @@
  */
 @SystemApi
 public final class CompatChanges {
+    private static final ChangeIdStateCache QUERY_CACHE = new ChangeIdStateCache();
     private CompatChanges() {}
 
     /**
@@ -69,17 +64,8 @@
      */
     public static boolean isChangeEnabled(long changeId, @NonNull String packageName,
             @NonNull UserHandle user) {
-        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-        final long token = Binder.clearCallingIdentity();
-        try {
-            return platformCompat.isChangeEnabledByPackageName(changeId, packageName,
-                    user.getIdentifier());
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+        return QUERY_CACHE.query(ChangeIdStateQuery.byPackageName(changeId, packageName,
+                                                           user.getIdentifier()));
     }
 
     /**
@@ -101,15 +87,7 @@
      * @return {@code true} if the change is enabled for the current app.
      */
     public static boolean isChangeEnabled(long changeId, int uid) {
-        IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(
-                ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
-        final long token = Binder.clearCallingIdentity();
-        try {
-            return platformCompat.isChangeEnabledByUid(changeId, uid);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
+        return QUERY_CACHE.query(ChangeIdStateQuery.byUid(changeId, uid));
     }
+
 }
diff --git a/core/java/android/app/trust/IStrongAuthTracker.aidl b/core/java/android/app/trust/IStrongAuthTracker.aidl
index 36c71bf..6d54396 100644
--- a/core/java/android/app/trust/IStrongAuthTracker.aidl
+++ b/core/java/android/app/trust/IStrongAuthTracker.aidl
@@ -23,4 +23,5 @@
  */
 oneway interface IStrongAuthTracker {
     void onStrongAuthRequiredChanged(int strongAuthRequired, int userId);
+    void onIsNonStrongBiometricAllowedChanged(boolean allowed, int userId);
 }
\ No newline at end of file
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 5b60b85..3e1a480 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -25,6 +25,7 @@
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.app.PropertyInvalidatedCache;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Handler;
@@ -1299,6 +1300,31 @@
         return false;
     }
 
+    private static final String BLUETOOTH_BONDING_CACHE_PROPERTY =
+            "cache_key.bluetooth.get_bond_state";
+    private final PropertyInvalidatedCache<BluetoothDevice, Integer> mBluetoothBondCache =
+            new PropertyInvalidatedCache<BluetoothDevice, Integer>(
+                8, BLUETOOTH_BONDING_CACHE_PROPERTY) {
+                @Override
+                protected Integer recompute(BluetoothDevice query) {
+                    try {
+                        return sService.getBondState(query);
+                    } catch (RemoteException e) {
+                        throw e.rethrowAsRuntimeException();
+                    }
+                }
+            };
+
+    /** @hide */
+    public void disableBluetoothGetBondStateCache() {
+        mBluetoothBondCache.disableLocal();
+    }
+
+    /** @hide */
+    public static void invalidateBluetoothGetBondStateCache() {
+        PropertyInvalidatedCache.invalidateCache(BLUETOOTH_BONDING_CACHE_PROPERTY);
+    }
+
     /**
      * Get the bond state of the remote device.
      * <p>Possible values for the bond state are:
@@ -1316,9 +1342,13 @@
             return BOND_NONE;
         }
         try {
-            return service.getBondState(this);
-        } catch (RemoteException e) {
-            Log.e(TAG, "", e);
+            return mBluetoothBondCache.query(this);
+        } catch (RuntimeException e) {
+            if (e.getCause() instanceof RemoteException) {
+                Log.e(TAG, "", e);
+            } else {
+                throw e;
+            }
         }
         return BOND_NONE;
     }
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index e1942da..bd3298c 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -580,6 +580,15 @@
         }
 
         @Override
+        public void canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
+                RemoteCallback callback) {
+            final Bundle result = new Bundle();
+            result.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
+                    canonicalize(callingPkg, featureId, uri));
+            callback.sendResult(result);
+        }
+
+        @Override
         public Uri uncanonicalize(String callingPkg, String featureId,  Uri uri) {
             uri = validateIncomingUri(uri);
             int userId = getUserIdFromUri(uri);
diff --git a/core/java/android/content/ContentProviderNative.java b/core/java/android/content/ContentProviderNative.java
index 0f1442d..7bc5901 100644
--- a/core/java/android/content/ContentProviderNative.java
+++ b/core/java/android/content/ContentProviderNative.java
@@ -359,6 +359,16 @@
                     return true;
                 }
 
+                case CANONICALIZE_ASYNC_TRANSACTION: {
+                    data.enforceInterface(IContentProvider.descriptor);
+                    String callingPkg = data.readString();
+                    String featureId = data.readString();
+                    Uri uri = Uri.CREATOR.createFromParcel(data);
+                    RemoteCallback callback = RemoteCallback.CREATOR.createFromParcel(data);
+                    canonicalizeAsync(callingPkg, featureId, uri, callback);
+                    return true;
+                }
+
                 case UNCANONICALIZE_TRANSACTION:
                 {
                     data.enforceInterface(IContentProvider.descriptor);
@@ -823,6 +833,25 @@
     }
 
     @Override
+    /* oneway */ public void canonicalizeAsync(String callingPkg, @Nullable String featureId,
+            Uri uri, RemoteCallback callback) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        try {
+            data.writeInterfaceToken(IContentProvider.descriptor);
+
+            data.writeString(callingPkg);
+            data.writeString(featureId);
+            uri.writeToParcel(data, 0);
+            callback.writeToParcel(data, 0);
+
+            mRemote.transact(IContentProvider.CANONICALIZE_ASYNC_TRANSACTION, data, null,
+                    Binder.FLAG_ONEWAY);
+        } finally {
+            data.recycle();
+        }
+    }
+
+    @Override
     public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri url)
             throws RemoteException {
         Parcel data = Parcel.obtain();
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 0e0161f..b748cfa 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -712,14 +712,17 @@
      * {@link #CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS}.
      * @hide
      */
-    public static final int CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS =
+    public static final int CONTENT_PROVIDER_READY_TIMEOUT_MILLIS =
             CONTENT_PROVIDER_PUBLISH_TIMEOUT_MILLIS + 10 * 1000;
 
+    // Timeout given a ContentProvider that has already been started and connected to.
+    private static final int CONTENT_PROVIDER_TIMEOUT_MILLIS = 3 * 1000;
+
     // Should be >= {@link #CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS}, because that's how
     // long ActivityManagerService is giving a content provider to get published if a new process
     // needs to be started for that.
-    private static final int GET_TYPE_TIMEOUT_MILLIS =
-            CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS + 5 * 1000;
+    private static final int REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS =
+            CONTENT_PROVIDER_READY_TIMEOUT_MILLIS + CONTENT_PROVIDER_TIMEOUT_MILLIS;
 
     public ContentResolver(@Nullable Context context) {
         this(context, null);
@@ -833,10 +836,10 @@
         IContentProvider provider = acquireExistingProvider(url);
         if (provider != null) {
             try {
-                final GetTypeResultListener resultListener = new GetTypeResultListener();
+                final StringResultListener resultListener = new StringResultListener();
                 provider.getTypeAsync(url, new RemoteCallback(resultListener));
-                resultListener.waitForResult();
-                return resultListener.type;
+                resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
+                return resultListener.result;
             } catch (RemoteException e) {
                 // Arbitrary and not worth documenting, as Activity
                 // Manager will kill this process shortly anyway.
@@ -854,13 +857,13 @@
         }
 
         try {
-            GetTypeResultListener resultListener = new GetTypeResultListener();
+            final StringResultListener resultListener = new StringResultListener();
             ActivityManager.getService().getProviderMimeTypeAsync(
                     ContentProvider.getUriWithoutUserId(url),
                     resolveUserId(url),
                     new RemoteCallback(resultListener));
-            resultListener.waitForResult();
-            return resultListener.type;
+            resultListener.waitForResult(REMOTE_CONTENT_PROVIDER_TIMEOUT_MILLIS);
+            return resultListener.result;
         } catch (RemoteException e) {
             // We just failed to send a oneway request to the System Server. Nothing to do.
             return null;
@@ -870,27 +873,29 @@
         }
     }
 
-    private static class GetTypeResultListener implements RemoteCallback.OnResultListener {
+    private abstract static class ResultListener<T> implements RemoteCallback.OnResultListener {
         @GuardedBy("this")
         public boolean done;
 
         @GuardedBy("this")
-        public String type;
+        public T result;
 
         @Override
         public void onResult(Bundle result) {
             synchronized (this) {
-                type = result.getString(REMOTE_CALLBACK_RESULT);
+                this.result = getResultFromBundle(result);
                 done = true;
                 notifyAll();
             }
         }
 
-        public void waitForResult() {
+        protected abstract T getResultFromBundle(Bundle result);
+
+        public void waitForResult(long timeout) {
             synchronized (this) {
                 if (!done) {
                     try {
-                        wait(GET_TYPE_TIMEOUT_MILLIS);
+                        wait(timeout);
                     } catch (InterruptedException e) {
                         // Ignore
                     }
@@ -899,6 +904,20 @@
         }
     }
 
+    private static class StringResultListener extends ResultListener<String> {
+        @Override
+        protected String getResultFromBundle(Bundle result) {
+            return result.getString(REMOTE_CALLBACK_RESULT);
+        }
+    }
+
+    private static class UriResultListener extends ResultListener<Uri> {
+        @Override
+        protected Uri getResultFromBundle(Bundle result) {
+            return result.getParcelable(REMOTE_CALLBACK_RESULT);
+        }
+    }
+
     /**
      * Query for the possible MIME types for the representations the given
      * content URL can be returned when opened as as stream with
@@ -1192,7 +1211,11 @@
         }
 
         try {
-            return provider.canonicalize(mPackageName, mFeatureId, url);
+            final UriResultListener resultListener = new UriResultListener();
+            provider.canonicalizeAsync(mPackageName, mFeatureId, url,
+                    new RemoteCallback(resultListener));
+            resultListener.waitForResult(CONTENT_PROVIDER_TIMEOUT_MILLIS);
+            return resultListener.result;
         } catch (RemoteException e) {
             // Arbitrary and not worth documenting, as Activity
             // Manager will kill this process shortly anyway.
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ae12de0..c6e84b7 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3495,13 +3495,23 @@
      * <dl>
      *  <dt> {@link #WINDOW_SERVICE} ("window")
      *  <dd> The top-level window manager in which you can place custom
-     *  windows.  The returned object is a {@link android.view.WindowManager}.
+     *  windows.  The returned object is a {@link android.view.WindowManager}. Must only be obtained
+     *  from a visual context such as Activity or a Context created with
+     *  {@link #createWindowContext(int, Bundle)}, which are adjusted to the configuration and
+     *  visual bounds of an area on screen.
      *  <dt> {@link #LAYOUT_INFLATER_SERVICE} ("layout_inflater")
      *  <dd> A {@link android.view.LayoutInflater} for inflating layout resources
-     *  in this context.
+     *  in this context. Must only be obtained from a visual context such as Activity or a Context
+     *  created with {@link #createWindowContext(int, Bundle)}, which are adjusted to the
+     *  configuration and visual bounds of an area on screen.
      *  <dt> {@link #ACTIVITY_SERVICE} ("activity")
      *  <dd> A {@link android.app.ActivityManager} for interacting with the
      *  global activity state of the system.
+     *  <dt> {@link #WALLPAPER_SERVICE} ("wallpaper")
+     *  <dd> A {@link android.service.wallpaper.WallpaperService} for accessing wallpapers in this
+     *  context. Must only be obtained from a visual context such as Activity or a Context created
+     *  with {@link #createWindowContext(int, Bundle)}, which are adjusted to the configuration and
+     *  visual bounds of an area on screen.
      *  <dt> {@link #POWER_SERVICE} ("power")
      *  <dd> A {@link android.os.PowerManager} for controlling power
      *  management.
@@ -5901,6 +5911,8 @@
      * {@link #createDisplayContext(Display)} to get a display object associated with a Context, or
      * {@link android.hardware.display.DisplayManager#getDisplay} to get a display object by id.
      * @return Returns the {@link Display} object this context is associated with.
+     * @throws UnsupportedOperationException if the method is called on an instance that is not
+     *         associated with any display.
      */
     @Nullable
     public Display getDisplay() {
@@ -5908,6 +5920,17 @@
     }
 
     /**
+     * A version of {@link #getDisplay()} that does not perform a Context misuse check to be used by
+     * legacy APIs.
+     * TODO(b/149790106): Fix usages and remove.
+     * @hide
+     */
+    @Nullable
+    public Display getDisplayNoVerify() {
+        throw new RuntimeException("Not implemented. Must override in a subclass.");
+    }
+
+    /**
      * Gets the ID of the display this context is associated with.
      *
      * @return display ID associated with this {@link Context}.
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index f6515e8..e5381ea 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -1003,6 +1003,12 @@
         return mBase.getDisplay();
     }
 
+    /** @hide */
+    @Override
+    public @Nullable Display getDisplayNoVerify() {
+        return mBase.getDisplayNoVerify();
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/content/IContentProvider.java b/core/java/android/content/IContentProvider.java
index 4658ba1..37643da 100644
--- a/core/java/android/content/IContentProvider.java
+++ b/core/java/android/content/IContentProvider.java
@@ -45,7 +45,7 @@
     public String getType(Uri url) throws RemoteException;
 
     /**
-     * An oneway version of getType. The functionality is exactly the same, except that the
+     * A oneway version of getType. The functionality is exactly the same, except that the
      * call returns immediately, and the resulting type is returned when available via
      * a binder callback.
      */
@@ -126,6 +126,14 @@
     public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
             throws RemoteException;
 
+    /**
+     * A oneway version of canonicalize. The functionality is exactly the same, except that the
+     * call returns immediately, and the resulting type is returned when available via
+     * a binder callback.
+     */
+    void canonicalizeAsync(String callingPkg, @Nullable String featureId, Uri uri,
+            RemoteCallback callback) throws RemoteException;
+
     public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
             throws RemoteException;
 
@@ -162,4 +170,5 @@
     static final int REFRESH_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 26;
     static final int CHECK_URI_PERMISSION_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 27;
     int GET_TYPE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 28;
+    int CANONICALIZE_ASYNC_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION + 29;
 }
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2e591ca..acc4cb0 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -6478,6 +6478,21 @@
     public static final int FLAG_ACTIVITY_MATCH_EXTERNAL = 0x00000800;
 
     /**
+     * If set in an intent passed to {@link Context#startActivity Context.startActivity()}, this
+     * flag will only launch the intent if it resolves to a result that is not a browser. If no such
+     * result exists, an {@link ActivityNotFoundException} will be thrown.
+     */
+    public static final int FLAG_ACTIVITY_REQUIRE_NON_BROWSER = 0x00000400;
+
+    /**
+     * If set in an intent passed to {@link Context#startActivity Context.startActivity()}, this
+     * flag will only launch the intent if it resolves to a single result. If no such result exists
+     * or if the system chooser would otherwise be displayed, an {@link ActivityNotFoundException}
+     * will be thrown.
+     */
+    public static final int FLAG_ACTIVITY_REQUIRE_DEFAULT = 0x00000200;
+
+    /**
      * If set, when sending a broadcast only registered receivers will be
      * called -- no BroadcastReceiver components will be launched.
      */
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 73c1e2f..61128f2 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -41,7 +41,9 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
+import java.util.function.BiConsumer;
 
 /**
  * Structured description of Intent values to be matched.  An IntentFilter can
@@ -153,7 +155,9 @@
     private static final String AUTH_STR = "auth";
     private static final String SSP_STR = "ssp";
     private static final String SCHEME_STR = "scheme";
+    private static final String STATIC_TYPE_STR = "staticType";
     private static final String TYPE_STR = "type";
+    private static final String GROUP_STR = "group";
     private static final String CAT_STR = "cat";
     private static final String NAME_STR = "name";
     private static final String ACTION_STR = "action";
@@ -280,8 +284,11 @@
     private ArrayList<PatternMatcher> mDataSchemeSpecificParts = null;
     private ArrayList<AuthorityEntry> mDataAuthorities = null;
     private ArrayList<PatternMatcher> mDataPaths = null;
+    private ArrayList<String> mStaticDataTypes = null;
     private ArrayList<String> mDataTypes = null;
-    private boolean mHasPartialTypes = false;
+    private ArrayList<String> mMimeGroups = null;
+    private boolean mHasStaticPartialTypes = false;
+    private boolean mHasDynamicPartialTypes = false;
 
     private static final int STATE_VERIFY_AUTO         = 0x00000001;
     private static final int STATE_NEED_VERIFY         = 0x00000010;
@@ -454,6 +461,9 @@
         if (o.mCategories != null) {
             mCategories = new ArrayList<String>(o.mCategories);
         }
+        if (o.mStaticDataTypes != null) {
+            mStaticDataTypes = new ArrayList<String>(o.mStaticDataTypes);
+        }
         if (o.mDataTypes != null) {
             mDataTypes = new ArrayList<String>(o.mDataTypes);
         }
@@ -469,7 +479,11 @@
         if (o.mDataPaths != null) {
             mDataPaths = new ArrayList<PatternMatcher>(o.mDataPaths);
         }
-        mHasPartialTypes = o.mHasPartialTypes;
+        if (o.mMimeGroups != null) {
+            mMimeGroups = new ArrayList<String>(o.mMimeGroups);
+        }
+        mHasStaticPartialTypes = o.mHasStaticPartialTypes;
+        mHasDynamicPartialTypes = o.mHasDynamicPartialTypes;
         mVerifyState = o.mVerifyState;
         mInstantAppVisibility = o.mInstantAppVisibility;
     }
@@ -776,25 +790,108 @@
      */
     public final void addDataType(String type)
         throws MalformedMimeTypeException {
+        processMimeType(type, (internalType, isPartial) -> {
+            if (mDataTypes == null) {
+                mDataTypes = new ArrayList<>();
+            }
+            if (mStaticDataTypes == null) {
+                mStaticDataTypes = new ArrayList<>();
+            }
+
+            if (mDataTypes.contains(internalType)) {
+                return;
+            }
+
+            mDataTypes.add(internalType.intern());
+            mStaticDataTypes.add(internalType.intern());
+            mHasStaticPartialTypes = mHasStaticPartialTypes || isPartial;
+        });
+    }
+
+    /**
+     * Add a new Intent data type <em>from MIME group</em> to match against.  If any types are
+     * included in the filter, then an Intent's data must be <em>either</em>
+     * one of these types <em>or</em> a matching scheme.  If no data types
+     * are included, then an Intent will only match if it specifies no data.
+     *
+     * <p><em>Note: MIME type matching in the Android framework is
+     * case-sensitive, unlike formal RFC MIME types.  As a result,
+     * you should always write your MIME types with lower case letters,
+     * and any MIME types you receive from outside of Android should be
+     * converted to lower case before supplying them here.</em></p>
+     *
+     * <p>Throws {@link MalformedMimeTypeException} if the given MIME type is
+     * not syntactically correct.
+     *
+     * @param type Name of the data type to match, such as "vnd.android.cursor.dir/person".
+     *
+     * @see #clearDynamicDataTypes()
+     * @hide
+     */
+    public final void addDynamicDataType(String type)
+            throws MalformedMimeTypeException {
+        processMimeType(type, (internalType, isPartial) -> {
+            if (mDataTypes == null) {
+                mDataTypes = new ArrayList<>();
+            }
+
+            if (!mDataTypes.contains(internalType)) {
+                mDataTypes.add(internalType.intern());
+
+                mHasDynamicPartialTypes = mHasDynamicPartialTypes || isPartial;
+            }
+        });
+    }
+
+    /**
+     * Process mime type - convert to representation used internally and check if type is partial,
+     * and then call provided action
+     */
+    private void processMimeType(String type, BiConsumer<String, Boolean> action)
+            throws MalformedMimeTypeException {
         final int slashpos = type.indexOf('/');
         final int typelen = type.length();
-        if (slashpos > 0 && typelen >= slashpos+2) {
-            if (mDataTypes == null) mDataTypes = new ArrayList<String>();
-            if (typelen == slashpos+2 && type.charAt(slashpos+1) == '*') {
-                String str = type.substring(0, slashpos);
-                if (!mDataTypes.contains(str)) {
-                    mDataTypes.add(str.intern());
-                }
-                mHasPartialTypes = true;
-            } else {
-                if (!mDataTypes.contains(type)) {
-                    mDataTypes.add(type.intern());
-                }
-            }
+        if (slashpos <= 0 || typelen < slashpos + 2) {
+            throw new MalformedMimeTypeException(type);
+        }
+
+        String internalType = type;
+        boolean isPartialType = false;
+        if (typelen == slashpos + 2 && type.charAt(slashpos + 1) == '*') {
+            internalType = type.substring(0, slashpos);
+            isPartialType = true;
+        }
+
+        action.accept(internalType, isPartialType);
+    }
+
+    /**
+     * Remove all previously added Intent data types from IntentFilter.
+     *
+     * @see #addDynamicDataType(String)
+     * @hide
+     */
+    public final void clearDynamicDataTypes() {
+        if (mDataTypes == null) {
             return;
         }
 
-        throw new MalformedMimeTypeException(type);
+        if (mStaticDataTypes != null) {
+            mDataTypes.clear();
+            mDataTypes.addAll(mStaticDataTypes);
+        } else {
+            mDataTypes = null;
+        }
+
+        mHasDynamicPartialTypes = false;
+    }
+
+    /**
+     * Return the number of static data types in the filter.
+     * @hide
+     */
+    public int countStaticDataTypes() {
+        return mStaticDataTypes != null ? mStaticDataTypes.size() : 0;
     }
 
     /**
@@ -815,6 +912,16 @@
         return mDataTypes != null && mDataTypes.contains(type);
     }
 
+    /** @hide */
+    public final boolean hasExactDynamicDataType(String type) {
+        return hasExactDataType(type) && !hasExactStaticDataType(type);
+    }
+
+    /** @hide */
+    public final boolean hasExactStaticDataType(String type) {
+        return mStaticDataTypes != null && mStaticDataTypes.contains(type);
+    }
+
     /**
      * Return the number of data types in the filter.
      */
@@ -837,6 +944,44 @@
     }
 
     /**
+     * Return copy of filter's data types.
+     * @hide
+     */
+    public final List<String> dataTypes() {
+        return mDataTypes != null ? new ArrayList<>(mDataTypes) : null;
+    }
+
+    /** @hide */
+    public final void addMimeGroup(String name) {
+        if (mMimeGroups == null) {
+            mMimeGroups = new ArrayList<>();
+        }
+        if (!mMimeGroups.contains(name)) {
+            mMimeGroups.add(name);
+        }
+    }
+
+    /** @hide */
+    public final boolean hasMimeGroup(String name) {
+        return mMimeGroups != null && mMimeGroups.contains(name);
+    }
+
+    /** @hide */
+    public final String getMimeGroup(int index) {
+        return mMimeGroups.get(index);
+    }
+
+    /** @hide */
+    public final int countMimeGroups() {
+        return mMimeGroups != null ? mMimeGroups.size() : 0;
+    }
+
+    /** @hide */
+    public final Iterator<String> mimeGroupsIterator() {
+        return mMimeGroups != null ? mMimeGroups.iterator() : null;
+    }
+
+    /**
      * Add a new Intent data scheme to match against.  If any schemes are
      * included in the filter, then an Intent's data must be <em>either</em>
      * one of these schemes <em>or</em> a matching data type.  If no schemes
@@ -1617,13 +1762,12 @@
             serializer.attribute(null, NAME_STR, mCategories.get(i));
             serializer.endTag(null, CAT_STR);
         }
-        N = countDataTypes();
+        writeDataTypesToXml(serializer);
+        N = countMimeGroups();
         for (int i=0; i<N; i++) {
-            serializer.startTag(null, TYPE_STR);
-            String type = mDataTypes.get(i);
-            if (type.indexOf('/') < 0) type = type + "/*";
-            serializer.attribute(null, NAME_STR, type);
-            serializer.endTag(null, TYPE_STR);
+            serializer.startTag(null, GROUP_STR);
+            serializer.attribute(null, NAME_STR, mMimeGroups.get(i));
+            serializer.endTag(null, GROUP_STR);
         }
         N = countDataSchemes();
         for (int i=0; i<N; i++) {
@@ -1683,6 +1827,46 @@
         }
     }
 
+    /**
+     * Write data types (both static and dynamic) to XML.
+     * In implementation we rely on two facts:
+     * - {@link #mStaticDataTypes} is subsequence of {@link #mDataTypes}
+     * - both {@link #mStaticDataTypes} and {@link #mDataTypes} does not contain duplicates
+     */
+    private void writeDataTypesToXml(XmlSerializer serializer) throws IOException {
+        if (mStaticDataTypes == null) {
+            return;
+        }
+
+        int i = 0;
+        for (String staticType: mStaticDataTypes) {
+            while (!mDataTypes.get(i).equals(staticType)) {
+                writeDataTypeToXml(serializer, mDataTypes.get(i), TYPE_STR);
+                i++;
+            }
+
+            writeDataTypeToXml(serializer, staticType, STATIC_TYPE_STR);
+            i++;
+        }
+
+        while (i < mDataTypes.size()) {
+            writeDataTypeToXml(serializer, mDataTypes.get(i), TYPE_STR);
+            i++;
+        }
+    }
+
+    private void writeDataTypeToXml(XmlSerializer serializer, String type, String tag)
+            throws IOException {
+        serializer.startTag(null, tag);
+
+        if (type.indexOf('/') < 0) {
+            type = type + "/*";
+        }
+
+        serializer.attribute(null, NAME_STR, type);
+        serializer.endTag(null, tag);
+    }
+
     public void readFromXml(XmlPullParser parser) throws XmlPullParserException,
             IOException {
         String autoVerify = parser.getAttributeValue(null, AUTO_VERIFY_STR);
@@ -1709,7 +1893,7 @@
                 if (name != null) {
                     addCategory(name);
                 }
-            } else if (tagName.equals(TYPE_STR)) {
+            } else if (tagName.equals(STATIC_TYPE_STR)) {
                 String name = parser.getAttributeValue(null, NAME_STR);
                 if (name != null) {
                     try {
@@ -1717,6 +1901,19 @@
                     } catch (MalformedMimeTypeException e) {
                     }
                 }
+            } else if (tagName.equals(TYPE_STR)) {
+                String name = parser.getAttributeValue(null, NAME_STR);
+                if (name != null) {
+                    try {
+                        addDynamicDataType(name);
+                    } catch (MalformedMimeTypeException e) {
+                    }
+                }
+            } else if (tagName.equals(GROUP_STR)) {
+                String name = parser.getAttributeValue(null, NAME_STR);
+                if (name != null) {
+                    addMimeGroup(name);
+                }
             } else if (tagName.equals(SCHEME_STR)) {
                 String name = parser.getAttributeValue(null, NAME_STR);
                 if (name != null) {
@@ -1802,9 +1999,15 @@
                 proto.write(IntentFilterProto.DATA_TYPES, it.next());
             }
         }
-        if (mPriority != 0 || mHasPartialTypes) {
+        if (mMimeGroups != null) {
+            Iterator<String> it = mMimeGroups.iterator();
+            while (it.hasNext()) {
+                proto.write(IntentFilterProto.MIME_GROUPS, it.next());
+            }
+        }
+        if (mPriority != 0 || hasPartialTypes()) {
             proto.write(IntentFilterProto.PRIORITY, mPriority);
-            proto.write(IntentFilterProto.HAS_PARTIAL_TYPES, mHasPartialTypes);
+            proto.write(IntentFilterProto.HAS_PARTIAL_TYPES, hasPartialTypes());
         }
         proto.write(IntentFilterProto.GET_AUTO_VERIFY, getAutoVerify());
         proto.end(token);
@@ -1871,20 +2074,45 @@
                 du.println(sb.toString());
             }
         }
-        if (mDataTypes != null) {
-            Iterator<String> it = mDataTypes.iterator();
+        if (mStaticDataTypes != null) {
+            Iterator<String> it = mStaticDataTypes.iterator();
             while (it.hasNext()) {
                 sb.setLength(0);
-                sb.append(prefix); sb.append("Type: \"");
-                        sb.append(it.next()); sb.append("\"");
+                sb.append(prefix); sb.append("StaticType: \"");
+                sb.append(it.next()); sb.append("\"");
                 du.println(sb.toString());
             }
         }
-        if (mPriority != 0 || mOrder != 0 || mHasPartialTypes) {
+        if (mDataTypes != null) {
+            Iterator<String> it = mDataTypes.iterator();
+            while (it.hasNext()) {
+                String dataType = it.next();
+                if (hasExactStaticDataType(dataType)) {
+                    continue;
+                }
+
+                sb.setLength(0);
+                sb.append(prefix); sb.append("Type: \"");
+                sb.append(dataType); sb.append("\"");
+                du.println(sb.toString());
+            }
+        }
+        if (mMimeGroups != null) {
+            Iterator<String> it = mMimeGroups.iterator();
+            while (it.hasNext()) {
+                sb.setLength(0);
+                sb.append(prefix); sb.append("MimeGroup: \"");
+                sb.append(it.next()); sb.append("\"");
+                du.println(sb.toString());
+            }
+        }
+        if (mPriority != 0 || mOrder != 0 || hasPartialTypes()) {
             sb.setLength(0);
-            sb.append(prefix); sb.append("mPriority="); sb.append(mPriority);
-                    sb.append(", mOrder="); sb.append(mOrder);
-                    sb.append(", mHasPartialTypes="); sb.append(mHasPartialTypes);
+            sb.append(prefix);
+            sb.append("mPriority="); sb.append(mPriority);
+            sb.append(", mOrder="); sb.append(mOrder);
+            sb.append(", mHasStaticPartialTypes="); sb.append(mHasStaticPartialTypes);
+            sb.append(", mHasDynamicPartialTypes="); sb.append(mHasDynamicPartialTypes);
             du.println(sb.toString());
         }
         if (getAutoVerify()) {
@@ -1923,12 +2151,24 @@
         } else {
             dest.writeInt(0);
         }
+        if (mStaticDataTypes != null) {
+            dest.writeInt(1);
+            dest.writeStringList(mStaticDataTypes);
+        } else {
+            dest.writeInt(0);
+        }
         if (mDataTypes != null) {
             dest.writeInt(1);
             dest.writeStringList(mDataTypes);
         } else {
             dest.writeInt(0);
         }
+        if (mMimeGroups != null) {
+            dest.writeInt(1);
+            dest.writeStringList(mMimeGroups);
+        } else {
+            dest.writeInt(0);
+        }
         if (mDataSchemeSpecificParts != null) {
             final int N = mDataSchemeSpecificParts.size();
             dest.writeInt(N);
@@ -1957,7 +2197,8 @@
             dest.writeInt(0);
         }
         dest.writeInt(mPriority);
-        dest.writeInt(mHasPartialTypes ? 1 : 0);
+        dest.writeInt(mHasStaticPartialTypes ? 1 : 0);
+        dest.writeInt(mHasDynamicPartialTypes ? 1 : 0);
         dest.writeInt(getAutoVerify() ? 1 : 0);
         dest.writeInt(mInstantAppVisibility);
         dest.writeInt(mOrder);
@@ -2002,9 +2243,17 @@
             source.readStringList(mDataSchemes);
         }
         if (source.readInt() != 0) {
+            mStaticDataTypes = new ArrayList<String>();
+            source.readStringList(mStaticDataTypes);
+        }
+        if (source.readInt() != 0) {
             mDataTypes = new ArrayList<String>();
             source.readStringList(mDataTypes);
         }
+        if (source.readInt() != 0) {
+            mMimeGroups = new ArrayList<String>();
+            source.readStringList(mMimeGroups);
+        }
         int N = source.readInt();
         if (N > 0) {
             mDataSchemeSpecificParts = new ArrayList<PatternMatcher>(N);
@@ -2027,12 +2276,17 @@
             }
         }
         mPriority = source.readInt();
-        mHasPartialTypes = source.readInt() > 0;
+        mHasStaticPartialTypes = source.readInt() > 0;
+        mHasDynamicPartialTypes = source.readInt() > 0;
         setAutoVerify(source.readInt() > 0);
         setVisibilityToInstantApp(source.readInt());
         mOrder = source.readInt();
     }
 
+    private boolean hasPartialTypes() {
+        return mHasStaticPartialTypes || mHasDynamicPartialTypes;
+    }
+
     private final boolean findMimeType(String type) {
         final ArrayList<String> t = mDataTypes;
 
@@ -2051,13 +2305,13 @@
         }
 
         // Deal with this IntentFilter wanting to match every Intent type.
-        if (mHasPartialTypes && t.contains("*")) {
+        if (hasPartialTypes() && t.contains("*")) {
             return true;
         }
 
         final int slashpos = type.indexOf('/');
         if (slashpos > 0) {
-            if (mHasPartialTypes && t.contains(type.substring(0, slashpos))) {
+            if (hasPartialTypes() && t.contains(type.substring(0, slashpos))) {
                 return true;
             }
             if (typeLength == slashpos+2 && type.charAt(slashpos+1) == '*') {
diff --git a/core/java/android/content/integrity/AppInstallMetadata.java b/core/java/android/content/integrity/AppInstallMetadata.java
index 4be7e6d..4ec9476 100644
--- a/core/java/android/content/integrity/AppInstallMetadata.java
+++ b/core/java/android/content/integrity/AppInstallMetadata.java
@@ -42,6 +42,9 @@
     private final List<String> mInstallerCertificates;
     private final long mVersionCode;
     private final boolean mIsPreInstalled;
+    private final boolean mIsStampTrusted;
+    // Raw string encoding for the SHA-256 hash of the certificate of the stamp.
+    private final String mStampCertificateHash;
     private final Map<String, String> mAllowedInstallersAndCertificates;
 
     private AppInstallMetadata(Builder builder) {
@@ -51,6 +54,8 @@
         this.mInstallerCertificates = builder.mInstallerCertificates;
         this.mVersionCode = builder.mVersionCode;
         this.mIsPreInstalled = builder.mIsPreInstalled;
+        this.mIsStampTrusted = builder.mIsStampTrusted;
+        this.mStampCertificateHash = builder.mStampCertificateHash;
         this.mAllowedInstallersAndCertificates = builder.mAllowedInstallersAndCertificates;
     }
 
@@ -84,9 +89,17 @@
         return mIsPreInstalled;
     }
 
-    /**
-     * Get the allowed installers and their corresponding cert.
-     */
+    /** @see AppInstallMetadata.Builder#setIsStampTrusted(boolean) */
+    public boolean isStampTrusted() {
+        return mIsStampTrusted;
+    }
+
+    /** @see AppInstallMetadata.Builder#setStampCertificateHash(String) */
+    public String getStampCertificateHash() {
+        return mStampCertificateHash;
+    }
+
+    /** Get the allowed installers and their corresponding cert. */
     public Map<String, String> getAllowedInstallersAndCertificates() {
         return mAllowedInstallersAndCertificates;
     }
@@ -95,13 +108,16 @@
     public String toString() {
         return String.format(
                 "AppInstallMetadata { PackageName = %s, AppCerts = %s, InstallerName = %s,"
-                    + " InstallerCerts = %s, VersionCode = %d, PreInstalled = %b }",
+                        + " InstallerCerts = %s, VersionCode = %d, PreInstalled = %b, "
+                        + "StampTrusted = %b, StampCert = %s }",
                 mPackageName,
                 mAppCertificates,
                 mInstallerName == null ? "null" : mInstallerName,
                 mInstallerCertificates == null ? "null" : mInstallerCertificates,
                 mVersionCode,
-                mIsPreInstalled);
+                mIsPreInstalled,
+                mIsStampTrusted,
+                mStampCertificateHash == null ? "null" : mStampCertificateHash);
     }
 
     /** Builder class for constructing {@link AppInstallMetadata} objects. */
@@ -112,6 +128,8 @@
         private List<String> mInstallerCertificates;
         private long mVersionCode;
         private boolean mIsPreInstalled;
+        private boolean mIsStampTrusted;
+        private String mStampCertificateHash;
         private Map<String, String> mAllowedInstallersAndCertificates;
 
         public Builder() {
@@ -203,6 +221,31 @@
         }
 
         /**
+         * Set certificate hash of the stamp embedded in the APK.
+         *
+         * <p>It is represented as the raw string encoding for the SHA-256 hash of the certificate
+         * of the stamp.
+         *
+         * @see AppInstallMetadata#getStampCertificateHash()
+         */
+        @NonNull
+        public Builder setStampCertificateHash(@NonNull String stampCertificateHash) {
+            this.mStampCertificateHash = Objects.requireNonNull(stampCertificateHash);
+            return this;
+        }
+
+        /**
+         * Set whether the stamp embedded in the APK is trusted or not.
+         *
+         * @see AppInstallMetadata#isStampTrusted()
+         */
+        @NonNull
+        public Builder setIsStampTrusted(boolean isStampTrusted) {
+            this.mIsStampTrusted = isStampTrusted;
+            return this;
+        }
+
+        /**
          * Build {@link AppInstallMetadata}.
          *
          * @throws IllegalArgumentException if package name or app certificate is null
diff --git a/core/java/android/content/integrity/AtomicFormula.java b/core/java/android/content/integrity/AtomicFormula.java
index d911eab..977a631 100644
--- a/core/java/android/content/integrity/AtomicFormula.java
+++ b/core/java/android/content/integrity/AtomicFormula.java
@@ -47,12 +47,14 @@
     /** @hide */
     @IntDef(
             value = {
-                    PACKAGE_NAME,
-                    APP_CERTIFICATE,
-                    INSTALLER_NAME,
-                    INSTALLER_CERTIFICATE,
-                    VERSION_CODE,
-                    PRE_INSTALLED,
+                PACKAGE_NAME,
+                APP_CERTIFICATE,
+                INSTALLER_NAME,
+                INSTALLER_CERTIFICATE,
+                VERSION_CODE,
+                PRE_INSTALLED,
+                STAMP_TRUSTED,
+                STAMP_CERTIFICATE_HASH,
             })
     @Retention(RetentionPolicy.SOURCE)
     public @interface Key {}
@@ -105,6 +107,20 @@
      */
     public static final int PRE_INSTALLED = 5;
 
+    /**
+     * If the APK has an embedded trusted stamp.
+     *
+     * <p>Can only be used in {@link BooleanAtomicFormula}.
+     */
+    public static final int STAMP_TRUSTED = 6;
+
+    /**
+     * SHA-256 of the certificate used to sign the stamp embedded in the APK.
+     *
+     * <p>Can only be used in {@link StringAtomicFormula}.
+     */
+    public static final int STAMP_CERTIFICATE_HASH = 7;
+
     public static final int EQ = 0;
     public static final int GT = 1;
     public static final int GTE = 2;
@@ -266,9 +282,7 @@
         }
 
         private static boolean isValidOperator(int operator) {
-            return operator == EQ
-                    || operator == GT
-                    || operator == GTE;
+            return operator == EQ || operator == GT || operator == GTE;
         }
 
         private static long getLongMetadataValue(AppInstallMetadata appInstallMetadata, int key) {
@@ -300,7 +314,8 @@
                     key == PACKAGE_NAME
                             || key == APP_CERTIFICATE
                             || key == INSTALLER_CERTIFICATE
-                            || key == INSTALLER_NAME,
+                            || key == INSTALLER_NAME
+                            || key == STAMP_CERTIFICATE_HASH,
                     String.format(
                             "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
             mValue = null;
@@ -321,7 +336,8 @@
                     key == PACKAGE_NAME
                             || key == APP_CERTIFICATE
                             || key == INSTALLER_CERTIFICATE
-                            || key == INSTALLER_NAME,
+                            || key == INSTALLER_NAME
+                            || key == STAMP_CERTIFICATE_HASH,
                     String.format(
                             "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
             mValue = value;
@@ -329,15 +345,14 @@
         }
 
         /**
-         * Constructs a new {@link StringAtomicFormula} together with handling the necessary
-         * hashing for the given key.
+         * Constructs a new {@link StringAtomicFormula} together with handling the necessary hashing
+         * for the given key.
          *
-         * <p> The value will be automatically hashed with SHA256 and the hex digest will be
-         * computed when the key is PACKAGE_NAME or INSTALLER_NAME and the value is more than 32
-         * characters.
+         * <p>The value will be automatically hashed with SHA256 and the hex digest will be computed
+         * when the key is PACKAGE_NAME or INSTALLER_NAME and the value is more than 32 characters.
          *
-         * <p> The APP_CERTIFICATES and INSTALLER_CERTIFICATES are always delivered in hashed
-         * form. So the isHashedValue is set to true by default.
+         * <p>The APP_CERTIFICATES, INSTALLER_CERTIFICATES, and STAMP_CERTIFICATE_HASH are always
+         * delivered in hashed form. So the isHashedValue is set to true by default.
          *
          * @throws IllegalArgumentException if {@code key} cannot be used with string value.
          */
@@ -347,13 +362,15 @@
                     key == PACKAGE_NAME
                             || key == APP_CERTIFICATE
                             || key == INSTALLER_CERTIFICATE
-                            || key == INSTALLER_NAME,
+                            || key == INSTALLER_NAME
+                            || key == STAMP_CERTIFICATE_HASH,
                     String.format(
                             "Key %s cannot be used with StringAtomicFormula", keyToString(key)));
             mValue = hashValue(key, value);
             mIsHashedValue =
                     key == APP_CERTIFICATE
-                            || key == INSTALLER_CERTIFICATE
+                                    || key == INSTALLER_CERTIFICATE
+                                    || key == STAMP_CERTIFICATE_HASH
                             ? true
                             : !mValue.equals(value);
         }
@@ -460,6 +477,8 @@
                     return appInstallMetadata.getInstallerCertificates();
                 case AtomicFormula.INSTALLER_NAME:
                     return Collections.singletonList(appInstallMetadata.getInstallerName());
+                case AtomicFormula.STAMP_CERTIFICATE_HASH:
+                    return Collections.singletonList(appInstallMetadata.getStampCertificateHash());
                 default:
                     throw new IllegalStateException(
                             "Unexpected key in StringAtomicFormula: " + key);
@@ -502,7 +521,7 @@
         public BooleanAtomicFormula(@Key int key) {
             super(key);
             checkArgument(
-                    key == PRE_INSTALLED,
+                    key == PRE_INSTALLED || key == STAMP_TRUSTED,
                     String.format(
                             "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
             mValue = null;
@@ -519,7 +538,7 @@
         public BooleanAtomicFormula(@Key int key, boolean value) {
             super(key);
             checkArgument(
-                    key == PRE_INSTALLED,
+                    key == PRE_INSTALLED || key == STAMP_TRUSTED,
                     String.format(
                             "Key %s cannot be used with BooleanAtomicFormula", keyToString(key)));
             mValue = value;
@@ -615,6 +634,8 @@
             switch (key) {
                 case AtomicFormula.PRE_INSTALLED:
                     return appInstallMetadata.isPreInstalled();
+                case AtomicFormula.STAMP_TRUSTED:
+                    return appInstallMetadata.isStampTrusted();
                 default:
                     throw new IllegalStateException(
                             "Unexpected key in BooleanAtomicFormula: " + key);
@@ -640,6 +661,10 @@
                 return "INSTALLER_CERTIFICATE";
             case PRE_INSTALLED:
                 return "PRE_INSTALLED";
+            case STAMP_TRUSTED:
+                return "STAMP_TRUSTED";
+            case STAMP_CERTIFICATE_HASH:
+                return "STAMP_CERTIFICATE_HASH";
             default:
                 throw new IllegalArgumentException("Unknown key " + key);
         }
@@ -664,6 +689,8 @@
                 || key == VERSION_CODE
                 || key == INSTALLER_NAME
                 || key == INSTALLER_CERTIFICATE
-                || key == PRE_INSTALLED;
+                || key == PRE_INSTALLED
+                || key == STAMP_TRUSTED
+                || key == STAMP_CERTIFICATE_HASH;
     }
 }
diff --git a/core/java/android/content/integrity/IntegrityFormula.java b/core/java/android/content/integrity/IntegrityFormula.java
index c5e5c8a..fc177721 100644
--- a/core/java/android/content/integrity/IntegrityFormula.java
+++ b/core/java/android/content/integrity/IntegrityFormula.java
@@ -90,8 +90,7 @@
             return new BooleanAtomicFormula(AtomicFormula.PRE_INSTALLED, true);
         }
 
-        private Application() {
-        }
+        private Application() {}
     }
 
     /** Factory class for creating integrity formulas based on installer. */
@@ -117,26 +116,45 @@
          */
         @NonNull
         public static IntegrityFormula certificatesContain(@NonNull String installerCertificate) {
-            return new StringAtomicFormula(AtomicFormula.INSTALLER_CERTIFICATE,
-                    installerCertificate);
+            return new StringAtomicFormula(
+                    AtomicFormula.INSTALLER_CERTIFICATE, installerCertificate);
         }
 
-        private Installer() {
+        private Installer() {}
+    }
+
+    /** Factory class for creating integrity formulas based on source stamp. */
+    public static final class SourceStamp {
+        /** Returns an integrity formula that checks the equality to a stamp certificate hash. */
+        @NonNull
+        public static IntegrityFormula stampCertificateHashEquals(
+                @NonNull String stampCertificateHash) {
+            return new StringAtomicFormula(
+                    AtomicFormula.STAMP_CERTIFICATE_HASH, stampCertificateHash);
         }
+
+        /**
+         * Returns an integrity formula that is valid when stamp embedded in the APK is NOT trusted.
+         */
+        @NonNull
+        public static IntegrityFormula notTrusted() {
+            return new BooleanAtomicFormula(AtomicFormula.STAMP_TRUSTED, /* value= */ false);
+        }
+
+        private SourceStamp() {}
     }
 
     /** @hide */
     @IntDef(
             value = {
-                    COMPOUND_FORMULA_TAG,
-                    STRING_ATOMIC_FORMULA_TAG,
-                    LONG_ATOMIC_FORMULA_TAG,
-                    BOOLEAN_ATOMIC_FORMULA_TAG,
-                    INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG
+                COMPOUND_FORMULA_TAG,
+                STRING_ATOMIC_FORMULA_TAG,
+                LONG_ATOMIC_FORMULA_TAG,
+                BOOLEAN_ATOMIC_FORMULA_TAG,
+                INSTALLER_ALLOWED_BY_MANIFEST_FORMULA_TAG
             })
     @Retention(RetentionPolicy.SOURCE)
-    @interface Tag {
-    }
+    @interface Tag {}
 
     /** @hide */
     public static final int COMPOUND_FORMULA_TAG = 0;
@@ -171,8 +189,8 @@
     public abstract boolean isAppCertificateFormula();
 
     /**
-     * Returns true when the formula (or one of its atomic formulas) has installer package name
-     * or installer certificate as key.
+     * Returns true when the formula (or one of its atomic formulas) has installer package name or
+     * installer certificate as key.
      *
      * @hide
      */
@@ -243,15 +261,12 @@
         return new CompoundFormula(CompoundFormula.AND, Arrays.asList(formulae));
     }
 
-    /**
-     * Returns a formula that evaluates to true when {@code formula} evaluates to false.
-     */
+    /** Returns a formula that evaluates to true when {@code formula} evaluates to false. */
     @NonNull
     public static IntegrityFormula not(@NonNull IntegrityFormula formula) {
         return new CompoundFormula(CompoundFormula.NOT, Arrays.asList(formula));
     }
 
     // Constructor is package private so it cannot be inherited outside of this package.
-    IntegrityFormula() {
-    }
+    IntegrityFormula() {}
 }
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index a3487be..55a6cab 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -45,7 +45,7 @@
             STATE_NO_IDMAP,
             STATE_DISABLED,
             STATE_ENABLED,
-            STATE_ENABLED_STATIC,
+            STATE_ENABLED_IMMUTABLE,
             // @Deprecated STATE_TARGET_IS_BEING_REPLACED,
             STATE_OVERLAY_IS_BEING_REPLACED,
     })
@@ -117,11 +117,12 @@
 
     /**
      * The overlay package is currently enabled because it is marked as
-     * 'static'. It cannot be disabled but will change state if for instance
+     * 'immutable'. It cannot be disabled but will change state if for instance
      * its target is uninstalled.
      * @hide
      */
-    public static final int STATE_ENABLED_STATIC = 6;
+    @Deprecated
+    public static final int STATE_ENABLED_IMMUTABLE = 6;
 
     /**
      * Overlay category: theme.
@@ -180,21 +181,21 @@
     public final int userId;
 
     /**
-     * Priority as read from the manifest. Used if isStatic is true. Not
-     * intended to be exposed to 3rd party.
+     * Priority as configured by {@link com.android.internal.content.om.OverlayConfig}.
+     * Not intended to be exposed to 3rd party.
      *
      * @hide
      */
     public final int priority;
 
     /**
-     * isStatic as read from the manifest. If true, the overlay is
-     * unconditionally loaded and cannot be unloaded. Not intended to be
+     * isMutable as configured by {@link com.android.internal.content.om.OverlayConfig}.
+     * If false, the overlay is unconditionally loaded and cannot be unloaded. Not intended to be
      * exposed to 3rd party.
      *
      * @hide
      */
-    public final boolean isStatic;
+    public final boolean isMutable;
 
     /**
      * Create a new OverlayInfo based on source with an updated state.
@@ -207,14 +208,14 @@
     public OverlayInfo(@NonNull OverlayInfo source, @State int state) {
         this(source.packageName, source.targetPackageName, source.targetOverlayableName,
                 source.category, source.baseCodePath, state, source.userId, source.priority,
-                source.isStatic);
+                source.isMutable);
     }
 
     /** @hide */
     public OverlayInfo(@NonNull String packageName, @NonNull String targetPackageName,
             @Nullable String targetOverlayableName, @Nullable String category,
             @NonNull String baseCodePath, int state, int userId,
-            int priority, boolean isStatic) {
+            int priority, boolean isMutable) {
         this.packageName = packageName;
         this.targetPackageName = targetPackageName;
         this.targetOverlayableName = targetOverlayableName;
@@ -223,7 +224,7 @@
         this.state = state;
         this.userId = userId;
         this.priority = priority;
-        this.isStatic = isStatic;
+        this.isMutable = isMutable;
         ensureValidState();
     }
 
@@ -237,7 +238,7 @@
         state = source.readInt();
         userId = source.readInt();
         priority = source.readInt();
-        isStatic = source.readBoolean();
+        isMutable = source.readBoolean();
         ensureValidState();
     }
 
@@ -307,7 +308,7 @@
             case STATE_NO_IDMAP:
             case STATE_DISABLED:
             case STATE_ENABLED:
-            case STATE_ENABLED_STATIC:
+            case STATE_ENABLED_IMMUTABLE:
             case STATE_TARGET_IS_BEING_REPLACED:
             case STATE_OVERLAY_IS_BEING_REPLACED:
                 break;
@@ -331,7 +332,7 @@
         dest.writeInt(state);
         dest.writeInt(userId);
         dest.writeInt(priority);
-        dest.writeBoolean(isStatic);
+        dest.writeBoolean(isMutable);
     }
 
     public static final @android.annotation.NonNull Parcelable.Creator<OverlayInfo> CREATOR =
@@ -360,7 +361,7 @@
     public boolean isEnabled() {
         switch (state) {
             case STATE_ENABLED:
-            case STATE_ENABLED_STATIC:
+            case STATE_ENABLED_IMMUTABLE:
                 return true;
             default:
                 return false;
@@ -386,8 +387,8 @@
                 return "STATE_DISABLED";
             case STATE_ENABLED:
                 return "STATE_ENABLED";
-            case STATE_ENABLED_STATIC:
-                return "STATE_ENABLED_STATIC";
+            case STATE_ENABLED_IMMUTABLE:
+                return "STATE_ENABLED_IMMUTABLE";
             case STATE_TARGET_IS_BEING_REPLACED:
                 return "STATE_TARGET_IS_BEING_REPLACED";
             case STATE_OVERLAY_IS_BEING_REPLACED:
diff --git a/core/java/android/service/controls/IControlsLoadCallback.aidl b/core/java/android/content/pm/AndroidTestBaseUpdater.java
similarity index 61%
copy from core/java/android/service/controls/IControlsLoadCallback.aidl
copy to core/java/android/content/pm/AndroidTestBaseUpdater.java
index bfc61cd..1cbbdca 100644
--- a/core/java/android/service/controls/IControlsLoadCallback.aidl
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2020, The Android Open Source Project
+ * 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
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,13 +14,13 @@
  * limitations under the License.
  */
 
-package android.service.controls;
-
-import android.service.controls.Control;
+package android.content.pm;
 
 /**
+ * Dummy class to maintain legacy behavior of including a class in core source to toggle
+ * whether or not a shared library is stripped at build time.
+ *
  * @hide
  */
-oneway interface IControlsLoadCallback {
-    void accept(in IBinder token, in List<Control> controls);
-}
\ No newline at end of file
+public class AndroidTestBaseUpdater {
+}
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index b5f4f80..8a89840 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -95,9 +95,9 @@
 
     void registerShortcutChangeCallback(String callingPackage, long changedSince,
             String packageName, in List shortcutIds, in List<LocusId> locusIds,
-            in ComponentName componentName, int flags, in IShortcutChangeCallback callback,
-            int callbackId);
-    void unregisterShortcutChangeCallback(String callingPackage, int callbackId);
+            in ComponentName componentName, int flags, in IShortcutChangeCallback callback);
+    void unregisterShortcutChangeCallback(String callingPackage,
+            in IShortcutChangeCallback callback);
 
     void cacheShortcuts(String callingPackage, String packageName, in List<String> shortcutIds,
             in UserHandle user);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 6552d1b..e9cdbf28 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -482,19 +482,12 @@
      * Notify the package manager that a list of dex files have been loaded.
      *
      * @param loadingPackageName the name of the package who performs the load
-     * @param classLoadersNames the names of the class loaders present in the loading chain. The
-     *    list encodes the class loader chain in the natural order. The first class loader has
-     *    the second one as its parent and so on. The dex files present in the class path of the
-     *    first class loader will be recorded in the usage file.
-     * @param classPaths the class paths corresponding to the class loaders names from
-     *     {@param classLoadersNames}. The the first element corresponds to the first class loader
-     *     and so on. A classpath is represented as a list of dex files separated by
-     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
-     *     The dex files found in the first class path will be recorded in the usage file.
+     * @param classLoaderContextMap a map from file paths to dex files that have been loaded to
+     *     the class loader context that was used to load them.
      * @param loaderIsa the ISA of the loader process
      */
-    oneway void notifyDexLoad(String loadingPackageName, in List<String> classLoadersNames,
-            in List<String> classPaths, String loaderIsa);
+    oneway void notifyDexLoad(String loadingPackageName,
+            in Map<String, String> classLoaderContextMap, String loaderIsa);
 
     /**
      * Register an application dex module with the package manager.
@@ -749,4 +742,11 @@
     // a large change that modifies many repos.
     //------------------------------------------------------------------------
     int checkUidPermission(String permName, int uid);
+
+    void setMimeGroup(String packageName, String group, in List<String> mimeTypes);
+
+    void clearMimeGroup(String packageName, String group);
+
+    List<String> getMimeGroup(String packageName, String group);
+
 }
diff --git a/core/java/android/content/pm/IShortcutService.aidl b/core/java/android/content/pm/IShortcutService.aidl
index 9e85fc3..29a55b7 100644
--- a/core/java/android/content/pm/IShortcutService.aidl
+++ b/core/java/android/content/pm/IShortcutService.aidl
@@ -76,4 +76,6 @@
     void removeLongLivedShortcuts(String packageName, in List shortcutIds, int userId);
 
     ParceledListSlice getShortcuts(String packageName, int matchFlags, int userId);
+
+    void pushDynamicShortcut(String packageName, in ShortcutInfo shortcut, int userId);
 }
\ No newline at end of file
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 5aa0208..86242fd 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import static android.Manifest.permission;
+
 import android.annotation.CallbackExecutor;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -161,7 +162,7 @@
     private final List<CallbackMessageHandler> mCallbacks = new ArrayList<>();
     private final List<SessionCallbackDelegate> mDelegates = new ArrayList<>();
 
-    private final Map<Integer, Pair<Executor, ShortcutChangeCallback>>
+    private final Map<ShortcutChangeCallback, Pair<Executor, IShortcutChangeCallback>>
             mShortcutChangeCallbacks = new HashMap<>();
 
     /**
@@ -549,8 +550,8 @@
             android.content.pm.IShortcutChangeCallback.Stub {
         private final WeakReference<Pair<Executor, ShortcutChangeCallback>> mRemoteReferences;
 
-        ShortcutChangeCallbackProxy(Pair<Executor, ShortcutChangeCallback> remoteReferences) {
-            mRemoteReferences = new WeakReference<>(remoteReferences);
+        ShortcutChangeCallbackProxy(Executor executor, ShortcutChangeCallback callback) {
+            mRemoteReferences = new WeakReference<>(new Pair<>(executor, callback));
         }
 
         @Override
@@ -1753,14 +1754,12 @@
         Objects.requireNonNull(executor, "Executor cannot be null");
 
         synchronized (mShortcutChangeCallbacks) {
-            final int callbackId = callback.hashCode();
-            final Pair<Executor, ShortcutChangeCallback> state = new Pair<>(executor, callback);
-            mShortcutChangeCallbacks.put(callbackId, state);
+            IShortcutChangeCallback proxy = new ShortcutChangeCallbackProxy(executor, callback);
+            mShortcutChangeCallbacks.put(callback, new Pair<>(executor, proxy));
             try {
                 mService.registerShortcutChangeCallback(mContext.getPackageName(),
                         query.mChangedSince, query.mPackage, query.mShortcutIds, query.mLocusIds,
-                        query.mActivity, query.mQueryFlags, new ShortcutChangeCallbackProxy(state),
-                        callbackId);
+                        query.mActivity, query.mQueryFlags, proxy);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
@@ -1779,12 +1778,10 @@
         Objects.requireNonNull(callback, "Callback cannot be null");
 
         synchronized (mShortcutChangeCallbacks) {
-            final int callbackId = callback.hashCode();
-            if (mShortcutChangeCallbacks.containsKey(callbackId)) {
-                mShortcutChangeCallbacks.remove(callbackId);
+            if (mShortcutChangeCallbacks.containsKey(callback)) {
+                IShortcutChangeCallback proxy = mShortcutChangeCallbacks.remove(callback).second;
                 try {
-                    mService.unregisterShortcutChangeCallback(mContext.getPackageName(),
-                            callbackId);
+                    mService.unregisterShortcutChangeCallback(mContext.getPackageName(), proxy);
                 } catch (RemoteException e) {
                     throw e.rethrowFromSystemServer();
                 }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 03ed373..ab3982a 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3023,6 +3023,18 @@
     public static final String FEATURE_TUNER = "android.hardware.tv.tuner";
 
     /**
+     * Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
+     * the necessary changes to support app enumeration.
+     *
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_APP_ENUMERATION = "android.software.app_enumeration";
+
+    /** @hide */
+    public static final boolean APP_ENUMERATION_ENABLED_BY_DEFAULT = true;
+
+    /**
      * Extra field name for the URI to a verification file. Passed to a package
      * verifier.
      *
@@ -7818,4 +7830,37 @@
         return resId == com.android.internal.R.drawable.sym_def_app_icon
                 || resId == com.android.internal.R.drawable.sym_app_on_sd_unavailable_icon;
     }
+
+    /**
+     * Sets MIME group's MIME types
+     *
+     * @param mimeGroup MIME group to modify
+     * @param mimeTypes new MIME types contained by MIME group
+     */
+    public void setMimeGroup(@NonNull String mimeGroup, @NonNull Set<String> mimeTypes) {
+        throw new UnsupportedOperationException(
+                "setMimeGroup not implemented in subclass");
+    }
+
+    /**
+     * Clears MIME group by removing all MIME types from it
+     *
+     * @param mimeGroup MIME group to clear
+     */
+    public void clearMimeGroup(@NonNull String mimeGroup) {
+        throw new UnsupportedOperationException(
+                "clearMimeGroup not implemented in subclass");
+    }
+
+    /**
+     * Gets all MIME types that MIME group contains
+     *
+     * @return MIME types contained by the MIME group,
+     *         or null if the MIME group was not declared in the manifest.
+     */
+    @Nullable
+    public Set<String> getMimeGroup(@NonNull String mimeGroup) {
+        throw new UnsupportedOperationException(
+                "getMimeGroup not implemented in subclass");
+    }
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index da44f70..1de82450 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -41,7 +41,6 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
-import android.annotation.AnyThread;
 import android.annotation.IntDef;
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -56,12 +55,7 @@
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.pm.PackageParserCacheHelper.ReadHelper;
-import android.content.pm.PackageParserCacheHelper.WriteHelper;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ApkParseUtils;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
 import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
@@ -79,14 +73,10 @@
 import android.os.Parcelable;
 import android.os.PatternMatcher;
 import android.os.RemoteException;
-import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.system.ErrnoException;
-import android.system.OsConstants;
-import android.system.StructStat;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -118,7 +108,6 @@
 
 import java.io.File;
 import java.io.FileDescriptor;
-import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -316,9 +305,6 @@
 
     public int mParseError = PackageManager.INSTALL_SUCCEEDED;
 
-    public ThreadLocal<ApkParseUtils.ParseResult> mSharedResult
-            = ThreadLocal.withInitial(ApkParseUtils.ParseResult::new);
-
     public static boolean sCompatibilityModeEnabled = true;
     public static boolean sUseRoundIcon = false;
 
@@ -483,6 +469,9 @@
         public final boolean isolatedSplits;
         public final boolean isSplitRequired;
         public final boolean useEmbeddedDex;
+        public final String targetPackageName;
+        public final boolean overlayIsStatic;
+        public final int overlayPriority;
 
         public ApkLite(String codePath, String packageName, String splitName,
                 boolean isFeatureSplit,
@@ -492,6 +481,7 @@
                 SigningDetails signingDetails, boolean coreApp,
                 boolean debuggable, boolean multiArch, boolean use32bitAbi,
                 boolean useEmbeddedDex, boolean extractNativeLibs, boolean isolatedSplits,
+                String targetPackageName, boolean overlayIsStatic, int overlayPriority,
                 int minSdkVersion, int targetSdkVersion) {
             this.codePath = codePath;
             this.packageName = packageName;
@@ -513,6 +503,9 @@
             this.extractNativeLibs = extractNativeLibs;
             this.isolatedSplits = isolatedSplits;
             this.isSplitRequired = isSplitRequired;
+            this.targetPackageName = targetPackageName;
+            this.overlayIsStatic = overlayIsStatic;
+            this.overlayPriority = overlayPriority;
             this.minSdkVersion = minSdkVersion;
             this.targetSdkVersion = targetSdkVersion;
         }
@@ -1047,7 +1040,7 @@
      * and unique split names.
      * <p>
      * Note that this <em>does not</em> perform signature verification; that
-     * must be done separately in {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}.
+     * must be done separately in {@link #collectCertificates(Package, boolean)}.
      *
      * If {@code useCaches} is true, the package parser might return a cached
      * result from a previous parse of the same {@code packageFile} with the same
@@ -1075,201 +1068,6 @@
     }
 
     /**
-     * Updated method which returns {@link ParsedPackage}, the current representation of a
-     * package parsed from disk.
-     *
-     * @see #parsePackage(File, int, boolean)
-     */
-    @AnyThread
-    public ParsedPackage parseParsedPackage(File packageFile, int flags, boolean useCaches)
-            throws PackageParserException {
-        ParsedPackage parsed = useCaches ? getCachedResult(packageFile, flags) : null;
-        if (parsed != null) {
-            return parsed;
-        }
-
-        long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
-        ApkParseUtils.ParseInput parseInput = mSharedResult.get().reset();
-        parsed = ApkParseUtils.parsePackage(
-                parseInput,
-                mSeparateProcesses,
-                mCallback,
-                mMetrics,
-                mOnlyCoreApps,
-                packageFile,
-                flags
-        )
-                .hideAsParsed();
-
-        long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
-        cacheResult(packageFile, flags, parsed);
-        if (LOG_PARSE_TIMINGS) {
-            parseTime = cacheTime - parseTime;
-            cacheTime = SystemClock.uptimeMillis() - cacheTime;
-            if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
-                Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
-                        + "ms, update_cache=" + cacheTime + " ms");
-            }
-        }
-
-        return parsed;
-    }
-
-    /**
-     * Returns the cache key for a specified {@code packageFile} and {@code flags}.
-     */
-    private String getCacheKey(File packageFile, int flags) {
-        StringBuilder sb = new StringBuilder(packageFile.getName());
-        sb.append('-');
-        sb.append(flags);
-
-        return sb.toString();
-    }
-
-    @VisibleForTesting
-    protected ParsedPackage fromCacheEntry(byte[] bytes) {
-        return fromCacheEntryStatic(bytes);
-    }
-
-    /** static version of {@link #fromCacheEntry} for unit tests. */
-    @VisibleForTesting
-    public static ParsedPackage fromCacheEntryStatic(byte[] bytes) {
-        final Parcel p = Parcel.obtain();
-        p.unmarshall(bytes, 0, bytes.length);
-        p.setDataPosition(0);
-
-        final ReadHelper helper = new ReadHelper(p);
-        helper.startAndInstall();
-
-        // TODO(b/135203078): Hide PackageImpl constructor?
-        ParsedPackage pkg = new PackageImpl(p);
-
-        p.recycle();
-
-        sCachedPackageReadCount.incrementAndGet();
-
-        return pkg;
-    }
-
-    @VisibleForTesting
-    protected byte[] toCacheEntry(ParsedPackage pkg) {
-        return toCacheEntryStatic(pkg);
-
-    }
-
-    /** static version of {@link #toCacheEntry} for unit tests. */
-    @VisibleForTesting
-    public static byte[] toCacheEntryStatic(ParsedPackage pkg) {
-        final Parcel p = Parcel.obtain();
-        final WriteHelper helper = new WriteHelper(p);
-
-        pkg.writeToParcel(p, 0 /* flags */);
-
-        helper.finishAndUninstall();
-
-        byte[] serialized = p.marshall();
-        p.recycle();
-
-        return serialized;
-    }
-
-    /**
-     * Given a {@code packageFile} and a {@code cacheFile} returns whether the
-     * cache file is up to date based on the mod-time of both files.
-     */
-    private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
-        try {
-            // NOTE: We don't use the File.lastModified API because it has the very
-            // non-ideal failure mode of returning 0 with no excepions thrown.
-            // The nio2 Files API is a little better but is considerably more expensive.
-            final StructStat pkg = android.system.Os.stat(packageFile.getAbsolutePath());
-            final StructStat cache = android.system.Os.stat(cacheFile.getAbsolutePath());
-            return pkg.st_mtime < cache.st_mtime;
-        } catch (ErrnoException ee) {
-            // The most common reason why stat fails is that a given cache file doesn't
-            // exist. We ignore that here. It's easy to reason that it's safe to say the
-            // cache isn't up to date if we see any sort of exception here.
-            //
-            // (1) Exception while stating the package file : This should never happen,
-            // and if it does, we do a full package parse (which is likely to throw the
-            // same exception).
-            // (2) Exception while stating the cache file : If the file doesn't exist, the
-            // cache is obviously out of date. If the file *does* exist, we can't read it.
-            // We will attempt to delete and recreate it after parsing the package.
-            if (ee.errno != OsConstants.ENOENT) {
-                Slog.w("Error while stating package cache : ", ee);
-            }
-
-            return false;
-        }
-    }
-
-    /**
-     * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
-     * or {@code null} if no cached result exists.
-     */
-    public ParsedPackage getCachedResult(File packageFile, int flags) {
-        if (mCacheDir == null) {
-            return null;
-        }
-
-        final String cacheKey = getCacheKey(packageFile, flags);
-        final File cacheFile = new File(mCacheDir, cacheKey);
-
-        try {
-            // If the cache is not up to date, return null.
-            if (!isCacheUpToDate(packageFile, cacheFile)) {
-                return null;
-            }
-
-            final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
-            return fromCacheEntry(bytes);
-        } catch (Throwable e) {
-            Slog.w(TAG, "Error reading package cache: ", e);
-
-            // If something went wrong while reading the cache entry, delete the cache file
-            // so that we regenerate it the next time.
-            cacheFile.delete();
-            return null;
-        }
-    }
-
-    /**
-     * Caches the parse result for {@code packageFile} with flags {@code flags}.
-     */
-    public void cacheResult(File packageFile, int flags, ParsedPackage parsed) {
-        if (mCacheDir == null) {
-            return;
-        }
-
-        try {
-            final String cacheKey = getCacheKey(packageFile, flags);
-            final File cacheFile = new File(mCacheDir, cacheKey);
-
-            if (cacheFile.exists()) {
-                if (!cacheFile.delete()) {
-                    Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
-                }
-            }
-
-            final byte[] cacheEntry = toCacheEntry(parsed);
-
-            if (cacheEntry == null) {
-                return;
-            }
-
-            try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
-                fos.write(cacheEntry);
-            } catch (IOException ioe) {
-                Slog.w(TAG, "Error writing cache entry.", ioe);
-                cacheFile.delete();
-            }
-        } catch (Throwable e) {
-            Slog.w(TAG, "Error saving package cache.", e);
-        }
-    }
-
-    /**
      * Parse all APKs contained in the given directory, treating them as a
      * single package. This also performs sanity checking, such as requiring
      * identical package name and version codes, a single base APK, and unique
@@ -1277,7 +1075,7 @@
      * <p>
      * Note that this <em>does not</em> perform signature verification; that
      * must be done separately in
-     * {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}.
+     * {@link #collectCertificates(Package, boolean)} .
      */
     private Package parseClusterPackage(File packageDir, int flags) throws PackageParserException {
         final PackageLite lite = parseClusterPackageLite(packageDir, 0);
@@ -1339,7 +1137,7 @@
      * <p>
      * Note that this <em>does not</em> perform signature verification; that
      * must be done separately in
-     * {@link ApkParseUtils#collectCertificates(AndroidPackage, boolean)}.
+     * {@link #collectCertificates(Package, boolean)}.
      */
     @UnsupportedAppUsage
     public Package parseMonolithicPackage(File apkFile, int flags) throws PackageParserException {
@@ -1688,7 +1486,7 @@
         }
     }
 
-    private static String validateName(String name, boolean requireSeparator,
+    public static String validateName(String name, boolean requireSeparator,
             boolean requireFilename) {
         final int N = name.length();
         boolean hasSep = false;
@@ -1784,6 +1582,12 @@
         boolean useEmbeddedDex = false;
         String configForSplit = null;
         String usesSplitName = null;
+        String targetPackage = null;
+        boolean overlayIsStatic = false;
+        int overlayPriority = 0;
+
+        String requiredSystemPropertyName = null;
+        String requiredSystemPropertyValue = null;
 
         for (int i = 0; i < attrs.getAttributeCount(); i++) {
             final String attr = attrs.getAttributeName(i);
@@ -1848,6 +1652,21 @@
                         useEmbeddedDex = attrs.getAttributeBooleanValue(i, false);
                     }
                 }
+            } else if (PackageParser.TAG_OVERLAY.equals(parser.getName())) {
+                for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+                    final String attr = attrs.getAttributeName(i);
+                    if ("requiredSystemPropertyName".equals(attr)) {
+                        requiredSystemPropertyName = attrs.getAttributeValue(i);
+                    } else if ("requiredSystemPropertyValue".equals(attr)) {
+                        requiredSystemPropertyValue = attrs.getAttributeValue(i);
+                    } else if ("targetPackage".equals(attr)) {
+                        targetPackage = attrs.getAttributeValue(i);;
+                    } else if ("isStatic".equals(attr)) {
+                        overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
+                    } else if ("priority".equals(attr)) {
+                        overlayPriority = attrs.getAttributeIntValue(i, 0);
+                    }
+                }
             } else if (TAG_USES_SPLIT.equals(parser.getName())) {
                 if (usesSplitName != null) {
                     Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
@@ -1874,11 +1693,22 @@
             }
         }
 
+        // Check to see if overlay should be excluded based on system property condition
+        if (!checkRequiredSystemProperty(requiredSystemPropertyName,
+                requiredSystemPropertyValue)) {
+            Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+                    + codePath + ": overlay ignored due to required system property: "
+                    + requiredSystemPropertyName + " with value: " + requiredSystemPropertyValue);
+            targetPackage = null;
+            overlayIsStatic = false;
+            overlayPriority = 0;
+        }
+
         return new ApkLite(codePath, packageSplit.first, packageSplit.second, isFeatureSplit,
                 configForSplit, usesSplitName, isSplitRequired, versionCode, versionCodeMajor,
                 revisionCode, installLocation, verifiers, signingDetails, coreApp, debuggable,
                 multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs, isolatedSplits,
-                minSdkVersion, targetSdkVersion);
+                targetPackage, overlayIsStatic, overlayPriority, minSdkVersion, targetSdkVersion);
     }
 
     /**
@@ -2162,7 +1992,7 @@
                 }
 
                 // check to see if overlay should be excluded based on system property condition
-                if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
+                if (!checkRequiredSystemProperty(propName, propValue)) {
                     Slog.i(TAG, "Skipping target and overlay pair " + pkg.mOverlayTarget + " and "
                         + pkg.baseCodePath+ ": overlay ignored due to required system property: "
                         + propName + " with value: " + propValue);
@@ -2590,8 +2420,11 @@
         return pkg;
     }
 
-    private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
-
+    /**
+     * Returns {@code true} if both the property name and value are empty or if the given system
+     * property is set to the specified value. In all other cases, returns {@code false}
+     */
+    public static boolean checkRequiredSystemProperty(String propName, String propValue) {
         if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
             if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
                 // malformed condition - incomplete
diff --git a/core/java/android/content/pm/PackagePartitions.java b/core/java/android/content/pm/PackagePartitions.java
new file mode 100644
index 0000000..9b8396e
--- /dev/null
+++ b/core/java/android/content/pm/PackagePartitions.java
@@ -0,0 +1,213 @@
+/*
+ * 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.content.pm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Environment;
+import android.os.FileUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.function.Function;
+
+/**
+ * Exposes {@link #SYSTEM_PARTITIONS} which represents the partitions in which application packages
+ * can be installed. The partitions are ordered from most generic (lowest priority) to most specific
+ * (greatest priority).
+ *
+ * @hide
+ **/
+public class PackagePartitions {
+    public static final int PARTITION_SYSTEM = 0;
+    public static final int PARTITION_VENDOR = 1;
+    public static final int PARTITION_ODM = 2;
+    public static final int PARTITION_OEM = 3;
+    public static final int PARTITION_PRODUCT = 4;
+    public static final int PARTITION_SYSTEM_EXT = 5;
+
+    @IntDef(flag = true, prefix = { "PARTITION_" }, value = {
+        PARTITION_SYSTEM,
+        PARTITION_VENDOR,
+        PARTITION_ODM,
+        PARTITION_OEM,
+        PARTITION_PRODUCT,
+        PARTITION_SYSTEM_EXT
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PartitionType {}
+
+    /**
+     * The list of all system partitions that may contain packages in ascending order of
+     * specificity (the more generic, the earlier in the list a partition appears).
+     */
+    private static final ArrayList<SystemPartition> SYSTEM_PARTITIONS =
+            new ArrayList<>(Arrays.asList(
+                    new SystemPartition(Environment.getRootDirectory(), PARTITION_SYSTEM,
+                            true /* containsPrivApp */, false /* containsOverlay */),
+                    new SystemPartition(Environment.getVendorDirectory(), PARTITION_VENDOR,
+                            true /* containsPrivApp */, true /* containsOverlay */),
+                    new SystemPartition(Environment.getOdmDirectory(), PARTITION_ODM,
+                            true /* containsPrivApp */, true /* containsOverlay */),
+                    new SystemPartition(Environment.getOemDirectory(), PARTITION_OEM,
+                            false /* containsPrivApp */, true /* containsOverlay */),
+                    new SystemPartition(Environment.getProductDirectory(), PARTITION_PRODUCT,
+                            true /* containsPrivApp */, true /* containsOverlay */),
+                    new SystemPartition(Environment.getSystemExtDirectory(), PARTITION_SYSTEM_EXT,
+                            true /* containsPrivApp */, true /* containsOverlay */)));
+
+    /**
+     * Returns a list in which the elements are products of the specified function applied to the
+     * list of {@link #SYSTEM_PARTITIONS} in increasing specificity order.
+     */
+    public static <T> ArrayList<T> getOrderedPartitions(
+            @NonNull Function<SystemPartition, T> producer) {
+        final ArrayList<T> out = new ArrayList<>();
+        for (int i = 0, n = SYSTEM_PARTITIONS.size(); i < n; i++) {
+            final T v = producer.apply(SYSTEM_PARTITIONS.get(i));
+            if (v != null)  {
+                out.add(v);
+            }
+        }
+        return out;
+    }
+
+    /** Represents a partition that contains application packages. */
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
+    public static class SystemPartition {
+        @NonNull
+        public final File folder;
+
+        @PartitionType
+        public final int type;
+
+        @Nullable
+        private final DeferredCanonicalFile mAppFolder;
+
+        @Nullable
+        private final DeferredCanonicalFile mPrivAppFolder;
+
+        @Nullable
+        private final DeferredCanonicalFile mOverlayFolder;
+
+        private SystemPartition(@NonNull File folder, @PartitionType int type,
+                boolean containsPrivApp, boolean containsOverlay) {
+            this.folder = folder;
+            this.type = type;
+            this.mAppFolder = new DeferredCanonicalFile(folder, "app");
+            this.mPrivAppFolder = containsPrivApp ?
+                    new DeferredCanonicalFile(folder, "priv-app") : null;
+            this.mOverlayFolder = containsOverlay ?
+                    new DeferredCanonicalFile(folder, "overlay") : null;
+        }
+
+        public SystemPartition(@NonNull SystemPartition original) {
+            this.folder = original.folder;
+            this.type = original.type;
+            this.mAppFolder = original.mAppFolder;
+            this.mPrivAppFolder = original.mPrivAppFolder;
+            this.mOverlayFolder = original.mOverlayFolder;
+        }
+
+        /**
+         * Creates a partition containing the same folders as the original partition but with a
+         * different root folder.
+         */
+        public SystemPartition(@NonNull File rootFolder, @NonNull SystemPartition partition) {
+            this(rootFolder, partition.type, partition.mPrivAppFolder != null,
+                    partition.mOverlayFolder != null);
+        }
+
+        /** Returns the canonical app folder of the partition. */
+        @Nullable
+        public File getAppFolder() {
+            return mAppFolder == null ? null : mAppFolder.getFile();
+        }
+
+        /** Returns the canonical priv-app folder of the partition, if one exists. */
+        @Nullable
+        public File getPrivAppFolder() {
+            return mPrivAppFolder == null ? null : mPrivAppFolder.getFile();
+        }
+
+        /** Returns the canonical overlay folder of the partition, if one exists. */
+        @Nullable
+        public File getOverlayFolder() {
+            return mOverlayFolder == null ? null : mOverlayFolder.getFile();
+        }
+
+        /** Returns whether the partition contains the specified file in its priv-app folder. */
+        public boolean containsPrivApp(@NonNull File scanFile) {
+            return FileUtils.contains(mPrivAppFolder.getFile(), scanFile);
+        }
+
+        /** Returns whether the partition contains the specified file in its app folder. */
+        public boolean containsApp(@NonNull File scanFile) {
+            return FileUtils.contains(mAppFolder.getFile(), scanFile);
+        }
+
+        /** Returns whether the partition contains the specified file in its overlay folder. */
+        public boolean containsOverlay(@NonNull File scanFile) {
+            return FileUtils.contains(mOverlayFolder.getFile(), scanFile);
+        }
+
+        /** Returns whether the partition contains the specified file. */
+        public boolean containsPath(@NonNull String path) {
+            return path.startsWith(folder.getPath() + "/");
+        }
+
+        /** Returns whether the partition contains the specified file in its priv-app folder. */
+        public boolean containsPrivPath(@NonNull String path) {
+            return mPrivAppFolder != null
+                    && path.startsWith(mPrivAppFolder.getFile().getPath() + "/");
+        }
+    }
+
+    /**
+     * A class that defers the canonicalization of its underlying file. This must be done so
+     * processes do not attempt to canonicalize files in directories for which the process does not
+     * have the correct selinux policies.
+     */
+    private static class DeferredCanonicalFile {
+        private boolean mIsCanonical;
+        private File mFile;
+        private DeferredCanonicalFile(File dir, String fileName) {
+            mFile = new File(dir, fileName);
+            mIsCanonical = false;
+        }
+
+        private File getFile() {
+            if (mIsCanonical) {
+                return mFile;
+            }
+            mIsCanonical = true;
+            try {
+                mFile = mFile.getCanonicalFile();
+            } catch (IOException ignore) {
+                // failed to look up canonical path, continue with original one
+            }
+            return mFile;
+        }
+    }
+}
diff --git a/core/java/android/content/pm/PackageUserState.java b/core/java/android/content/pm/PackageUserState.java
index da7623a..30cf4e7 100644
--- a/core/java/android/content/pm/PackageUserState.java
+++ b/core/java/android/content/pm/PackageUserState.java
@@ -28,7 +28,7 @@
 import static android.content.pm.PackageManager.MATCH_SYSTEM_ONLY;
 
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.pm.parsing.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedMainComponent;
 import android.os.BaseBundle;
 import android.os.Debug;
 import android.os.PersistableBundle;
@@ -163,7 +163,7 @@
     }
 
     public boolean isMatch(boolean isSystem, boolean isPackageEnabled,
-            ComponentParseUtils.ParsedComponent component, int flags) {
+            ParsedMainComponent component, int flags) {
         return isMatch(isSystem, isPackageEnabled, component.isEnabled(),
                 component.isDirectBootAware(), component.getName(), flags);
     }
@@ -217,7 +217,7 @@
     }
 
     public boolean isEnabled(boolean isPackageEnabled,
-            ComponentParseUtils.ParsedComponent parsedComponent, int flags) {
+            ParsedMainComponent parsedComponent, int flags) {
         return isEnabled(isPackageEnabled, parsedComponent.isEnabled(), parsedComponent.getName(),
                 flags);
     }
diff --git a/core/java/android/content/pm/ResolveInfo.java b/core/java/android/content/pm/ResolveInfo.java
index 55846ad..82b07f2 100644
--- a/core/java/android/content/pm/ResolveInfo.java
+++ b/core/java/android/content/pm/ResolveInfo.java
@@ -39,6 +39,8 @@
  */
 public class ResolveInfo implements Parcelable {
     private static final String TAG = "ResolveInfo";
+    private static final String INTENT_FORWARDER_ACTIVITY =
+            "com.android.internal.app.IntentForwarderActivity";
 
     /**
      * The activity or broadcast receiver that corresponds to this resolution
@@ -351,6 +353,16 @@
         }
     }
 
+    /**
+     * Returns whether this resolution represents the intent forwarder activity.
+     *
+     * @return whether this resolution represents the intent forwarder activity
+     */
+    public boolean isCrossProfileIntentForwarderActivity() {
+        return activityInfo != null
+                && INTENT_FORWARDER_ACTIVITY.equals(activityInfo.targetActivity);
+    }
+
     public ResolveInfo() {
         targetUserId = UserHandle.USER_CURRENT;
     }
diff --git a/core/java/android/content/pm/SharedLibraryInfo.java b/core/java/android/content/pm/SharedLibraryInfo.java
index 2863b26..fe4b36f 100644
--- a/core/java/android/content/pm/SharedLibraryInfo.java
+++ b/core/java/android/content/pm/SharedLibraryInfo.java
@@ -20,7 +20,6 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Parcel;
 import android.os.Parcelable;
 
@@ -39,28 +38,6 @@
 public final class SharedLibraryInfo implements Parcelable {
 
     /** @hide */
-    public static SharedLibraryInfo createForStatic(AndroidPackage pkg) {
-        return new SharedLibraryInfo(null, pkg.getPackageName(),
-                pkg.makeListAllCodePaths(),
-                pkg.getStaticSharedLibName(),
-                pkg.getStaticSharedLibVersion(),
-                TYPE_STATIC,
-                new VersionedPackage(pkg.getManifestPackageName(),
-                        pkg.getLongVersionCode()),
-                null, null);
-    }
-
-    /** @hide */
-    public static SharedLibraryInfo createForDynamic(AndroidPackage pkg, String name) {
-        return new SharedLibraryInfo(null, pkg.getPackageName(),
-                pkg.makeListAllCodePaths(), name,
-                (long) VERSION_UNDEFINED,
-                TYPE_DYNAMIC, new VersionedPackage(pkg.getPackageName(),
-                pkg.getLongVersionCode()),
-                null, null);
-    }
-
-    /** @hide */
     @IntDef(flag = true, prefix = { "TYPE_" }, value = {
             TYPE_BUILTIN,
             TYPE_DYNAMIC,
diff --git a/core/java/android/content/pm/ShortcutInfo.java b/core/java/android/content/pm/ShortcutInfo.java
index bde4f61..49e8c05 100644
--- a/core/java/android/content/pm/ShortcutInfo.java
+++ b/core/java/android/content/pm/ShortcutInfo.java
@@ -1726,11 +1726,11 @@
     }
 
     /**
-     * @return true if pinned but neither static nor dynamic.
+     * @return true if pinned or cached, but neither static nor dynamic.
      * @hide
      */
     public boolean isFloating() {
-        return isPinned() && !(isDynamic() || isManifestShortcut());
+        return (isPinned() || isCached()) && !(isDynamic() || isManifestShortcut());
     }
 
     /** @hide */
diff --git a/core/java/android/content/pm/ShortcutManager.java b/core/java/android/content/pm/ShortcutManager.java
index 3eea3f6..35c99a1 100644
--- a/core/java/android/content/pm/ShortcutManager.java
+++ b/core/java/android/content/pm/ShortcutManager.java
@@ -24,6 +24,7 @@
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
+import android.app.Notification;
 import android.app.usage.UsageStatsManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
@@ -741,4 +742,33 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Publish a single dynamic shortcut. If there are already dynamic or pinned shortcuts with the
+     * same ID, each mutable shortcut is updated.
+     *
+     * <p>This method is useful when posting notifications which are tagged with shortcut IDs; In
+     * order to make sure shortcuts exist and are up-to-date, without the need to explicitly handle
+     * the shortcut count limit.
+     * @see android.app.NotificationManager#notify(int, Notification)
+     * @see Notification.Builder#setShortcutId(String)
+     *
+     * <p>If {@link #getMaxShortcutCountPerActivity()} is already reached, an existing shortcut with
+     * the lowest rank will be removed to add space for the new shortcut.
+     *
+     * <p>If the rank of the shortcut is not explicitly set, it will be set to zero, and shortcut
+     * will be added to the top of the list.
+     *
+     * @throws IllegalArgumentException if trying to update an immutable shortcut.
+     *
+     * @throws IllegalStateException when the user is locked.
+     */
+    public void pushDynamicShortcut(@NonNull ShortcutInfo shortcut) {
+        try {
+            mService.pushDynamicShortcut(mContext.getPackageName(), shortcut, injectMyUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
 }
diff --git a/core/java/android/content/pm/ShortcutServiceInternal.java b/core/java/android/content/pm/ShortcutServiceInternal.java
index a69905e..a50ce92 100644
--- a/core/java/android/content/pm/ShortcutServiceInternal.java
+++ b/core/java/android/content/pm/ShortcutServiceInternal.java
@@ -22,6 +22,7 @@
 import android.appwidget.AppWidgetProviderInfo;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.LocusId;
 import android.content.pm.LauncherApps.ShortcutQuery;
@@ -64,6 +65,9 @@
 
     public abstract void addListener(@NonNull ShortcutChangeListener listener);
 
+    public abstract void addShortcutChangeCallback(
+            @NonNull LauncherApps.ShortcutChangeCallback callback);
+
     public abstract int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
             @NonNull String packageName, @NonNull String shortcutId, int userId);
 
@@ -92,4 +96,11 @@
     public abstract void uncacheShortcuts(int launcherUserId,
             @NonNull String callingPackage, @NonNull String packageName,
             @NonNull List<String> shortcutIds, int userId);
+
+    /**
+     * Retrieves all of the direct share targets that match the given IntentFilter for the specified
+     * user.
+     */
+    public abstract List<ShortcutManager.ShareShortcutInfo> getShareTargets(
+            @NonNull String callingPackage, @NonNull IntentFilter intentFilter, int userId);
 }
diff --git a/core/java/android/content/pm/dex/DexMetadataHelper.java b/core/java/android/content/pm/dex/DexMetadataHelper.java
index 4cd201f..cdb1d22 100644
--- a/core/java/android/content/pm/dex/DexMetadataHelper.java
+++ b/core/java/android/content/pm/dex/DexMetadataHelper.java
@@ -22,7 +22,6 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.parsing.AndroidPackage;
 import android.util.ArrayMap;
 import android.util.jar.StrictJarFile;
 
@@ -87,16 +86,6 @@
      *
      * NOTE: involves I/O checks.
      */
-    public static Map<String, String> getPackageDexMetadata(AndroidPackage pkg) {
-        return buildPackageApkToDexMetadataMap(pkg.makeListAllCodePaths());
-    }
-
-    /**
-     * Return the dex metadata files for the given package as a map
-     * [code path -> dex metadata path].
-     *
-     * NOTE: involves I/O checks.
-     */
     private static Map<String, String> getPackageDexMetadata(PackageLite pkg) {
         return buildPackageApkToDexMetadataMap(pkg.getAllCodePaths());
     }
@@ -114,7 +103,7 @@
      * This should only be used for code paths extracted from a package structure after the naming
      * was enforced in the installer.
      */
-    private static Map<String, String> buildPackageApkToDexMetadataMap(
+    public static Map<String, String> buildPackageApkToDexMetadataMap(
             List<String> codePaths) {
         ArrayMap<String, String> result = new ArrayMap<>();
         for (int i = codePaths.size() - 1; i >= 0; i--) {
@@ -157,25 +146,12 @@
     }
 
     /**
-     * Validate the dex metadata files installed for the given package.
-     *
-     * @throws PackageParserException in case of errors.
-     */
-    public static void validatePackageDexMetadata(AndroidPackage pkg)
-            throws PackageParserException {
-        Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
-        for (String dexMetadata : apkToDexMetadataList) {
-            validateDexMetadataFile(dexMetadata);
-        }
-    }
-
-    /**
      * Validate that the given file is a dex metadata archive.
      * This is just a sanity validation that the file is a zip archive.
      *
      * @throws PackageParserException if the file is not a .dm file.
      */
-    private static void validateDexMetadataFile(String dmaPath) throws PackageParserException {
+    public static void validateDexMetadataFile(String dmaPath) throws PackageParserException {
         StrictJarFile jarFile = null;
         try {
             jarFile = new StrictJarFile(dmaPath, false, false);
diff --git a/core/java/android/content/pm/parsing/AndroidPackage.java b/core/java/android/content/pm/parsing/AndroidPackage.java
deleted file mode 100644
index b93c3a2..0000000
--- a/core/java/android/content/pm/parsing/AndroidPackage.java
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.content.pm.parsing;
-
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageUserState;
-import android.content.pm.SharedLibraryInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.SparseArray;
-
-import java.security.PublicKey;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * The last state of a package during parsing/install before it is available in
- * {@link com.android.server.pm.PackageManagerService#mPackages}.
- *
- * It is the responsibility of the caller to understand what data is available at what step of the
- * parsing or install process.
- *
- * TODO(b/135203078): Nullability annotations
- * TODO(b/135203078): Remove get/setAppInfo differences
- *
- * @hide
- */
-public interface AndroidPackage extends Parcelable {
-
-    /**
-     * This will eventually be removed. Avoid calling this at all costs.
-     */
-    @Deprecated
-    AndroidPackageWrite mutate();
-
-    boolean canHaveOatDir();
-
-    boolean cantSaveState();
-
-    List<String> getAdoptPermissions();
-
-    List<String> getAllCodePaths();
-
-    List<String> getAllCodePathsExcludingResourceOnly();
-
-    String getAppComponentFactory();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getClassLoaderName()}
-     */
-    @Deprecated
-    String getAppInfoClassLoaderName();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getCodePath()}
-     */
-    @Deprecated
-    String getAppInfoCodePath();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getName()}
-     */
-    @Deprecated
-    String getAppInfoName();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getPackageName()}
-     */
-    @Deprecated
-    String getAppInfoPackageName();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getProcessName()}
-     */
-    @Deprecated
-    String getAppInfoProcessName();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getCodePath()}
-     */
-    @Deprecated
-    String getAppInfoResourcePath();
-
-    Bundle getAppMetaData();
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #getVolumeUuid()}
-     */
-    @Deprecated
-    String getApplicationInfoVolumeUuid();
-
-    String getBackupAgentName();
-
-    int getBanner();
-
-    String getBaseCodePath();
-
-    int getBaseRevisionCode();
-
-    int getCategory();
-
-    String getClassLoaderName();
-
-    String getClassName();
-
-    String getCodePath();
-
-    int getCompatibleWidthLimitDp();
-
-    int getCompileSdkVersion();
-
-    String getCompileSdkVersionCodeName();
-
-    @Nullable
-    List<ConfigurationInfo> getConfigPreferences();
-
-    String getCpuAbiOverride();
-
-    String getCredentialProtectedDataDir();
-
-    String getDataDir();
-
-    int getDescriptionRes();
-
-    String getDeviceProtectedDataDir();
-
-    List<FeatureGroupInfo> getFeatureGroups();
-
-    int getFlags();
-
-    int getFullBackupContent();
-
-    int getHiddenApiEnforcementPolicy();
-
-    int getIcon();
-
-    int getIconRes();
-
-    List<String> getImplicitPermissions();
-
-    int getInstallLocation();
-
-    Map<String, ArraySet<PublicKey>> getKeySetMapping();
-
-    int getLabelRes();
-
-    int getLargestWidthLimitDp();
-
-    long[] getLastPackageUsageTimeInMills();
-
-    long getLatestForegroundPackageUseTimeInMills();
-
-    long getLatestPackageUseTimeInMills();
-
-    List<String> getLibraryNames();
-
-    int getLogo();
-
-    long getLongVersionCode();
-
-    String getManageSpaceActivityName();
-
-    String getManifestPackageName();
-
-    float getMaxAspectRatio();
-
-    Bundle getMetaData(); // TODO(b/135203078): Make all the Bundles immutable
-
-    float getMinAspectRatio();
-
-    int getMinSdkVersion();
-
-    String getName();
-
-    String getNativeLibraryDir();
-
-    String getNativeLibraryRootDir();
-
-    int getNetworkSecurityConfigRes();
-
-    CharSequence getNonLocalizedLabel();
-
-    @Nullable
-    List<String> getOriginalPackages();
-
-    String getOverlayCategory();
-
-    int getOverlayPriority();
-
-    String getOverlayTarget();
-
-    String getOverlayTargetName();
-
-    /**
-     * Map of overlayable name to actor name.
-     */
-    Map<String, String> getOverlayables();
-
-    // TODO(b/135203078): Does this and getAppInfoPackageName have to be separate methods?
-    //  The refactor makes them the same value with no known consequences, so should be redundant.
-    String getPackageName();
-
-    @Nullable
-    List<ParsedActivity> getActivities();
-
-    @Nullable
-    List<ParsedInstrumentation> getInstrumentations();
-
-    @Nullable
-    List<ParsedFeature> getFeatures();
-
-    @Nullable
-    List<ParsedPermissionGroup> getPermissionGroups();
-
-    @Nullable
-    List<ParsedPermission> getPermissions();
-
-    @Nullable
-    List<ParsedProvider> getProviders();
-
-    @Nullable
-    List<ParsedActivity> getReceivers();
-
-    @Nullable
-    List<ParsedService> getServices();
-
-    String getPermission();
-
-    @Nullable
-    List<ParsedActivityIntentInfo> getPreferredActivityFilters();
-
-    int getPreferredOrder();
-
-    String getPrimaryCpuAbi();
-
-    int getPrivateFlags();
-
-    String getProcessName();
-
-    @Nullable
-    List<String> getProtectedBroadcasts();
-
-    String getPublicSourceDir();
-
-    List<Intent> getQueriesIntents();
-
-    List<String> getQueriesPackages();
-
-    Set<String> getQueriesProviders();
-
-    String getRealPackage();
-
-    // TODO(b/135203078): Rename to getRequiredFeatures? Somewhat ambiguous whether "Req" is
-    //  required or requested.
-    @Nullable
-    List<FeatureInfo> getReqFeatures();
-
-    List<String> getRequestedPermissions();
-
-    String getRequiredAccountType();
-
-    int getRequiresSmallestWidthDp();
-
-    byte[] getRestrictUpdateHash();
-
-    String getRestrictedAccountType();
-
-    int getRoundIconRes();
-
-    String getScanPublicSourceDir();
-
-    String getScanSourceDir();
-
-    String getSeInfo();
-
-    String getSeInfoUser();
-
-    String getSecondaryCpuAbi();
-
-    String getSecondaryNativeLibraryDir();
-
-    String getSharedUserId();
-
-    int getSharedUserLabel();
-
-    PackageParser.SigningDetails getSigningDetails();
-
-    String[] getSplitClassLoaderNames();
-
-    @Nullable
-    String[] getSplitCodePaths();
-
-    @Nullable
-    SparseArray<int[]> getSplitDependencies();
-
-    int[] getSplitFlags();
-
-    String[] getSplitNames();
-
-    String[] getSplitPublicSourceDirs();
-
-    int[] getSplitRevisionCodes();
-
-    String getStaticSharedLibName();
-
-    long getStaticSharedLibVersion();
-
-    // TODO(b/135203078): Return String directly
-    UUID getStorageUuid();
-
-    int getTargetSandboxVersion();
-
-    int getTargetSdkVersion();
-
-    String getTaskAffinity();
-
-    int getTheme();
-
-    int getUiOptions();
-
-    int getUid();
-
-    Set<String> getUpgradeKeySets();
-
-    @Nullable
-    List<String> getUsesLibraries();
-
-    @Nullable
-    String[] getUsesLibraryFiles();
-
-    List<SharedLibraryInfo> getUsesLibraryInfos();
-
-    @Nullable
-    List<String> getUsesOptionalLibraries();
-
-    @Nullable
-    List<String> getUsesStaticLibraries();
-
-    @Nullable
-    String[][] getUsesStaticLibrariesCertDigests();
-
-    @Nullable
-    long[] getUsesStaticLibrariesVersions();
-
-    @Nullable
-    ArrayMap<String, ComponentParseUtils.ParsedProcess> getProcesses();
-
-    int getVersionCode();
-
-    int getVersionCodeMajor();
-
-    String getVersionName();
-
-    String getVolumeUuid();
-
-    String getZygotePreloadName();
-
-    boolean hasComponentClassName(String className);
-
-    boolean hasPreserveLegacyExternalStorage();
-
-    // App Info
-
-    boolean hasRequestedLegacyExternalStorage();
-
-    boolean isBaseHardwareAccelerated();
-
-    boolean isCoreApp();
-
-    boolean isDefaultToDeviceProtectedStorage();
-
-    boolean isDirectBootAware();
-
-    boolean isEmbeddedDexUsed();
-
-    boolean isEnabled();
-
-    boolean isCrossProfile();
-
-    boolean isEncryptionAware();
-
-    boolean isExternal();
-
-    boolean isForceQueryable();
-
-    boolean isForwardLocked();
-
-    boolean isHiddenUntilInstalled();
-
-    boolean isInstantApp();
-
-    boolean isInternal();
-
-    boolean isLibrary();
-
-    // TODO(b/135203078): Should probably be in a utility class
-    boolean isMatch(int flags);
-
-    boolean isNativeLibraryRootRequiresIsa();
-
-    boolean isOem();
-
-    boolean isOverlayIsStatic();
-
-    boolean isPrivileged();
-
-    boolean isProduct();
-
-    boolean isProfileableByShell();
-
-    boolean isRequiredForAllUsers();
-
-    boolean isStaticSharedLibrary();
-
-    boolean isStub();
-
-    boolean isSystem(); // TODO(b/135203078): Collapse with isSystemApp, should be exactly the same.
-
-    boolean isSystemApp();
-
-    boolean isSystemExt();
-
-    boolean isUpdatedSystemApp();
-
-    boolean isUse32BitAbi();
-
-    boolean isVendor();
-
-    boolean isVisibleToInstantApps();
-
-    List<String> makeListAllCodePaths(); // TODO(b/135203078): Collapse with getAllCodePaths
-
-    boolean requestsIsolatedSplitLoading();
-
-    /**
-     * Generates an {@link ApplicationInfo} object with only the data available in this object.
-     *
-     * This does not contain any system or user state data, and should be avoided. Prefer
-     * {@link PackageInfoUtils#generateApplicationInfo(AndroidPackage, int, PackageUserState, int)}.
-     */
-    ApplicationInfo toAppInfoWithoutState();
-
-    Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
-        @Override
-        public PackageImpl createFromParcel(Parcel source) {
-            return new PackageImpl(source);
-        }
-
-        @Override
-        public PackageImpl[] newArray(int size) {
-            return new PackageImpl[size];
-        }
-    };
-}
diff --git a/core/java/android/content/pm/parsing/AndroidPackageWrite.java b/core/java/android/content/pm/parsing/AndroidPackageWrite.java
deleted file mode 100644
index b7595d2..0000000
--- a/core/java/android/content/pm/parsing/AndroidPackageWrite.java
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm.parsing;
-
-import android.annotation.Nullable;
-import android.content.pm.PackageParser;
-import android.content.pm.SharedLibraryInfo;
-
-import java.util.List;
-
-/**
- * Contains remaining mutable fields after package parsing has completed.
- *
- * Most are state that can probably be tracked outside of the AndroidPackage object. New methods
- * should never be added to this interface.
- *
- * TODO(b/135203078): Remove entirely
- *
- * @deprecated the eventual goal is that the object returned from parsing represents exactly what
- * was parsed from the APK, and so further mutation should be disallowed,
- * with any state being stored in another class
- *
- * @hide
- */
-@Deprecated
-public interface AndroidPackageWrite extends AndroidPackage {
-
-    AndroidPackageWrite setUsesLibraryFiles(@Nullable String[] usesLibraryFiles);
-
-    // TODO(b/135203078): Remove or use a non-system wide representation of the shared libraries;
-    //  this doesn't represent what was parsed from the APK
-    AndroidPackageWrite setUsesLibraryInfos(@Nullable List<SharedLibraryInfo> usesLibraryInfos);
-
-    AndroidPackageWrite setHiddenUntilInstalled(boolean hidden);
-
-    AndroidPackageWrite setUpdatedSystemApp(boolean updatedSystemApp);
-
-    AndroidPackageWrite setLastPackageUsageTimeInMills(int reason, long time);
-
-    AndroidPackageWrite setPrimaryCpuAbi(String primaryCpuAbi);
-
-    AndroidPackageWrite setSeInfo(String seInfo);
-
-    AndroidPackageWrite setSigningDetails(PackageParser.SigningDetails signingDetails);
-}
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 5be9c91..4c6da03 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -50,7 +50,7 @@
 /** @hide */
 public class ApkLiteParseUtils {
 
-    private static final String TAG = ApkParseUtils.TAG;
+    private static final String TAG = ParsingPackageUtils.TAG;
 
     // TODO(b/135203078): Consolidate constants
     private static final int DEFAULT_MIN_SDK_VERSION = 1;
@@ -235,7 +235,7 @@
                 final boolean skipVerify = (flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0;
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
                 try {
-                    signingDetails = ApkParseUtils.collectCertificates(apkFile.getAbsolutePath(),
+                    signingDetails = ParsingPackageUtils.collectCertificates(apkFile.getAbsolutePath(),
                             skipVerify, false, PackageParser.SigningDetails.UNKNOWN,
                             DEFAULT_TARGET_SDK_VERSION);
                 } finally {
@@ -289,6 +289,12 @@
         boolean useEmbeddedDex = false;
         String configForSplit = null;
         String usesSplitName = null;
+        String targetPackage = null;
+        boolean overlayIsStatic = false;
+        int overlayPriority = 0;
+
+        String requiredSystemPropertyName = null;
+        String requiredSystemPropertyValue = null;
 
         for (int i = 0; i < attrs.getAttributeCount(); i++) {
             final String attr = attrs.getAttributeName(i);
@@ -365,6 +371,21 @@
                             break;
                     }
                 }
+            } else if (PackageParser.TAG_OVERLAY.equals(parser.getName())) {
+                for (int i = 0; i < attrs.getAttributeCount(); ++i) {
+                    final String attr = attrs.getAttributeName(i);
+                    if ("requiredSystemPropertyName".equals(attr)) {
+                        requiredSystemPropertyName = attrs.getAttributeValue(i);
+                    } else if ("requiredSystemPropertyValue".equals(attr)) {
+                        requiredSystemPropertyValue = attrs.getAttributeValue(i);
+                    } else if ("targetPackage".equals(attr)) {
+                        targetPackage = attrs.getAttributeValue(i);;
+                    } else if ("isStatic".equals(attr)) {
+                        overlayIsStatic = attrs.getAttributeBooleanValue(i, false);
+                    } else if ("priority".equals(attr)) {
+                        overlayPriority = attrs.getAttributeIntValue(i, 0);
+                    }
+                }
             } else if (PackageParser.TAG_USES_SPLIT.equals(parser.getName())) {
                 if (usesSplitName != null) {
                     Slog.w(TAG, "Only one <uses-split> permitted. Ignoring others.");
@@ -391,11 +412,23 @@
             }
         }
 
+        // Check to see if overlay should be excluded based on system property condition
+        if (!PackageParser.checkRequiredSystemProperty(requiredSystemPropertyName,
+                requiredSystemPropertyValue)) {
+            Slog.i(TAG, "Skipping target and overlay pair " + targetPackage + " and "
+                    + codePath + ": overlay ignored due to required system property: "
+                    + requiredSystemPropertyName + " with value: " + requiredSystemPropertyValue);
+            targetPackage = null;
+            overlayIsStatic = false;
+            overlayPriority = 0;
+        }
+
         return new PackageParser.ApkLite(codePath, packageSplit.first, packageSplit.second,
                 isFeatureSplit, configForSplit, usesSplitName, isSplitRequired, versionCode,
                 versionCodeMajor, revisionCode, installLocation, verifiers, signingDetails,
                 coreApp, debuggable, multiArch, use32bitAbi, useEmbeddedDex, extractNativeLibs,
-                isolatedSplits, minSdkVersion, targetSdkVersion);
+                isolatedSplits, targetPackage, overlayIsStatic, overlayPriority, minSdkVersion,
+                targetSdkVersion);
     }
 
     public static VerifierInfo parseVerifier(AttributeSet attrs) {
diff --git a/core/java/android/content/pm/parsing/ApkParseUtils.java b/core/java/android/content/pm/parsing/ApkParseUtils.java
deleted file mode 100644
index 905794b..0000000
--- a/core/java/android/content/pm/parsing/ApkParseUtils.java
+++ /dev/null
@@ -1,3349 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm.parsing;
-
-import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.content.pm.PackageManager.FEATURE_WATCH;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
-import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
-import static android.os.Build.VERSION_CODES.O;
-import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.app.ActivityTaskManager;
-import android.app.ActivityThread;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.PackageParser.SigningDetails;
-import android.content.pm.Signature;
-import android.content.pm.permission.SplitPermissionInfoParcelable;
-import android.content.pm.split.DefaultSplitAssetLoader;
-import android.content.pm.split.SplitAssetDependencyLoader;
-import android.content.pm.split.SplitAssetLoader;
-import android.content.res.ApkAssets;
-import android.content.res.AssetManager;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.FileUtils;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.os.Trace;
-import android.os.ext.SdkExtensions;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.DisplayMetrics;
-import android.util.Pair;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.TypedValue;
-import android.util.apk.ApkSignatureVerifier;
-
-import com.android.internal.R;
-import com.android.internal.os.ClassLoaderFactory;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.XmlUtils;
-
-import libcore.io.IoUtils;
-import libcore.util.EmptyArray;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.File;
-import java.io.IOException;
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.StringTokenizer;
-
-/** @hide */
-public class ApkParseUtils {
-
-    // TODO(b/135203078): Consolidate log tags
-    static final String TAG = "PackageParsing";
-
-    /**
-     * Parse the package at the given location. Automatically detects if the
-     * package is a monolithic style (single APK file) or cluster style
-     * (directory of APKs).
-     * <p>
-     * This performs sanity checking on cluster style packages, such as
-     * requiring identical package name and version codes, a single base APK,
-     * and unique split names.
-     * <p>
-     * Note that this <em>does not</em> perform signature verification; that
-     * must be done separately in {@link #collectCertificates(ParsedPackage, boolean)}.
-     *
-     * If {@code useCaches} is true, the package parser might return a cached
-     * result from a previous parse of the same {@code packageFile} with the same
-     * {@code flags}. Note that this method does not check whether {@code packageFile}
-     * has changed since the last parse, it's up to callers to do so.
-     *
-     * @see PackageParser#parsePackageLite(File, int)
-     */
-    public static ParsingPackage parsePackage(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            DisplayMetrics displayMetrics,
-            boolean onlyCoreApps,
-            File packageFile,
-            int flags
-    ) throws PackageParserException {
-        if (packageFile.isDirectory()) {
-            return parseClusterPackage(parseInput, separateProcesses, callback, displayMetrics,
-                    onlyCoreApps, packageFile, flags);
-        } else {
-            return parseMonolithicPackage(parseInput, separateProcesses, callback, displayMetrics,
-                    onlyCoreApps, packageFile, flags);
-        }
-    }
-
-    /**
-     * Parse all APKs contained in the given directory, treating them as a
-     * single package. This also performs sanity checking, such as requiring
-     * identical package name and version codes, a single base APK, and unique
-     * split names.
-     * <p>
-     * Note that this <em>does not</em> perform signature verification; that
-     * must be done separately in {@link #collectCertificates(ParsedPackage, boolean)}.
-     */
-    private static ParsingPackage parseClusterPackage(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            DisplayMetrics displayMetrics,
-            boolean onlyCoreApps,
-            File packageDir,
-            int flags
-    ) throws PackageParserException {
-        final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir,
-                0);
-        if (onlyCoreApps && !lite.coreApp) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Not a coreApp: " + packageDir);
-        }
-
-        // Build the split dependency tree.
-        SparseArray<int[]> splitDependencies = null;
-        final SplitAssetLoader assetLoader;
-        if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
-            try {
-                splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
-                assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
-            } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
-            }
-        } else {
-            assetLoader = new DefaultSplitAssetLoader(lite, flags);
-        }
-
-        try {
-            final AssetManager assets = assetLoader.getBaseAssetManager();
-            final File baseApk = new File(lite.baseCodePath);
-            ParsingPackage parsingPackage = parseBaseApk(parseInput, separateProcesses, callback,
-                    displayMetrics, baseApk, assets, flags);
-            if (parsingPackage == null) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_NOT_APK,
-                        "Failed to parse base APK: " + baseApk);
-            }
-
-            if (!ArrayUtils.isEmpty(lite.splitNames)) {
-                parsingPackage.asSplit(
-                        lite.splitNames,
-                        lite.splitCodePaths,
-                        lite.splitRevisionCodes,
-                        splitDependencies
-                );
-                final int num = lite.splitNames.length;
-
-                for (int i = 0; i < num; i++) {
-                    final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
-                    parseSplitApk(parseInput, displayMetrics, separateProcesses, parsingPackage, i,
-                            splitAssets, flags);
-                }
-            }
-
-            return parsingPackage.setCodePath(lite.codePath)
-                    .setUse32BitAbi(lite.use32bitAbi);
-        } finally {
-            IoUtils.closeQuietly(assetLoader);
-        }
-    }
-
-    /**
-     * Parse the given APK file, treating it as as a single monolithic package.
-     * <p>
-     * Note that this <em>does not</em> perform signature verification; that
-     * must be done separately in {@link #collectCertificates(AndroidPackage, boolean)}.
-     */
-    public static ParsingPackage parseMonolithicPackage(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            DisplayMetrics displayMetrics,
-            boolean onlyCoreApps,
-            File apkFile,
-            int flags
-    ) throws PackageParserException {
-        final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile,
-                flags);
-        if (onlyCoreApps) {
-            if (!lite.coreApp) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Not a coreApp: " + apkFile);
-            }
-        }
-
-        final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
-        try {
-            return parseBaseApk(parseInput, separateProcesses, callback,
-                    displayMetrics, apkFile, assetLoader.getBaseAssetManager(), flags)
-                    .setCodePath(apkFile.getCanonicalPath())
-                    .setUse32BitAbi(lite.use32bitAbi);
-        } catch (IOException e) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
-                    "Failed to get path: " + apkFile, e);
-        } finally {
-            IoUtils.closeQuietly(assetLoader);
-        }
-    }
-
-    private static ParsingPackage parseBaseApk(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            DisplayMetrics displayMetrics,
-            File apkFile,
-            AssetManager assets,
-            int flags
-    ) throws PackageParserException {
-        final String apkPath = apkFile.getAbsolutePath();
-
-        String volumeUuid = null;
-        if (apkPath.startsWith(PackageParser.MNT_EXPAND)) {
-            final int end = apkPath.indexOf('/', PackageParser.MNT_EXPAND.length());
-            volumeUuid = apkPath.substring(PackageParser.MNT_EXPAND.length(), end);
-        }
-
-        if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
-
-        XmlResourceParser parser = null;
-        try {
-            final int cookie = assets.findCookieForPath(apkPath);
-            if (cookie == 0) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                        "Failed adding asset path: " + apkPath);
-            }
-            parser = assets.openXmlResourceParser(cookie, PackageParser.ANDROID_MANIFEST_FILENAME);
-            final Resources res = new Resources(assets, displayMetrics, null);
-
-            ParseResult result = parseBaseApk(parseInput, separateProcesses, callback, apkPath, res,
-                    parser, flags);
-            if (!result.isSuccess()) {
-                throw new PackageParserException(result.getParseError(),
-                        apkPath + " (at " + parser.getPositionDescription() + "): "
-                                + result.getErrorMessage());
-            }
-
-            ParsingPackage pkg = result.getResultAndNull();
-            ApkAssets apkAssets = assets.getApkAssets()[0];
-            if (apkAssets.definesOverlayable()) {
-                SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
-                int size = packageNames.size();
-                for (int index = 0; index < size; index++) {
-                    String packageName = packageNames.get(index);
-                    Map<String, String> overlayableToActor = assets.getOverlayableMap(packageName);
-                    if (overlayableToActor != null && !overlayableToActor.isEmpty()) {
-                        for (String overlayable : overlayableToActor.keySet()) {
-                            pkg.addOverlayable(overlayable, overlayableToActor.get(overlayable));
-                        }
-                    }
-                }
-            }
-
-            return pkg.setVolumeUuid(volumeUuid)
-                    .setApplicationVolumeUuid(volumeUuid)
-                    .setSigningDetails(SigningDetails.UNKNOWN);
-        } catch (PackageParserException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
-                    "Failed to read manifest from " + apkPath, e);
-        } finally {
-            IoUtils.closeQuietly(parser);
-        }
-    }
-
-    private static void parseSplitApk(
-            ParseInput parseInput,
-            DisplayMetrics displayMetrics,
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            int splitIndex,
-            AssetManager assets,
-            int flags
-    ) throws PackageParserException {
-        final String apkPath = parsingPackage.getSplitCodePaths()[splitIndex];
-
-        if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
-
-        final Resources res;
-        XmlResourceParser parser = null;
-        try {
-            // This must always succeed, as the path has been added to the AssetManager before.
-            final int cookie = assets.findCookieForPath(apkPath);
-            if (cookie == 0) {
-                throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                        "Failed adding asset path: " + apkPath);
-            }
-
-            parser = assets.openXmlResourceParser(cookie, PackageParser.ANDROID_MANIFEST_FILENAME);
-            res = new Resources(assets, displayMetrics, null);
-
-            final String[] outError = new String[1];
-            ParseResult parseResult = parseSplitApk(parseInput, separateProcesses, parsingPackage,
-                    res, parser, flags, splitIndex, outError);
-            if (!parseResult.isSuccess()) {
-                throw new PackageParserException(parseResult.getParseError(),
-                        apkPath + " (at " + parser.getPositionDescription() + "): "
-                                + parseResult.getErrorMessage());
-            }
-        } catch (PackageParserException e) {
-            throw e;
-        } catch (Exception e) {
-            throw new PackageParserException(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
-                    "Failed to read manifest from " + apkPath, e);
-        } finally {
-            IoUtils.closeQuietly(parser);
-        }
-    }
-
-    /**
-     * Parse the manifest of a <em>base APK</em>. When adding new features you
-     * need to consider whether they should be supported by split APKs and child
-     * packages.
-     *
-     * @param apkPath  The package apk file path
-     * @param res      The resources from which to resolve values
-     * @param parser   The manifest parser
-     * @param flags    Flags how to parse
-     * @return Parsed package or null on error.
-     */
-    private static ParseResult parseBaseApk(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            String apkPath,
-            Resources res,
-            XmlResourceParser parser,
-            int flags
-    ) throws XmlPullParserException, IOException {
-        final String splitName;
-        final String pkgName;
-
-        try {
-            Pair<String, String> packageSplit = PackageParser.parsePackageSplitNames(parser,
-                    parser);
-            pkgName = packageSplit.first;
-            splitName = packageSplit.second;
-
-            if (!TextUtils.isEmpty(splitName)) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
-                        "Expected base APK, but found split " + splitName
-                );
-            }
-        } catch (PackageParserException e) {
-            return parseInput.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME);
-        }
-
-        TypedArray manifestArray = null;
-
-        try {
-            manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
-
-            boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
-
-            ParsingPackage parsingPackage = PackageImpl.forParsing(
-                    pkgName,
-                    apkPath,
-                    manifestArray,
-                    isCoreApp
-            );
-
-            ParseResult result = parseBaseApkTags(parseInput, separateProcesses, callback,
-                    parsingPackage, manifestArray, res, parser, flags);
-            if (!result.isSuccess()) {
-                return result;
-            }
-
-            return parseInput.success(parsingPackage);
-        } finally {
-            if (manifestArray != null) {
-                manifestArray.recycle();
-            }
-        }
-    }
-
-    /**
-     * Parse the manifest of a <em>split APK</em>.
-     * <p>
-     * Note that split APKs have many more restrictions on what they're capable
-     * of doing, so many valid features of a base APK have been carefully
-     * omitted here.
-     *
-     * @param parsingPackage builder to fill
-     * @return false on failure
-     */
-    private static ParseResult parseSplitApk(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            int flags,
-            int splitIndex,
-            String[] outError
-    ) throws XmlPullParserException, IOException, PackageParserException {
-        AttributeSet attrs = parser;
-
-        // We parsed manifest tag earlier; just skip past it
-        PackageParser.parsePackageSplitNames(parser, attrs);
-
-        int type;
-
-        boolean foundApp = false;
-
-        int outerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals(PackageParser.TAG_APPLICATION)) {
-                if (foundApp) {
-                    if (PackageParser.RIGID_PARSER) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "<manifest> has more than one <application>"
-                        );
-                    } else {
-                        Slog.w(TAG, "<manifest> has more than one <application>");
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                }
-
-                foundApp = true;
-                ParseResult parseResult = parseSplitApplication(parseInput, separateProcesses,
-                        parsingPackage, res,
-                        parser, flags,
-                        splitIndex, outError);
-                if (!parseResult.isSuccess()) {
-                    return parseResult;
-                }
-
-            } else if (PackageParser.RIGID_PARSER) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Bad element under <manifest>: " + parser.getName()
-                );
-
-            } else {
-                Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
-                        + " at " + parsingPackage.getBaseCodePath() + " "
-                        + parser.getPositionDescription());
-                XmlUtils.skipCurrentTag(parser);
-                continue;
-            }
-        }
-
-        if (!foundApp) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY,
-                    "<manifest> does not contain an <application>"
-            );
-        }
-
-        return parseInput.success(parsingPackage);
-    }
-
-    /**
-     * Parse the {@code application} XML tree at the current parse location in a
-     * <em>split APK</em> manifest.
-     * <p>
-     * Note that split APKs have many more restrictions on what they're capable
-     * of doing, so many valid features of a base APK have been carefully
-     * omitted here.
-     */
-    private static ParseResult parseSplitApplication(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            int flags,
-            int splitIndex,
-            String[] outError
-    ) throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestApplication);
-
-        parsingPackage.setSplitHasCode(splitIndex, sa.getBoolean(
-                R.styleable.AndroidManifestApplication_hasCode, true));
-
-        final String classLoaderName = sa.getString(
-                R.styleable.AndroidManifestApplication_classLoader);
-        if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
-            parsingPackage.setSplitClassLoaderName(splitIndex, classLoaderName);
-        } else {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Invalid class loader name: " + classLoaderName
-            );
-        }
-
-        final int innerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            ComponentParseUtils.ParsedComponent parsedComponent = null;
-
-            String tagName = parser.getName();
-            switch (tagName) {
-                case "activity":
-                    ComponentParseUtils.ParsedActivity activity =
-                            ComponentParseUtils.parseActivity(separateProcesses,
-                                    parsingPackage,
-                                    res, parser, flags,
-                                    outError,
-                                    false,
-                                    parsingPackage.isBaseHardwareAccelerated());
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addActivity(activity);
-                    parsedComponent = activity;
-                    break;
-                case "receiver":
-                    activity = ComponentParseUtils.parseActivity(
-                            separateProcesses, parsingPackage,
-                            res, parser, flags, outError,
-                            true, false);
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addReceiver(activity);
-                    parsedComponent = activity;
-                    break;
-                case "service":
-                    ComponentParseUtils.ParsedService s = ComponentParseUtils.parseService(
-                            separateProcesses,
-                            parsingPackage,
-                            res, parser, flags, outError
-                    );
-                    if (s == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addService(s);
-                    parsedComponent = s;
-                    break;
-                case "provider":
-                    ComponentParseUtils.ParsedProvider p = ComponentParseUtils.parseProvider(
-                            separateProcesses,
-                            parsingPackage,
-                            res, parser, flags, outError);
-                    if (p == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addProvider(p);
-                    parsedComponent = p;
-                    break;
-                case "activity-alias":
-                    activity = ComponentParseUtils.parseActivityAlias(
-                            parsingPackage,
-                            res,
-                            parser,
-                            outError
-                    );
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addActivity(activity);
-                    parsedComponent = activity;
-                    break;
-                case "meta-data":
-                    // note: application meta-data is stored off to the side, so it can
-                    // remain null in the primary copy (we like to avoid extra copies because
-                    // it can be large)
-                    Bundle appMetaData = parseMetaData(parsingPackage, res, parser,
-                            parsingPackage.getAppMetaData(),
-                            outError);
-                    if (appMetaData == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.setAppMetaData(appMetaData);
-                    break;
-                case "uses-static-library":
-                    ParseResult parseResult = parseUsesStaticLibrary(parseInput, parsingPackage,
-                            res, parser);
-                    if (!parseResult.isSuccess()) {
-                        return parseResult;
-                    }
-
-                    break;
-                case "uses-library":
-                    sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesLibrary);
-
-                    // Note: don't allow this value to be a reference to a resource
-                    // that may change.
-                    String lname = sa.getNonResourceString(
-                            R.styleable.AndroidManifestUsesLibrary_name);
-                    boolean req = sa.getBoolean(
-                            R.styleable.AndroidManifestUsesLibrary_required, true);
-
-                    sa.recycle();
-
-                    if (lname != null) {
-                        lname = lname.intern();
-                        if (req) {
-                            // Upgrade to treat as stronger constraint
-                            parsingPackage.addUsesLibrary(lname)
-                                    .removeUsesOptionalLibrary(lname);
-                        } else {
-                            // Ignore if someone already defined as required
-                            if (!ArrayUtils.contains(parsingPackage.getUsesLibraries(), lname)) {
-                                parsingPackage.addUsesOptionalLibrary(lname);
-                            }
-                        }
-                    }
-
-                    XmlUtils.skipCurrentTag(parser);
-                    break;
-                case "uses-package":
-                    // Dependencies for app installers; we don't currently try to
-                    // enforce this.
-                    XmlUtils.skipCurrentTag(parser);
-                    break;
-                default:
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG, "Unknown element under <application>: " + tagName
-                                + " at " + parsingPackage.getBaseCodePath() + " "
-                                + parser.getPositionDescription());
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    } else {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Bad element under <application>: " + tagName
-                        );
-                    }
-            }
-
-            if (parsedComponent != null && parsedComponent.getSplitName() == null) {
-                // If the loaded component did not specify a split, inherit the split name
-                // based on the split it is defined in.
-                // This is used to later load the correct split when starting this
-                // component.
-                parsedComponent.setSplitName(parsingPackage.getSplitNames()[splitIndex]);
-            }
-        }
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseBaseApkTags(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            ParsingPackage parsingPackage,
-            TypedArray manifestArray,
-            Resources res,
-            XmlResourceParser parser,
-            int flags
-    ) throws XmlPullParserException, IOException {
-        int type;
-        boolean foundApp = false;
-
-        TypedArray sa = manifestArray;
-
-        ParseResult sharedUserResult = parseSharedUser(parseInput, parsingPackage, sa);
-        if (!sharedUserResult.isSuccess()) {
-            return sharedUserResult;
-        }
-
-        parseManifestAttributes(sa, parsingPackage, flags);
-
-        int outerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-
-            // All methods return a boolean, even if they can't fail. This can be enforced
-            // by making this final and not assigned, forcing the switch to assign success
-            // once in every branch.
-            final boolean success;
-            ParseResult parseResult = null;
-
-            // TODO(b/135203078): Either use all booleans or all ParseResults
-            // TODO(b/135203078): Convert to instance methods to share variables
-            switch (tagName) {
-                case PackageParser.TAG_APPLICATION:
-                    if (foundApp) {
-                        if (PackageParser.RIGID_PARSER) {
-                            return parseInput.error(
-                                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                    "<manifest> has more than one <application>"
-                            );
-                        } else {
-                            Slog.w(TAG, "<manifest> has more than one <application>");
-                            XmlUtils.skipCurrentTag(parser);
-                            success = true;
-                        }
-                    } else {
-                        foundApp = true;
-                        parseResult = parseBaseApplication(parseInput, separateProcesses,
-                                callback,
-                                parsingPackage, res, parser, flags);
-                        success = parseResult.isSuccess();
-                    }
-                    break;
-                case PackageParser.TAG_OVERLAY:
-                    parseResult = parseOverlay(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_KEY_SETS:
-                    parseResult = parseKeySets(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_FEATURE:
-                    parseResult = parseFeature(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_PERMISSION_GROUP:
-                    parseResult = parsePermissionGroup(parseInput, parsingPackage, res,
-                            parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_PERMISSION:
-                    parseResult = parsePermission(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_PERMISSION_TREE:
-                    parseResult = parsePermissionTree(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_USES_PERMISSION:
-                case PackageParser.TAG_USES_PERMISSION_SDK_M:
-                case PackageParser.TAG_USES_PERMISSION_SDK_23:
-                    parseResult = parseUsesPermission(parseInput, parsingPackage, res, parser,
-                            callback);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_USES_CONFIGURATION:
-                    success = parseUsesConfiguration(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_USES_FEATURE:
-                    success = parseUsesFeature(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_FEATURE_GROUP:
-                    success = parseFeatureGroup(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_USES_SDK:
-                    parseResult = parseUsesSdk(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_SUPPORT_SCREENS:
-                    success = parseSupportScreens(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_PROTECTED_BROADCAST:
-                    success = parseProtectedBroadcast(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_INSTRUMENTATION:
-                    parseResult = parseInstrumentation(parseInput, parsingPackage, res,
-                            parser);
-                    success = parseResult.isSuccess();
-                    break;
-                case PackageParser.TAG_ORIGINAL_PACKAGE:
-                    success = parseOriginalPackage(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_ADOPT_PERMISSIONS:
-                    success = parseAdoptPermissions(parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_USES_GL_TEXTURE:
-                case PackageParser.TAG_COMPATIBLE_SCREENS:
-                case PackageParser.TAG_SUPPORTS_INPUT:
-                case PackageParser.TAG_EAT_COMMENT:
-                    // Just skip this tag
-                    XmlUtils.skipCurrentTag(parser);
-                    success = true;
-                    break;
-                case PackageParser.TAG_RESTRICT_UPDATE:
-                    success = parseRestrictUpdateHash(flags, parsingPackage, res, parser);
-                    break;
-                case PackageParser.TAG_QUERIES:
-                    parseResult = parseQueries(parseInput, parsingPackage, res, parser);
-                    success = parseResult.isSuccess();
-                    break;
-                default:
-                    parseResult = parseUnknownTag(parseInput, parsingPackage, parser);
-                    success = parseResult.isSuccess();
-                    break;
-            }
-
-            if (parseResult != null && !parseResult.isSuccess()) {
-                return parseResult;
-            }
-
-            if (!success) {
-                return parseResult;
-            }
-        }
-
-        if (!foundApp && ArrayUtils.size(parsingPackage.getInstrumentations()) == 0) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY,
-                    "<manifest> does not contain an <application> or <instrumentation>"
-            );
-        }
-
-        if (!ComponentParseUtils.ParsedFeature.isCombinationValid(parsingPackage.getFeatures())) {
-            return parseInput.error(
-                    INSTALL_PARSE_FAILED_BAD_MANIFEST,
-                    "Combination <feature> tags are not valid"
-            );
-        }
-
-        convertNewPermissions(parsingPackage);
-
-        convertSplitPermissions(parsingPackage);
-
-        // At this point we can check if an application is not supporting densities and hence
-        // cannot be windowed / resized. Note that an SDK version of 0 is common for
-        // pre-Doughnut applications.
-        if (parsingPackage.usesCompatibilityMode()) {
-            adjustPackageToBeUnresizeableAndUnpipable(parsingPackage);
-        }
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseUnknownTag(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        if (PackageParser.RIGID_PARSER) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Bad element under <manifest>: " + parser.getName()
-            );
-        } else {
-            Slog.w(TAG, "Unknown element under <manifest>: " + parser.getName()
-                    + " at " + parsingPackage.getBaseCodePath() + " "
-                    + parser.getPositionDescription());
-            XmlUtils.skipCurrentTag(parser);
-            return parseInput.success(parsingPackage);
-        }
-    }
-
-    private static ParseResult parseSharedUser(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            TypedArray manifestArray
-    ) {
-        String str = manifestArray.getNonConfigurationString(
-                R.styleable.AndroidManifest_sharedUserId, 0);
-        if (TextUtils.isEmpty(str)) {
-            return parseInput.success(parsingPackage);
-        }
-
-        String nameError = validateName(str, true, true);
-        if (nameError != null && !"android".equals(parsingPackage.getPackageName())) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID,
-                    "<manifest> specifies bad sharedUserId name \"" + str + "\": "
-                            + nameError
-            );
-        }
-
-        int sharedUserLabel = manifestArray.getResourceId(
-                R.styleable.AndroidManifest_sharedUserLabel, 0);
-        parsingPackage.setSharedUserId(str.intern())
-                .setSharedUserLabel(sharedUserLabel);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static void parseManifestAttributes(
-            TypedArray manifestArray,
-            ParsingPackage parsingPackage,
-            int flags
-    ) {
-        int installLocation = manifestArray.getInteger(R.styleable.AndroidManifest_installLocation,
-                PackageParser.PARSE_DEFAULT_INSTALL_LOCATION);
-
-        final int targetSandboxVersion = manifestArray.getInteger(
-                R.styleable.AndroidManifest_targetSandboxVersion,
-                PackageParser.PARSE_DEFAULT_TARGET_SANDBOX);
-
-        parsingPackage.setInstallLocation(installLocation)
-                .setTargetSandboxVersion(targetSandboxVersion);
-
-        /* Set the global "on SD card" flag */
-        parsingPackage.setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0);
-
-        parsingPackage.setIsolatedSplitLoading(manifestArray.getBoolean(
-                R.styleable.AndroidManifest_isolatedSplits, false));
-    }
-
-    private static ParseResult parseKeySets(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        // we've encountered the 'key-sets' tag
-        // all the keys and keysets that we want must be defined here
-        // so we're going to iterate over the parser and pull out the things we want
-        int outerDepth = parser.getDepth();
-        int currentKeySetDepth = -1;
-        int type;
-        String currentKeySet = null;
-        ArrayMap<String, PublicKey> publicKeys = new ArrayMap<>();
-        ArraySet<String> upgradeKeySets = new ArraySet<>();
-        ArrayMap<String, ArraySet<String>> definedKeySets =
-                new ArrayMap<>();
-        ArraySet<String> improperKeySets = new ArraySet<>();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG) {
-                if (parser.getDepth() == currentKeySetDepth) {
-                    currentKeySet = null;
-                    currentKeySetDepth = -1;
-                }
-                continue;
-            }
-            String tagName = parser.getName();
-            if (tagName.equals("key-set")) {
-                if (currentKeySet != null) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Improperly nested 'key-set' tag at " + parser.getPositionDescription()
-                    );
-                }
-                final TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestKeySet);
-                final String keysetName = sa.getNonResourceString(
-                        R.styleable.AndroidManifestKeySet_name);
-                definedKeySets.put(keysetName, new ArraySet<>());
-                currentKeySet = keysetName;
-                currentKeySetDepth = parser.getDepth();
-                sa.recycle();
-            } else if (tagName.equals("public-key")) {
-                if (currentKeySet == null) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Improperly nested 'key-set' tag at " + parser.getPositionDescription()
-                    );
-                }
-                final TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestPublicKey);
-                final String publicKeyName = sa.getNonResourceString(
-                        R.styleable.AndroidManifestPublicKey_name);
-                final String encodedKey = sa.getNonResourceString(
-                        R.styleable.AndroidManifestPublicKey_value);
-                if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
-                    sa.recycle();
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "'public-key' " + publicKeyName + " must define a public-key value"
-                                    + " on first use at " + parser.getPositionDescription()
-                    );
-                } else if (encodedKey != null) {
-                    PublicKey currentKey = PackageParser.parsePublicKey(encodedKey);
-                    if (currentKey == null) {
-                        Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
-                                + parser.getPositionDescription() + " key-set " + currentKeySet
-                                + " will not be added to the package's defined key-sets.");
-                        sa.recycle();
-                        improperKeySets.add(currentKeySet);
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    if (publicKeys.get(publicKeyName) == null
-                            || publicKeys.get(publicKeyName).equals(currentKey)) {
-
-                        /* public-key first definition, or matches old definition */
-                        publicKeys.put(publicKeyName, currentKey);
-                    } else {
-                        sa.recycle();
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Value of 'public-key' " + publicKeyName
-                                        + " conflicts with previously defined value at "
-                                        + parser.getPositionDescription()
-                        );
-                    }
-                }
-                definedKeySets.get(currentKeySet).add(publicKeyName);
-                sa.recycle();
-                XmlUtils.skipCurrentTag(parser);
-            } else if (tagName.equals("upgrade-key-set")) {
-                final TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestUpgradeKeySet);
-                String name = sa.getNonResourceString(
-                        R.styleable.AndroidManifestUpgradeKeySet_name);
-                upgradeKeySets.add(name);
-                sa.recycle();
-                XmlUtils.skipCurrentTag(parser);
-            } else if (PackageParser.RIGID_PARSER) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Bad element under <key-sets>: " + parser.getName()
-                                + " at " + parsingPackage.getBaseCodePath() + " "
-                                + parser.getPositionDescription()
-                );
-            } else {
-                Slog.w(TAG, "Unknown element under <key-sets>: " + parser.getName()
-                        + " at " + parsingPackage.getBaseCodePath() + " "
-                        + parser.getPositionDescription());
-                XmlUtils.skipCurrentTag(parser);
-                continue;
-            }
-        }
-        String packageName = parsingPackage.getPackageName();
-        Set<String> publicKeyNames = publicKeys.keySet();
-        if (publicKeyNames.removeAll(definedKeySets.keySet())) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Package" + packageName + " AndroidManifest.xml "
-                            + "'key-set' and 'public-key' names must be distinct."
-            );
-        }
-
-        for (ArrayMap.Entry<String, ArraySet<String>> e : definedKeySets.entrySet()) {
-            final String keySetName = e.getKey();
-            if (e.getValue().size() == 0) {
-                Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml "
-                        + "'key-set' " + keySetName + " has no valid associated 'public-key'."
-                        + " Not including in package's defined key-sets.");
-                continue;
-            } else if (improperKeySets.contains(keySetName)) {
-                Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml "
-                        + "'key-set' " + keySetName + " contained improper 'public-key'"
-                        + " tags. Not including in package's defined key-sets.");
-                continue;
-            }
-
-            for (String s : e.getValue()) {
-                parsingPackage.addKeySet(keySetName, publicKeys.get(s));
-            }
-        }
-        if (parsingPackage.getKeySetMapping().keySet().containsAll(upgradeKeySets)) {
-            parsingPackage.setUpgradeKeySets(upgradeKeySets);
-        } else {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Package" + packageName + " AndroidManifest.xml "
-                            + "does not define all 'upgrade-key-set's ."
-            );
-        }
-
-        return parseInput.success(parsingPackage);
-    }
-
-    public static boolean parsePackageItemInfo(String packageName, PackageItemInfo outInfo,
-            String[] outError, String tag, TypedArray sa, boolean nameRequired,
-            int nameRes, int labelRes, int iconRes, int roundIconRes, int logoRes, int bannerRes) {
-        // This case can only happen in unit tests where we sometimes need to create fakes
-        // of various package parser data structures.
-        if (sa == null) {
-            outError[0] = tag + " does not contain any attributes";
-            return false;
-        }
-
-        String name = sa.getNonConfigurationString(nameRes, 0);
-        if (name == null) {
-            if (nameRequired) {
-                outError[0] = tag + " does not specify android:name";
-                return false;
-            }
-        } else {
-            String outInfoName = buildClassName(packageName, name);
-            if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
-                outError[0] = tag + " invalid android:name";
-                return false;
-            }
-            outInfo.name = outInfoName;
-            if (outInfoName == null) {
-                return false;
-            }
-        }
-
-        int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
-        if (roundIconVal != 0) {
-            outInfo.icon = roundIconVal;
-            outInfo.nonLocalizedLabel = null;
-        } else {
-            int iconVal = sa.getResourceId(iconRes, 0);
-            if (iconVal != 0) {
-                outInfo.icon = iconVal;
-                outInfo.nonLocalizedLabel = null;
-            }
-        }
-
-        int logoVal = sa.getResourceId(logoRes, 0);
-        if (logoVal != 0) {
-            outInfo.logo = logoVal;
-        }
-
-        int bannerVal = sa.getResourceId(bannerRes, 0);
-        if (bannerVal != 0) {
-            outInfo.banner = bannerVal;
-        }
-
-        TypedValue v = sa.peekValue(labelRes);
-        if (v != null && (outInfo.labelRes = v.resourceId) == 0) {
-            outInfo.nonLocalizedLabel = v.coerceToString();
-        }
-
-        outInfo.packageName = packageName;
-
-        return true;
-    }
-
-    private static ParseResult parsePackageItemInfo(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            String tag,
-            TypedArray sa,
-            boolean nameRequired,
-            int nameRes,
-            int labelRes,
-            int iconRes,
-            int roundIconRes,
-            int logoRes,
-            int bannerRes
-    ) {
-        // This case can only happen in unit tests where we sometimes need to create fakes
-        // of various package parser data structures.
-        if (sa == null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    tag + " does not contain any attributes"
-            );
-        }
-
-        String name = sa.getNonConfigurationString(nameRes, 0);
-        if (name == null) {
-            if (nameRequired) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        tag + " does not specify android:name"
-                );
-            }
-        } else {
-            String packageName = parsingPackage.getPackageName();
-            String outInfoName = buildClassName(packageName, name);
-            if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        tag + " invalid android:name"
-                );
-            } else if (outInfoName == null) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Empty class name in package " + packageName
-                );
-            }
-
-            parsingPackage.setName(outInfoName);
-        }
-
-        int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
-        if (roundIconVal != 0) {
-            parsingPackage.setIcon(roundIconVal)
-                    .setNonLocalizedLabel(null);
-        } else {
-            int iconVal = sa.getResourceId(iconRes, 0);
-            if (iconVal != 0) {
-                parsingPackage.setIcon(iconVal)
-                        .setNonLocalizedLabel(null);
-            }
-        }
-
-        int logoVal = sa.getResourceId(logoRes, 0);
-        if (logoVal != 0) {
-            parsingPackage.setLogo(logoVal);
-        }
-
-        int bannerVal = sa.getResourceId(bannerRes, 0);
-        if (bannerVal != 0) {
-            parsingPackage.setBanner(bannerVal);
-        }
-
-        TypedValue v = sa.peekValue(labelRes);
-        if (v != null) {
-            parsingPackage.setLabelRes(v.resourceId);
-            if (v.resourceId == 0) {
-                parsingPackage.setNonLocalizedLabel(v.coerceToString());
-            }
-        }
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseFeature(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-
-        ComponentParseUtils.ParsedFeature parsedFeature =
-                ComponentParseUtils.parseFeature(res, parser, outError);
-
-        if (parsedFeature == null || outError[0] != null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    outError[0]
-            );
-        }
-
-        parsingPackage.addFeature(parsedFeature);
-
-        return parseInput.success(parsingPackage);
-    }
-
-
-    private static ParseResult parsePermissionGroup(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-
-        ComponentParseUtils.ParsedPermissionGroup parsedPermissionGroup =
-                ComponentParseUtils.parsePermissionGroup(parsingPackage,
-                        res, parser, outError);
-
-        if (parsedPermissionGroup == null || outError[0] != null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    outError[0]
-            );
-        }
-
-        parsingPackage.addPermissionGroup(parsedPermissionGroup);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parsePermission(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-
-        ComponentParseUtils.ParsedPermission parsedPermission =
-                ComponentParseUtils.parsePermission(parsingPackage,
-                        res, parser, outError);
-
-        if (parsedPermission == null || outError[0] != null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    outError[0]
-            );
-        }
-
-        parsingPackage.addPermission(parsedPermission);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parsePermissionTree(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-
-        ComponentParseUtils.ParsedPermission parsedPermission =
-                ComponentParseUtils.parsePermissionTree(parsingPackage,
-                        res, parser, outError);
-
-        if (parsedPermission == null || outError[0] != null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    outError[0]
-            );
-        }
-
-        parsingPackage.addPermission(parsedPermission);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseUsesPermission(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            PackageParser.Callback callback
-    )
-            throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestUsesPermission);
-
-        // Note: don't allow this value to be a reference to a resource
-        // that may change.
-        String name = sa.getNonResourceString(
-                R.styleable.AndroidManifestUsesPermission_name);
-
-        int maxSdkVersion = 0;
-        TypedValue val = sa.peekValue(
-                R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
-        if (val != null) {
-            if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
-                maxSdkVersion = val.data;
-            }
-        }
-
-        final String requiredFeature = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
-
-        final String requiredNotfeature = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestUsesPermission_requiredNotFeature,
-                0);
-
-        sa.recycle();
-
-        XmlUtils.skipCurrentTag(parser);
-
-        // Can only succeed from here on out
-        ParseResult success = parseInput.success(parsingPackage);
-
-        if (name == null) {
-            return success;
-        }
-
-        if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
-            return success;
-        }
-
-        // Only allow requesting this permission if the platform supports the given feature.
-        if (requiredFeature != null && callback != null && !callback.hasFeature(requiredFeature)) {
-            return success;
-        }
-
-        // Only allow requesting this permission if the platform doesn't support the given feature.
-        if (requiredNotfeature != null && callback != null
-                && callback.hasFeature(requiredNotfeature)) {
-            return success;
-        }
-
-        if (!parsingPackage.getRequestedPermissions().contains(name)) {
-            parsingPackage.addRequestedPermission(name.intern());
-        } else {
-            Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
-                    + name + " in package: " + parsingPackage.getPackageName() + " at: "
-                    + parser.getPositionDescription());
-        }
-
-        return success;
-    }
-
-    private static boolean parseUsesConfiguration(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        ConfigurationInfo cPref = new ConfigurationInfo();
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestUsesConfiguration);
-        cPref.reqTouchScreen = sa.getInt(
-                R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
-                Configuration.TOUCHSCREEN_UNDEFINED);
-        cPref.reqKeyboardType = sa.getInt(
-                R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
-                Configuration.KEYBOARD_UNDEFINED);
-        if (sa.getBoolean(
-                R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
-                false)) {
-            cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
-        }
-        cPref.reqNavigation = sa.getInt(
-                R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
-                Configuration.NAVIGATION_UNDEFINED);
-        if (sa.getBoolean(
-                R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
-                false)) {
-            cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
-        }
-        sa.recycle();
-        parsingPackage.addConfigPreference(cPref);
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static boolean parseUsesFeature(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        FeatureInfo fi = parseFeatureInfo(res, parser);
-        parsingPackage.addReqFeature(fi);
-
-        if (fi.name == null) {
-            ConfigurationInfo cPref = new ConfigurationInfo();
-            cPref.reqGlEsVersion = fi.reqGlEsVersion;
-            parsingPackage.addConfigPreference(cPref);
-        }
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static FeatureInfo parseFeatureInfo(Resources res, AttributeSet attrs) {
-        FeatureInfo fi = new FeatureInfo();
-        TypedArray sa = res.obtainAttributes(attrs,
-                R.styleable.AndroidManifestUsesFeature);
-        // Note: don't allow this value to be a reference to a resource
-        // that may change.
-        fi.name = sa.getNonResourceString(R.styleable.AndroidManifestUsesFeature_name);
-        fi.version = sa.getInt(R.styleable.AndroidManifestUsesFeature_version, 0);
-        if (fi.name == null) {
-            fi.reqGlEsVersion = sa.getInt(R.styleable.AndroidManifestUsesFeature_glEsVersion,
-                    FeatureInfo.GL_ES_VERSION_UNDEFINED);
-        }
-        if (sa.getBoolean(R.styleable.AndroidManifestUsesFeature_required, true)) {
-            fi.flags |= FeatureInfo.FLAG_REQUIRED;
-        }
-        sa.recycle();
-        return fi;
-    }
-
-    private static boolean parseFeatureGroup(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        FeatureGroupInfo group = new FeatureGroupInfo();
-        ArrayList<FeatureInfo> features = null;
-        final int innerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            final String innerTagName = parser.getName();
-            if (innerTagName.equals("uses-feature")) {
-                FeatureInfo featureInfo = parseFeatureInfo(res, parser);
-                // FeatureGroups are stricter and mandate that
-                // any <uses-feature> declared are mandatory.
-                featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
-                features = ArrayUtils.add(features, featureInfo);
-            } else {
-                Slog.w(TAG,
-                        "Unknown element under <feature-group>: " + innerTagName +
-                                " at " + parsingPackage.getBaseCodePath() + " " +
-                                parser.getPositionDescription());
-            }
-            XmlUtils.skipCurrentTag(parser);
-        }
-
-        if (features != null) {
-            group.features = new FeatureInfo[features.size()];
-            group.features = features.toArray(group.features);
-        }
-
-        parsingPackage.addFeatureGroup(group);
-        return true;
-    }
-
-    private static ParseResult parseUsesSdk(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        if (PackageParser.SDK_VERSION > 0) {
-            TypedArray sa = res.obtainAttributes(parser,
-                    R.styleable.AndroidManifestUsesSdk);
-
-            int minVers = 1;
-            String minCode = null;
-            int targetVers = 0;
-            String targetCode = null;
-
-            TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);
-            if (val != null) {
-                if (val.type == TypedValue.TYPE_STRING && val.string != null) {
-                    minCode = val.string.toString();
-                } else {
-                    // If it's not a string, it's an integer.
-                    minVers = val.data;
-                }
-            }
-
-            val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
-            if (val != null) {
-                if (val.type == TypedValue.TYPE_STRING && val.string != null) {
-                    targetCode = val.string.toString();
-                    if (minCode == null) {
-                        minCode = targetCode;
-                    }
-                } else {
-                    // If it's not a string, it's an integer.
-                    targetVers = val.data;
-                }
-            } else {
-                targetVers = minVers;
-                targetCode = minCode;
-            }
-
-            sa.recycle();
-
-            // TODO(b/135203078): Remove, replace with ParseResult
-            String[] outError = new String[1];
-            final int minSdkVersion = PackageParser.computeMinSdkVersion(minVers,
-                    minCode,
-                    PackageParser.SDK_VERSION, PackageParser.SDK_CODENAMES, outError);
-            if (minSdkVersion < 0) {
-                return parseInput.error(
-                        PackageManager.INSTALL_FAILED_OLDER_SDK
-                );
-            }
-
-            final int targetSdkVersion = PackageParser.computeTargetSdkVersion(
-                    targetVers,
-                    targetCode, PackageParser.SDK_CODENAMES, outError);
-            if (targetSdkVersion < 0) {
-                return parseInput.error(
-                        PackageManager.INSTALL_FAILED_OLDER_SDK
-                );
-            }
-
-            int type;
-            final int innerDepth = parser.getDepth();
-            while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                    && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-                if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                    continue;
-                }
-                if (parser.getName().equals("extension-sdk")) {
-                    final ParseResult result =
-                            parseExtensionSdk(parseInput, parsingPackage, res, parser);
-                    if (!result.isSuccess()) {
-                        return result;
-                    }
-                } else {
-                    Slog.w(TAG, "Unknown element under <uses-sdk>: " + parser.getName()
-                            + " at " + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                }
-                XmlUtils.skipCurrentTag(parser);
-            }
-
-            parsingPackage.setMinSdkVersion(minSdkVersion)
-                    .setTargetSdkVersion(targetSdkVersion);
-        }
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseExtensionSdk(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser,
-                com.android.internal.R.styleable.AndroidManifestExtensionSdk);
-        int sdkVersion = sa.getInt(
-                com.android.internal.R.styleable.AndroidManifestExtensionSdk_sdkVersion, -1);
-        int minVersion = sa.getInt(
-                com.android.internal.R.styleable.AndroidManifestExtensionSdk_minExtensionVersion,
-                -1);
-        sa.recycle();
-
-        if (sdkVersion < 0) {
-            return parseInput.error(
-                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                "<extension-sdk> must specify an sdkVersion >= 0");
-        }
-        if (minVersion < 0) {
-            return parseInput.error(
-                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                "<extension-sdk> must specify minExtensionVersion >= 0");
-        }
-
-        try {
-            int version = SdkExtensions.getExtensionVersion(sdkVersion);
-            if (version < minVersion) {
-                return parseInput.error(
-                        PackageManager.INSTALL_FAILED_OLDER_SDK,
-                        "Package requires " + sdkVersion + " extension version " + minVersion
-                                + " which exceeds device version " + version);
-            }
-        } catch (RuntimeException e) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Specified sdkVersion " + sdkVersion + " is not valid");
-        }
-        return parseInput.success(parsingPackage);
-    }
-
-    private static boolean parseRestrictUpdateHash(
-            int flags,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        if ((flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
-            TypedArray sa = res.obtainAttributes(parser,
-                    R.styleable.AndroidManifestRestrictUpdate);
-            final String hash = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestRestrictUpdate_hash,
-                    0);
-            sa.recycle();
-
-            if (hash != null) {
-                final int hashLength = hash.length();
-                final byte[] hashBytes = new byte[hashLength / 2];
-                for (int i = 0; i < hashLength; i += 2) {
-                    hashBytes[i / 2] = (byte) ((Character.digit(hash.charAt(i), 16)
-                            << 4)
-                            + Character.digit(hash.charAt(i + 1), 16));
-                }
-                parsingPackage.setRestrictUpdateHash(hashBytes);
-            } else {
-                parsingPackage.setRestrictUpdateHash(null);
-            }
-        }
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static ParseResult parseQueries(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-
-        final int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-            if (parser.getName().equals("intent")) {
-                String[] outError = new String[1];
-                ComponentParseUtils.ParsedQueriesIntentInfo intentInfo =
-                        ComponentParseUtils.parsedParsedQueriesIntentInfo(
-                                parsingPackage, res, parser, outError
-                        );
-                if (intentInfo == null) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-
-                Uri data = null;
-                String dataType = null;
-                String host = "";
-                final int numActions = intentInfo.countActions();
-                final int numSchemes = intentInfo.countDataSchemes();
-                final int numTypes = intentInfo.countDataTypes();
-                final int numHosts = intentInfo.getHosts().length;
-                if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) {
-                    outError[0] = "intent tags must contain either an action or data.";
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-                if (numActions > 1) {
-                    outError[0] = "intent tag may have at most one action.";
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-                if (numTypes > 1) {
-                    outError[0] = "intent tag may have at most one data type.";
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-                if (numSchemes > 1) {
-                    outError[0] = "intent tag may have at most one data scheme.";
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-                if (numHosts > 1) {
-                    outError[0] = "intent tag may have at most one data host.";
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            outError[0]
-                    );
-                }
-                Intent intent = new Intent();
-                for (int i = 0, max = intentInfo.countCategories(); i < max; i++) {
-                    intent.addCategory(intentInfo.getCategory(i));
-                }
-                if (numHosts == 1) {
-                    host = intentInfo.getHosts()[0];
-                }
-                if (numSchemes == 1) {
-                    data = new Uri.Builder()
-                            .scheme(intentInfo.getDataScheme(0))
-                            .authority(host)
-                            .build();
-                }
-                if (numTypes == 1) {
-                    dataType = intentInfo.getDataType(0);
-                }
-                intent.setDataAndType(data, dataType);
-                if (numActions == 1) {
-                    intent.setAction(intentInfo.getAction(0));
-                }
-                parsingPackage.addQueriesIntent(intent);
-            } else if (parser.getName().equals("package")) {
-                final TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestQueriesPackage);
-                final String packageName =
-                        sa.getString(R.styleable.AndroidManifestQueriesPackage_name);
-                if (TextUtils.isEmpty(packageName)) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Package name is missing from package tag."
-                    );
-                }
-                parsingPackage.addQueriesPackage(packageName.intern());
-            } else if (parser.getName().equals("provider")) {
-                final TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestQueriesProvider);
-                try {
-                    final String authorities =
-                            sa.getString(R.styleable.AndroidManifestQueriesProvider_authorities);
-                    if (TextUtils.isEmpty(authorities)) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Authority missing from provider tag."
-                        );
-                    }
-                    StringTokenizer authoritiesTokenizer = new StringTokenizer(authorities, ";");
-                    while (authoritiesTokenizer.hasMoreElements()) {
-                        parsingPackage.addQueriesProvider(authoritiesTokenizer.nextToken());
-                    }
-                } finally {
-                    sa.recycle();
-                }
-            }
-        }
-        return parseInput.success(parsingPackage);
-    }
-
-    /**
-     * Parse the {@code application} XML tree at the current parse location in a
-     * <em>base APK</em> manifest.
-     * <p>
-     * When adding new features, carefully consider if they should also be
-     * supported by split APKs.
-     *
-     * @hide
-     */
-    public static ParseResult parseBaseApplication(
-            ParseInput parseInput,
-            String[] separateProcesses,
-            PackageParser.Callback callback,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            int flags
-    ) throws XmlPullParserException, IOException {
-        final String pkgName = parsingPackage.getPackageName();
-
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-        TypedArray sa = null;
-
-        try {
-            sa = res.obtainAttributes(parser,
-                    R.styleable.AndroidManifestApplication);
-
-
-            parsingPackage
-                    .setIconRes(
-                            sa.getResourceId(R.styleable.AndroidManifestApplication_icon, 0))
-                    .setRoundIconRes(
-                            sa.getResourceId(R.styleable.AndroidManifestApplication_roundIcon, 0));
-
-            ParseResult result = parsePackageItemInfo(
-                    parseInput,
-                    parsingPackage,
-                    "<application>",
-                    sa, false /*nameRequired*/,
-                    R.styleable.AndroidManifestApplication_name,
-                    R.styleable.AndroidManifestApplication_label,
-                    R.styleable.AndroidManifestApplication_icon,
-                    R.styleable.AndroidManifestApplication_roundIcon,
-                    R.styleable.AndroidManifestApplication_logo,
-                    R.styleable.AndroidManifestApplication_banner
-            );
-            if (!result.isSuccess()) {
-                return result;
-            }
-
-            String name = parsingPackage.getName();
-            if (name != null) {
-                parsingPackage.setClassName(name);
-            }
-
-            String manageSpaceActivity = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestApplication_manageSpaceActivity,
-                    Configuration.NATIVE_CONFIG_VERSION);
-            if (manageSpaceActivity != null) {
-                String manageSpaceActivityName = buildClassName(pkgName, manageSpaceActivity);
-
-                if (manageSpaceActivityName == null) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Empty class name in package " + pkgName
-                    );
-                }
-
-                parsingPackage.setManageSpaceActivityName(manageSpaceActivityName);
-            }
-
-            boolean allowBackup = sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowBackup, true);
-            parsingPackage.setAllowBackup(allowBackup);
-
-            if (allowBackup) {
-                // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
-                // and restoreAnyVersion are only relevant if backup is possible for the
-                // given application.
-                String backupAgent = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestApplication_backupAgent,
-                        Configuration.NATIVE_CONFIG_VERSION);
-                if (backupAgent != null) {
-                    String backupAgentName = buildClassName(pkgName, backupAgent);
-                    if (backupAgentName == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Empty class name in package " + pkgName
-                        );
-                    }
-
-                    if (PackageParser.DEBUG_BACKUP) {
-                        Slog.v(TAG, "android:backupAgent = " + backupAgentName
-                                + " from " + pkgName + "+" + backupAgent);
-                    }
-
-                    parsingPackage.setBackupAgentName(backupAgentName);
-
-                    parsingPackage.setKillAfterRestore(sa.getBoolean(
-                            R.styleable.AndroidManifestApplication_killAfterRestore, true));
-
-                    parsingPackage.setRestoreAnyVersion(sa.getBoolean(
-                            R.styleable.AndroidManifestApplication_restoreAnyVersion, false));
-
-                    parsingPackage.setFullBackupOnly(sa.getBoolean(
-                            R.styleable.AndroidManifestApplication_fullBackupOnly, false));
-
-                    parsingPackage.setBackupInForeground(sa.getBoolean(
-                            R.styleable.AndroidManifestApplication_backupInForeground,
-                            false));
-                }
-
-                TypedValue v = sa.peekValue(
-                        R.styleable.AndroidManifestApplication_fullBackupContent);
-                int fullBackupContent = 0;
-
-                if (v != null) {
-                    fullBackupContent = v.resourceId;
-
-                    if (v.resourceId == 0) {
-                        if (PackageParser.DEBUG_BACKUP) {
-                            Slog.v(TAG, "fullBackupContent specified as boolean=" +
-                                    (v.data == 0 ? "false" : "true"));
-                        }
-                        // "false" => -1, "true" => 0
-                        fullBackupContent = v.data == 0 ? -1 : 0;
-                    }
-
-                    parsingPackage.setFullBackupContent(fullBackupContent);
-                }
-                if (PackageParser.DEBUG_BACKUP) {
-                    Slog.v(TAG, "fullBackupContent=" + fullBackupContent + " for " + pkgName);
-                }
-            }
-
-            parsingPackage
-                    .setTheme(
-                            sa.getResourceId(R.styleable.AndroidManifestApplication_theme, 0))
-                    .setDescriptionRes(
-                            sa.getResourceId(R.styleable.AndroidManifestApplication_description,
-                                    0));
-
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_persistent,
-                    false)) {
-                // Check if persistence is based on a feature being present
-                final String requiredFeature = sa.getNonResourceString(R.styleable
-                        .AndroidManifestApplication_persistentWhenFeatureAvailable);
-                parsingPackage.setPersistent(requiredFeature == null
-                        || callback.hasFeature(requiredFeature));
-            }
-
-            boolean requiredForAllUsers = sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_requiredForAllUsers,
-                    false);
-            parsingPackage.setRequiredForAllUsers(requiredForAllUsers);
-
-            String restrictedAccountType = sa.getString(R.styleable
-                    .AndroidManifestApplication_restrictedAccountType);
-            if (restrictedAccountType != null && restrictedAccountType.length() > 0) {
-                parsingPackage.setRestrictedAccountType(restrictedAccountType);
-            }
-
-            String requiredAccountType = sa.getString(R.styleable
-                    .AndroidManifestApplication_requiredAccountType);
-            if (requiredAccountType != null && requiredAccountType.length() > 0) {
-                parsingPackage.setRequiredAccountType(requiredAccountType);
-            }
-
-            parsingPackage.setForceQueryable(
-                    sa.getBoolean(R.styleable.AndroidManifestApplication_forceQueryable, false)
-            );
-
-            boolean debuggable = sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_debuggable,
-                    false
-            );
-
-            parsingPackage.setDebuggable(debuggable);
-
-            if (debuggable) {
-                // Debuggable implies profileable
-                parsingPackage.setProfileableByShell(true);
-            }
-
-            parsingPackage.setVmSafeMode(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_vmSafeMode, false));
-
-            boolean baseHardwareAccelerated = sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_hardwareAccelerated,
-                    parsingPackage.getTargetSdkVersion()
-                            >= Build.VERSION_CODES.ICE_CREAM_SANDWICH);
-            parsingPackage.setBaseHardwareAccelerated(baseHardwareAccelerated);
-
-            parsingPackage.setHasCode(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_hasCode, true));
-
-            parsingPackage.setAllowTaskReparenting(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowTaskReparenting, false));
-
-            parsingPackage.setAllowClearUserData(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowClearUserData, true));
-
-            parsingPackage.setTestOnly(sa.getBoolean(
-                    com.android.internal.R.styleable.AndroidManifestApplication_testOnly,
-                    false));
-
-            parsingPackage.setLargeHeap(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_largeHeap, false));
-
-            parsingPackage.setUsesCleartextTraffic(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_usesCleartextTraffic,
-                    parsingPackage.getTargetSdkVersion() < Build.VERSION_CODES.P));
-
-            parsingPackage.setSupportsRtl(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_supportsRtl,
-                    false /* default is no RTL support*/));
-
-            parsingPackage.setMultiArch(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_multiArch, false));
-
-            parsingPackage.setExtractNativeLibs(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_extractNativeLibs, true));
-
-            parsingPackage.setUseEmbeddedDex(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_useEmbeddedDex, false));
-
-            parsingPackage.setDefaultToDeviceProtectedStorage(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage,
-                    false));
-
-            parsingPackage.setDirectBootAware(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_directBootAware, false));
-
-            if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
-                parsingPackage.setActivitiesResizeModeResizeable(sa.getBoolean(
-                        R.styleable.AndroidManifestApplication_resizeableActivity, true));
-            } else {
-                parsingPackage.setActivitiesResizeModeResizeableViaSdkVersion(
-                        parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.N);
-            }
-
-            parsingPackage.setAllowClearUserDataOnFailedRestore(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowClearUserDataOnFailedRestore,
-                    true));
-
-
-            parsingPackage.setAllowAudioPlaybackCapture(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture,
-                    parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q));
-
-            parsingPackage.setRequestLegacyExternalStorage(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_requestLegacyExternalStorage,
-                    parsingPackage.getTargetSdkVersion() < Build.VERSION_CODES.Q));
-
-            parsingPackage.setAllowNativeHeapPointerTagging(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_allowNativeHeapPointerTagging, true));
-
-            parsingPackage.setPreserveLegacyExternalStorage(sa.getBoolean(
-                            R.styleable.AndroidManifestApplication_preserveLegacyExternalStorage,
-                            false));
-
-            parsingPackage
-                    .setMaxAspectRatio(
-                            sa.getFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, 0))
-                    .setMinAspectRatio(
-                            sa.getFloat(R.styleable.AndroidManifestApplication_minAspectRatio, 0))
-                    .setNetworkSecurityConfigRes(sa.getResourceId(
-                            R.styleable.AndroidManifestApplication_networkSecurityConfig, 0))
-                    .setCategory(sa.getInt(R.styleable.AndroidManifestApplication_appCategory,
-                            ApplicationInfo.CATEGORY_UNDEFINED));
-
-            String str;
-            str = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestApplication_permission, 0);
-            parsingPackage.setPermission((str != null && str.length() > 0) ? str.intern() : null);
-
-            if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestApplication_taskAffinity,
-                        Configuration.NATIVE_CONFIG_VERSION);
-            } else {
-                // Some older apps have been seen to use a resource reference
-                // here that on older builds was ignored (with a warning).  We
-                // need to continue to do this for them so they don't break.
-                str = sa.getNonResourceString(
-                        R.styleable.AndroidManifestApplication_taskAffinity);
-            }
-            String packageName = parsingPackage.getPackageName();
-            String taskAffinity = PackageParser.buildTaskAffinityName(packageName,
-                    packageName,
-                    str, outError);
-
-            if (outError[0] != null) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        outError[0]
-                );
-            }
-
-            parsingPackage.setTaskAffinity(taskAffinity);
-            String factory = sa.getNonResourceString(
-                    R.styleable.AndroidManifestApplication_appComponentFactory);
-            if (factory != null) {
-                String appComponentFactory = buildClassName(packageName, factory);
-                if (appComponentFactory == null) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "Empty class name in package " + pkgName
-                    );
-                }
-
-                parsingPackage.setAppComponentFactory(appComponentFactory);
-            }
-
-            parsingPackage.setUsesNonSdkApi(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_usesNonSdkApi, false));
-
-            parsingPackage.setHasFragileUserData(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_hasFragileUserData, false));
-
-            CharSequence pname;
-            if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
-                pname = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestApplication_process,
-                        Configuration.NATIVE_CONFIG_VERSION);
-            } else {
-                // Some older apps have been seen to use a resource reference
-                // here that on older builds was ignored (with a warning).  We
-                // need to continue to do this for them so they don't break.
-                pname = sa.getNonResourceString(
-                        R.styleable.AndroidManifestApplication_process);
-            }
-            String processName = PackageParser.buildProcessName(packageName, null, pname, flags,
-                    separateProcesses, outError);
-
-            if (outError[0] != null) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        outError[0]
-                );
-            }
-
-            parsingPackage
-                    .setProcessName(processName)
-                    .setEnabled(
-                            sa.getBoolean(R.styleable.AndroidManifestApplication_enabled,
-                                    true));
-
-            parsingPackage.setCrossProfile(
-                    sa.getBoolean(R.styleable.AndroidManifestApplication_crossProfile, false));
-
-            parsingPackage.setIsGame(sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_isGame, false));
-
-            boolean cantSaveState = sa.getBoolean(
-                    R.styleable.AndroidManifestApplication_cantSaveState, false);
-            parsingPackage.setCantSaveState(cantSaveState);
-            if (cantSaveState) {
-                // A heavy-weight application can not be in a custom process.
-                // We can do direct compare because we intern all strings.
-                if (processName != null && !processName.equals(packageName)) {
-                    return parseInput.error(
-                            PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                            "cantSaveState applications can not use custom processes"
-                    );
-                }
-            }
-
-            String classLoaderName = sa.getString(
-                    R.styleable.AndroidManifestApplication_classLoader);
-            parsingPackage
-                    .setUiOptions(sa.getInt(R.styleable.AndroidManifestApplication_uiOptions, 0))
-                    .setClassLoaderName(classLoaderName)
-                    .setZygotePreloadName(
-                            sa.getString(R.styleable.AndroidManifestApplication_zygotePreloadName));
-
-            if (classLoaderName != null
-                    && !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        "Invalid class loader name: " + classLoaderName
-                );
-            }
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        final int innerDepth = parser.getDepth();
-        int type;
-        boolean hasActivityOrder = false;
-        boolean hasReceiverOrder = false;
-        boolean hasServiceOrder = false;
-
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            switch (tagName) {
-                case "activity":
-                    ComponentParseUtils.ParsedActivity activity =
-                            ComponentParseUtils.parseActivity(separateProcesses,
-                                    parsingPackage,
-                                    res, parser, flags,
-                                    outError, false,
-                                    parsingPackage.isBaseHardwareAccelerated());
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    hasActivityOrder |= (activity.order != 0);
-                    parsingPackage.addActivity(activity);
-                    break;
-                case "receiver":
-                    activity = ComponentParseUtils.parseActivity(separateProcesses,
-                            parsingPackage,
-                            res, parser,
-                            flags, outError,
-                            true, false);
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    hasReceiverOrder |= (activity.order != 0);
-                    parsingPackage.addReceiver(activity);
-                    break;
-                case "service":
-                    ComponentParseUtils.ParsedService s = ComponentParseUtils.parseService(
-                            separateProcesses,
-                            parsingPackage,
-                            res, parser, flags,
-                            outError);
-                    if (s == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    hasServiceOrder |= (s.order != 0);
-                    parsingPackage.addService(s);
-                    break;
-                case "provider":
-                    ComponentParseUtils.ParsedProvider p = ComponentParseUtils.parseProvider(
-                            separateProcesses,
-                            parsingPackage,
-                            res, parser, flags,
-                            outError
-                    );
-                    if (p == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.addProvider(p);
-                    break;
-                case "activity-alias":
-                    activity = ComponentParseUtils.parseActivityAlias(
-                            parsingPackage,
-                            res,
-                            parser,
-                            outError
-                    );
-                    if (activity == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    hasActivityOrder |= (activity.order != 0);
-                    parsingPackage.addActivity(activity);
-                    break;
-                case "meta-data":
-                    // note: application meta-data is stored off to the side, so it can
-                    // remain null in the primary copy (we like to avoid extra copies because
-                    // it can be large)
-                    Bundle appMetaData = parseMetaData(parsingPackage, res, parser,
-                            parsingPackage.getAppMetaData(),
-                            outError);
-                    if (appMetaData == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.setAppMetaData(appMetaData);
-                    break;
-                case "static-library":
-                    sa = res.obtainAttributes(parser,
-                            R.styleable.AndroidManifestStaticLibrary);
-
-                    // Note: don't allow this value to be a reference to a resource
-                    // that may change.
-                    String lname = sa.getNonResourceString(
-                            R.styleable.AndroidManifestStaticLibrary_name);
-                    final int version = sa.getInt(
-                            R.styleable.AndroidManifestStaticLibrary_version, -1);
-                    final int versionMajor = sa.getInt(
-                            R.styleable.AndroidManifestStaticLibrary_versionMajor,
-                            0);
-
-                    sa.recycle();
-
-                    // Since the app canot run without a static lib - fail if malformed
-                    if (lname == null || version < 0) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Bad static-library declaration name: " + lname
-                                        + " version: " + version
-                        );
-                    }
-
-                    if (parsingPackage.getSharedUserId() != null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID,
-                                "sharedUserId not allowed in static shared library"
-                        );
-                    }
-
-                    if (parsingPackage.getStaticSharedLibName() != null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Multiple static-shared libs for package " + pkgName
-                        );
-                    }
-
-                    parsingPackage.setStaticSharedLibName(lname.intern());
-                    if (version >= 0) {
-                        parsingPackage.setStaticSharedLibVersion(
-                                PackageInfo.composeLongVersionCode(versionMajor, version));
-                    } else {
-                        parsingPackage.setStaticSharedLibVersion(version);
-                    }
-                    parsingPackage.setStaticSharedLibrary(true);
-
-                    XmlUtils.skipCurrentTag(parser);
-
-                    break;
-                case "library":
-                    sa = res.obtainAttributes(parser,
-                            R.styleable.AndroidManifestLibrary);
-
-                    // Note: don't allow this value to be a reference to a resource
-                    // that may change.
-                    lname = sa.getNonResourceString(
-                            R.styleable.AndroidManifestLibrary_name);
-
-                    sa.recycle();
-
-                    if (lname != null) {
-                        lname = lname.intern();
-                        if (!ArrayUtils.contains(parsingPackage.getLibraryNames(), lname)) {
-                            parsingPackage.addLibraryName(lname);
-                        }
-                    }
-
-                    XmlUtils.skipCurrentTag(parser);
-
-                    break;
-                case "uses-static-library":
-                    ParseResult parseResult = parseUsesStaticLibrary(parseInput, parsingPackage,
-                            res, parser);
-                    if (!parseResult.isSuccess()) {
-                        return parseResult;
-                    }
-                    break;
-                case "uses-library":
-                    sa = res.obtainAttributes(parser,
-                            R.styleable.AndroidManifestUsesLibrary);
-
-                    // Note: don't allow this value to be a reference to a resource
-                    // that may change.
-                    lname = sa.getNonResourceString(
-                            R.styleable.AndroidManifestUsesLibrary_name);
-                    boolean req = sa.getBoolean(
-                            R.styleable.AndroidManifestUsesLibrary_required,
-                            true);
-
-                    sa.recycle();
-
-                    if (lname != null) {
-                        lname = lname.intern();
-                        if (req) {
-                            parsingPackage.addUsesLibrary(lname);
-                        } else {
-                            parsingPackage.addUsesOptionalLibrary(lname);
-                        }
-                    }
-
-                    XmlUtils.skipCurrentTag(parser);
-
-                    break;
-                case "processes":
-                    ArrayMap<String, ComponentParseUtils.ParsedProcess> processes =
-                            ComponentParseUtils.parseProcesses(separateProcesses,
-                                    parsingPackage,
-                                    res, parser, flags,
-                                    outError);
-                    if (processes == null) {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                outError[0]
-                        );
-                    }
-
-                    parsingPackage.setProcesses(processes);
-                    break;
-                case "uses-package":
-                    // Dependencies for app installers; we don't currently try to
-                    // enforce this.
-                    XmlUtils.skipCurrentTag(parser);
-                    break;
-                case "profileable":
-                    sa = res.obtainAttributes(parser,
-                            R.styleable.AndroidManifestProfileable);
-                    if (sa.getBoolean(
-                            R.styleable.AndroidManifestProfileable_shell, false)) {
-                        parsingPackage.setProfileableByShell(true);
-                    }
-                    XmlUtils.skipCurrentTag(parser);
-                    break;
-                default:
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG, "Unknown element under <application>: " + tagName
-                                + " at " + parsingPackage.getBaseCodePath() + " "
-                                + parser.getPositionDescription());
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    } else {
-                        return parseInput.error(
-                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                                "Bad element under <application>: " + tagName
-                        );
-                    }
-            }
-        }
-
-        if (TextUtils.isEmpty(parsingPackage.getStaticSharedLibName())) {
-            // Add a hidden app detail activity to normal apps which forwards user to App Details
-            // page.
-            ComponentParseUtils.ParsedActivity a = generateAppDetailsHiddenActivity(
-                    parsingPackage,
-                    outError
-            );
-            // Ignore errors here
-            parsingPackage.addActivity(a);
-        }
-
-        if (hasActivityOrder) {
-            parsingPackage.sortActivities();
-        }
-        if (hasReceiverOrder) {
-            parsingPackage.sortReceivers();
-        }
-        if (hasServiceOrder) {
-            parsingPackage.sortServices();
-        }
-        // Must be ran after the entire {@link ApplicationInfo} has been fully processed and after
-        // every activity info has had a chance to set it from its attributes.
-        setMaxAspectRatio(parsingPackage);
-        setMinAspectRatio(parsingPackage, callback);
-
-        parsingPackage.setHasDomainUrls(hasDomainURLs(parsingPackage));
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static ParseResult parseUsesStaticLibrary(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestUsesStaticLibrary);
-
-        // Note: don't allow this value to be a reference to a resource that may change.
-        String lname = sa.getNonResourceString(
-                R.styleable.AndroidManifestUsesLibrary_name);
-        final int version = sa.getInt(
-                R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
-        String certSha256Digest = sa.getNonResourceString(com.android.internal.R.styleable
-                .AndroidManifestUsesStaticLibrary_certDigest);
-        sa.recycle();
-
-        // Since an APK providing a static shared lib can only provide the lib - fail if malformed
-        if (lname == null || version < 0 || certSha256Digest == null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Bad uses-static-library declaration name: " + lname + " version: "
-                            + version + " certDigest" + certSha256Digest
-            );
-        }
-
-        // Can depend only on one version of the same library
-        List<String> usesStaticLibraries = parsingPackage.getUsesStaticLibraries();
-        if (usesStaticLibraries != null && usesStaticLibraries.contains(lname)) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Depending on multiple versions of static library " + lname
-            );
-        }
-
-        lname = lname.intern();
-        // We allow ":" delimiters in the SHA declaration as this is the format
-        // emitted by the certtool making it easy for developers to copy/paste.
-        certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
-
-        // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
-        String[] additionalCertSha256Digests = EmptyArray.STRING;
-        if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.O_MR1) {
-            // TODO(b/135203078): Remove, replace with ParseResult
-            String[] outError = new String[1];
-            additionalCertSha256Digests = parseAdditionalCertificates(res, parser, outError);
-            if (additionalCertSha256Digests == null || outError[0] != null) {
-                return parseInput.error(
-                        PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                        outError[0]
-                );
-            }
-        } else {
-            XmlUtils.skipCurrentTag(parser);
-        }
-
-        final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
-        certSha256Digests[0] = certSha256Digest;
-        System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
-                1, additionalCertSha256Digests.length);
-
-        parsingPackage.addUsesStaticLibrary(lname)
-                .addUsesStaticLibraryVersion(version)
-                .addUsesStaticLibraryCertDigests(certSha256Digests);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static String[] parseAdditionalCertificates(
-            Resources resources,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws XmlPullParserException, IOException {
-        String[] certSha256Digests = EmptyArray.STRING;
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            final String nodeName = parser.getName();
-            if (nodeName.equals("additional-certificate")) {
-                final TypedArray sa = resources.obtainAttributes(parser, com.android.internal.
-                        R.styleable.AndroidManifestAdditionalCertificate);
-                String certSha256Digest = sa.getNonResourceString(com.android.internal.
-                        R.styleable.AndroidManifestAdditionalCertificate_certDigest);
-                sa.recycle();
-
-                if (TextUtils.isEmpty(certSha256Digest)) {
-                    outError[0] = "Bad additional-certificate declaration with empty"
-                            + " certDigest:" + certSha256Digest;
-                    XmlUtils.skipCurrentTag(parser);
-                    sa.recycle();
-                    return null;
-                }
-
-                // We allow ":" delimiters in the SHA declaration as this is the format
-                // emitted by the certtool making it easy for developers to copy/paste.
-                certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
-                certSha256Digests = ArrayUtils.appendElement(String.class,
-                        certSha256Digests, certSha256Digest);
-            } else {
-                XmlUtils.skipCurrentTag(parser);
-            }
-        }
-
-        return certSha256Digests;
-    }
-
-    /**
-     * Generate activity object that forwards user to App Details page automatically.
-     * This activity should be invisible to user and user should not know or see it.
-     *
-     * @hide
-     */
-    @NonNull
-    private static ComponentParseUtils.ParsedActivity generateAppDetailsHiddenActivity(
-            ParsingPackage parsingPackage,
-            String[] outError
-    ) {
-        String packageName = parsingPackage.getPackageName();
-        String processName = parsingPackage.getProcessName();
-        boolean hardwareAccelerated = parsingPackage.isBaseHardwareAccelerated();
-        int uiOptions = parsingPackage.getUiOptions();
-
-        // Build custom App Details activity info instead of parsing it from xml
-        ComponentParseUtils.ParsedActivity activity = new ComponentParseUtils.ParsedActivity();
-        activity.setPackageName(packageName);
-
-        activity.theme = android.R.style.Theme_NoDisplay;
-        activity.exported = true;
-        activity.className = PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME;
-        activity.setProcessName(processName, processName);
-        activity.uiOptions = uiOptions;
-        activity.taskAffinity = PackageParser.buildTaskAffinityName(packageName,
-                packageName,
-                ":app_details", outError);
-        activity.enabled = true;
-        activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
-        activity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
-        activity.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
-        activity.configChanges = PackageParser.getActivityConfigChanges(0, 0);
-        activity.softInputMode = 0;
-        activity.persistableMode = ActivityInfo.PERSIST_NEVER;
-        activity.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
-        activity.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
-        activity.lockTaskLaunchMode = 0;
-        activity.directBootAware = false;
-        activity.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
-        activity.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
-        activity.preferMinimalPostProcessing = ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT;
-        if (hardwareAccelerated) {
-            activity.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
-        }
-
-        return activity;
-    }
-
-    /**
-     * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
-     */
-    private static boolean hasDomainURLs(
-            ParsingPackage parsingPackage) {
-        final List<ComponentParseUtils.ParsedActivity> activities = parsingPackage.getActivities();
-        final int countActivities = activities.size();
-        for (int n = 0; n < countActivities; n++) {
-            ComponentParseUtils.ParsedActivity activity = activities.get(n);
-            List<ComponentParseUtils.ParsedActivityIntentInfo> filters = activity.intents;
-            if (filters == null) continue;
-            final int countFilters = filters.size();
-            for (int m = 0; m < countFilters; m++) {
-                ComponentParseUtils.ParsedActivityIntentInfo aii = filters.get(m);
-                if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
-                if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
-                if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
-                        aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Sets the max aspect ratio of every child activity that doesn't already have an aspect
-     * ratio set.
-     */
-    private static void setMaxAspectRatio(
-            ParsingPackage parsingPackage) {
-        // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
-        // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
-        float maxAspectRatio = parsingPackage.getTargetSdkVersion() < O
-                ? PackageParser.DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
-
-        float packageMaxAspectRatio = parsingPackage.getMaxAspectRatio();
-        if (packageMaxAspectRatio != 0) {
-            // Use the application max aspect ration as default if set.
-            maxAspectRatio = packageMaxAspectRatio;
-        } else {
-            Bundle appMetaData = parsingPackage.getAppMetaData();
-            if (appMetaData != null && appMetaData.containsKey(
-                    PackageParser.METADATA_MAX_ASPECT_RATIO)) {
-                maxAspectRatio = appMetaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
-                        maxAspectRatio);
-            }
-        }
-
-        if (parsingPackage.getActivities() != null) {
-            for (ComponentParseUtils.ParsedActivity activity : parsingPackage.getActivities()) {
-                // If the max aspect ratio for the activity has already been set, skip.
-                if (activity.hasMaxAspectRatio()) {
-                    continue;
-                }
-
-                // By default we prefer to use a values defined on the activity directly than values
-                // defined on the application. We do not check the styled attributes on the activity
-                // as it would have already been set when we processed the activity. We wait to
-                // process the meta data here since this method is called at the end of processing
-                // the application and all meta data is guaranteed.
-                final float activityAspectRatio = activity.metaData != null
-                        ? activity.metaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
-                        maxAspectRatio)
-                        : maxAspectRatio;
-
-                activity.setMaxAspectRatio(activity.resizeMode, activityAspectRatio);
-            }
-        }
-    }
-
-    /**
-     * Sets the min aspect ratio of every child activity that doesn't already have an aspect
-     * ratio set.
-     */
-    private static void setMinAspectRatio(
-            ParsingPackage parsingPackage,
-            PackageParser.Callback callback
-    ) {
-        final float minAspectRatio;
-        float packageMinAspectRatio = parsingPackage.getMinAspectRatio();
-        if (packageMinAspectRatio != 0) {
-            // Use the application max aspect ration as default if set.
-            minAspectRatio = packageMinAspectRatio;
-        } else {
-            // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
-            // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
-            // except for watches which always supported 1:1.
-            minAspectRatio = parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.Q
-                    ? 0
-                    : (callback != null && callback.hasFeature(FEATURE_WATCH))
-                            ? PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
-                            : PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
-        }
-
-        if (parsingPackage.getActivities() != null) {
-            for (ComponentParseUtils.ParsedActivity activity : parsingPackage.getActivities()) {
-                if (activity.hasMinAspectRatio()) {
-                    continue;
-                }
-                activity.setMinAspectRatio(activity.resizeMode, minAspectRatio);
-            }
-        }
-    }
-
-    private static ParseResult parseOverlay(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestResourceOverlay);
-        String target = sa.getString(
-                R.styleable.AndroidManifestResourceOverlay_targetPackage);
-        String targetName = sa.getString(
-                R.styleable.AndroidManifestResourceOverlay_targetName);
-        String category = sa.getString(
-                R.styleable.AndroidManifestResourceOverlay_category);
-        int priority = sa.getInt(R.styleable.AndroidManifestResourceOverlay_priority,
-                0);
-        boolean isStatic = sa.getBoolean(
-                R.styleable.AndroidManifestResourceOverlay_isStatic, false);
-
-        if (target == null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "<overlay> does not specify a target package"
-            );
-        }
-
-        if (priority < 0 || priority > 9999) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "<overlay> priority must be between 0 and 9999"
-            );
-        }
-
-        // check to see if overlay should be excluded based on system property condition
-        String propName = sa.getString(
-                R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName);
-        String propValue = sa.getString(
-                R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
-        if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
-            Slog.i(TAG, "Skipping target and overlay pair " + target + " and "
-                    + parsingPackage.getBaseCodePath()
-                    + ": overlay ignored due to required system property: "
-                    + propName + " with value: " + propValue);
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    "Skipping target and overlay pair " + target + " and "
-                            + parsingPackage.getBaseCodePath()
-                            + ": overlay ignored due to required system property: "
-                            + propName + " with value: " + propValue
-            );
-        }
-
-        parsingPackage
-                .setIsOverlay(true)
-                .setOverlayTarget(target)
-                .setOverlayTargetName(targetName)
-                .setOverlayCategory(category)
-                .setOverlayPriority(priority)
-                .setOverlayIsStatic(isStatic);
-
-        sa.recycle();
-
-        XmlUtils.skipCurrentTag(parser);
-        return parseInput.success(parsingPackage);
-    }
-
-    private static boolean parseProtectedBroadcast(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestProtectedBroadcast);
-
-        // Note: don't allow this value to be a reference to a resource
-        // that may change.
-        String name = sa.getNonResourceString(R.styleable.AndroidManifestProtectedBroadcast_name);
-
-        sa.recycle();
-
-        if (name != null) {
-            parsingPackage.addProtectedBroadcast(name);
-        }
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static boolean parseSupportScreens(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestSupportsScreens);
-
-        int requiresSmallestWidthDp = sa.getInteger(
-                R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp,
-                0);
-        int compatibleWidthLimitDp = sa.getInteger(
-                R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp,
-                0);
-        int largestWidthLimitDp = sa.getInteger(
-                R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp,
-                0);
-
-        // This is a trick to get a boolean and still able to detect
-        // if a value was actually set.
-        parsingPackage
-                .setSupportsSmallScreens(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_smallScreens, 1))
-                .setSupportsNormalScreens(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_normalScreens, 1))
-                .setSupportsLargeScreens(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_largeScreens, 1))
-                .setSupportsXLargeScreens(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_xlargeScreens, 1))
-                .setResizeable(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_resizeable, 1))
-                .setAnyDensity(
-                        sa.getInteger(R.styleable.AndroidManifestSupportsScreens_anyDensity, 1))
-                .setRequiresSmallestWidthDp(requiresSmallestWidthDp)
-                .setCompatibleWidthLimitDp(compatibleWidthLimitDp)
-                .setLargestWidthLimitDp(largestWidthLimitDp);
-
-        sa.recycle();
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static ParseResult parseInstrumentation(
-            ParseInput parseInput,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws XmlPullParserException, IOException {
-        // TODO(b/135203078): Remove, replace with ParseResult
-        String[] outError = new String[1];
-
-        ComponentParseUtils.ParsedInstrumentation parsedInstrumentation =
-                ComponentParseUtils.parseInstrumentation(parsingPackage,
-                        res, parser, outError);
-
-        if (parsedInstrumentation == null || outError[0] != null) {
-            return parseInput.error(
-                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
-                    outError[0]
-            );
-        }
-
-        parsingPackage.addInstrumentation(parsedInstrumentation);
-
-        return parseInput.success(parsingPackage);
-    }
-
-    private static boolean parseOriginalPackage(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestOriginalPackage);
-
-        String orig = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestOriginalPackage_name,
-                0);
-        if (!parsingPackage.getPackageName().equals(orig)) {
-            if (parsingPackage.getOriginalPackages() == null) {
-                parsingPackage.setRealPackage(parsingPackage.getPackageName());
-            }
-            parsingPackage.addOriginalPackage(orig);
-        }
-
-        sa.recycle();
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static boolean parseAdoptPermissions(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestOriginalPackage);
-
-        String name = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestOriginalPackage_name,
-                0);
-
-        sa.recycle();
-
-        if (name != null) {
-            parsingPackage.addAdoptPermission(name);
-        }
-
-        XmlUtils.skipCurrentTag(parser);
-        return true;
-    }
-
-    private static void convertNewPermissions(
-            ParsingPackage packageToParse) {
-        final int NP = PackageParser.NEW_PERMISSIONS.length;
-        StringBuilder newPermsMsg = null;
-        for (int ip = 0; ip < NP; ip++) {
-            final PackageParser.NewPermissionInfo npi
-                    = PackageParser.NEW_PERMISSIONS[ip];
-            if (packageToParse.getTargetSdkVersion() >= npi.sdkVersion) {
-                break;
-            }
-            if (!packageToParse.getRequestedPermissions().contains(npi.name)) {
-                if (newPermsMsg == null) {
-                    newPermsMsg = new StringBuilder(128);
-                    newPermsMsg.append(packageToParse.getPackageName());
-                    newPermsMsg.append(": compat added ");
-                } else {
-                    newPermsMsg.append(' ');
-                }
-                newPermsMsg.append(npi.name);
-                packageToParse.addRequestedPermission(npi.name);
-                packageToParse.addImplicitPermission(npi.name);
-            }
-        }
-        if (newPermsMsg != null) {
-            Slog.i(TAG, newPermsMsg.toString());
-        }
-    }
-
-    private static void convertSplitPermissions(ParsingPackage packageToParse) {
-        List<SplitPermissionInfoParcelable> splitPermissions;
-
-        try {
-            splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
-
-        final int listSize = splitPermissions.size();
-        for (int is = 0; is < listSize; is++) {
-            final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
-            List<String> requestedPermissions = packageToParse.getRequestedPermissions();
-            if (packageToParse.getTargetSdkVersion() >= spi.getTargetSdk()
-                    || !requestedPermissions.contains(spi.getSplitPermission())) {
-                continue;
-            }
-            final List<String> newPerms = spi.getNewPermissions();
-            for (int in = 0; in < newPerms.size(); in++) {
-                final String perm = newPerms.get(in);
-                if (!requestedPermissions.contains(perm)) {
-                    packageToParse.addRequestedPermission(perm);
-                    packageToParse.addImplicitPermission(perm);
-                }
-            }
-        }
-    }
-
-    private static boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
-        if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
-            if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
-                // malformed condition - incomplete
-                Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
-                        + "=" + propValue + "' - require both requiredSystemPropertyName"
-                        + " AND requiredSystemPropertyValue to be specified.");
-                return false;
-            }
-            // no valid condition set - so no exclusion criteria, overlay will be included.
-            return true;
-        }
-
-        // check property value - make sure it is both set and equal to expected value
-        final String currValue = SystemProperties.get(propName);
-        return (currValue != null && currValue.equals(propValue));
-    }
-
-    /**
-     * This is a pre-density application which will get scaled - instead of being pixel perfect.
-     * This type of application is not resizable.
-     *
-     * @param parsingPackage The package which needs to be marked as unresizable.
-     */
-    private static void adjustPackageToBeUnresizeableAndUnpipable(
-            ParsingPackage parsingPackage) {
-        if (parsingPackage.getActivities() != null) {
-            for (ComponentParseUtils.ParsedActivity a : parsingPackage.getActivities()) {
-                a.resizeMode = RESIZE_MODE_UNRESIZEABLE;
-                a.flags &= ~FLAG_SUPPORTS_PICTURE_IN_PICTURE;
-            }
-        }
-    }
-
-    private static String validateName(String name, boolean requireSeparator,
-            boolean requireFilename) {
-        final int N = name.length();
-        boolean hasSep = false;
-        boolean front = true;
-        for (int i = 0; i < N; i++) {
-            final char c = name.charAt(i);
-            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
-                front = false;
-                continue;
-            }
-            if (!front) {
-                if ((c >= '0' && c <= '9') || c == '_') {
-                    continue;
-                }
-            }
-            if (c == '.') {
-                hasSep = true;
-                front = true;
-                continue;
-            }
-            return "bad character '" + c + "'";
-        }
-        if (requireFilename && !FileUtils.isValidExtFilename(name)) {
-            return "Invalid filename";
-        }
-        return hasSep || !requireSeparator
-                ? null : "must have at least one '.' separator";
-    }
-
-    public static Bundle parseMetaData(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser, Bundle data, String[] outError)
-            throws XmlPullParserException, IOException {
-
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestMetaData);
-
-        if (data == null) {
-            data = new Bundle();
-        }
-
-        String name = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestMetaData_name, 0);
-        if (name == null) {
-            outError[0] = "<meta-data> requires an android:name attribute";
-            sa.recycle();
-            return null;
-        }
-
-        name = name.intern();
-
-        TypedValue v = sa.peekValue(
-                R.styleable.AndroidManifestMetaData_resource);
-        if (v != null && v.resourceId != 0) {
-            //Slog.i(TAG, "Meta data ref " + name + ": " + v);
-            data.putInt(name, v.resourceId);
-        } else {
-            v = sa.peekValue(
-                    R.styleable.AndroidManifestMetaData_value);
-            //Slog.i(TAG, "Meta data " + name + ": " + v);
-            if (v != null) {
-                if (v.type == TypedValue.TYPE_STRING) {
-                    CharSequence cs = v.coerceToString();
-                    data.putString(name, cs != null ? cs.toString() : null);
-                } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
-                    data.putBoolean(name, v.data != 0);
-                } else if (v.type >= TypedValue.TYPE_FIRST_INT
-                        && v.type <= TypedValue.TYPE_LAST_INT) {
-                    data.putInt(name, v.data);
-                } else if (v.type == TypedValue.TYPE_FLOAT) {
-                    data.putFloat(name, v.getFloat());
-                } else {
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG,
-                                "<meta-data> only supports string, integer, float, color, "
-                                        + "boolean, and resource reference types: "
-                                        + parser.getName() + " at "
-                                        + parsingPackage.getBaseCodePath() + " "
-                                        + parser.getPositionDescription());
-                    } else {
-                        outError[0] =
-                                "<meta-data> only supports string, integer, float, color, "
-                                        + "boolean, and resource reference types";
-                        data = null;
-                    }
-                }
-            } else {
-                outError[0] = "<meta-data> requires an android:value or android:resource attribute";
-                data = null;
-            }
-        }
-
-        sa.recycle();
-
-        XmlUtils.skipCurrentTag(parser);
-
-        return data;
-    }
-
-    /**
-     * Collect certificates from all the APKs described in the given package,
-     * populating {@link AndroidPackageWrite#setSigningDetails(SigningDetails)}. Also asserts that
-     * all APK contents are signed correctly and consistently.
-     */
-    public static void collectCertificates(AndroidPackage pkg, boolean skipVerify)
-            throws PackageParserException {
-        pkg.mutate().setSigningDetails(SigningDetails.UNKNOWN);
-
-        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
-        try {
-            pkg.mutate().setSigningDetails(collectCertificates(
-                    pkg.getBaseCodePath(),
-                    skipVerify,
-                    pkg.isStaticSharedLibrary(),
-                    pkg.getSigningDetails(),
-                    pkg.getTargetSdkVersion()
-            ));
-
-            String[] splitCodePaths = pkg.getSplitCodePaths();
-            if (!ArrayUtils.isEmpty(splitCodePaths)) {
-                for (int i = 0; i < splitCodePaths.length; i++) {
-                    pkg.mutate().setSigningDetails(collectCertificates(
-                            splitCodePaths[i],
-                            skipVerify,
-                            pkg.isStaticSharedLibrary(),
-                            pkg.getSigningDetails(),
-                            pkg.getTargetSdkVersion()
-                    ));
-                }
-            }
-        } finally {
-            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
-        }
-    }
-
-    public static SigningDetails collectCertificates(
-            String baseCodePath,
-            boolean skipVerify,
-            boolean isStaticSharedLibrary,
-            @NonNull SigningDetails existingSigningDetails,
-            int targetSdk
-    ) throws PackageParserException {
-        int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
-                targetSdk);
-        if (isStaticSharedLibrary) {
-            // must use v2 signing scheme
-            minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
-        }
-        SigningDetails verified;
-        if (skipVerify) {
-            // systemDir APKs are already trusted, save time by not verifying
-            verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
-                    baseCodePath, minSignatureScheme);
-        } else {
-            verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme);
-        }
-
-        // Verify that entries are signed consistently with the first pkg
-        // we encountered. Note that for splits, certificates may have
-        // already been populated during an earlier parse of a base APK.
-        if (existingSigningDetails == SigningDetails.UNKNOWN) {
-            return verified;
-        } else {
-            if (!Signature.areExactMatch(existingSigningDetails.signatures, verified.signatures)) {
-                throw new PackageParserException(
-                        INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
-                        baseCodePath + " has mismatched certificates");
-            }
-
-            return existingSigningDetails;
-        }
-    }
-
-    @Nullable
-    public static String buildClassName(String pkg, CharSequence clsSeq) {
-        if (clsSeq == null || clsSeq.length() <= 0) {
-            return null;
-        }
-        String cls = clsSeq.toString();
-        char c = cls.charAt(0);
-        if (c == '.') {
-            return pkg + cls;
-        }
-        if (cls.indexOf('.') < 0) {
-            StringBuilder b = new StringBuilder(pkg);
-            b.append('.');
-            b.append(cls);
-            return b.toString();
-        }
-        return cls;
-    }
-
-    public interface ParseInput {
-        ParseResult success(ParsingPackage result);
-
-        ParseResult error(int parseError);
-
-        ParseResult error(int parseError, String errorMessage);
-    }
-
-    public static class ParseResult implements ParseInput {
-
-        private static final boolean DEBUG_FILL_STACK_TRACE = false;
-
-        private ParsingPackage result;
-
-        private int parseError;
-        private String errorMessage;
-
-        public ParseInput reset() {
-            this.result = null;
-            this.parseError = PackageManager.INSTALL_SUCCEEDED;
-            this.errorMessage = null;
-            return this;
-        }
-
-        @Override
-        public ParseResult success(ParsingPackage result) {
-            if (parseError != PackageManager.INSTALL_SUCCEEDED || errorMessage != null) {
-                throw new IllegalStateException("Cannot set to success after set to error");
-            }
-            this.result = result;
-            return this;
-        }
-
-        @Override
-        public ParseResult error(int parseError) {
-            return error(parseError, null);
-        }
-
-        @Override
-        public ParseResult error(int parseError, String errorMessage) {
-            this.parseError = parseError;
-            this.errorMessage = errorMessage;
-
-            if (DEBUG_FILL_STACK_TRACE) {
-                this.errorMessage += Arrays.toString(new Exception().getStackTrace());
-            }
-
-            return this;
-        }
-
-        public ParsingPackage getResultAndNull() {
-            ParsingPackage result = this.result;
-            this.result = null;
-            return result;
-        }
-
-        public boolean isSuccess() {
-            return parseError == PackageManager.INSTALL_SUCCEEDED;
-        }
-
-        public int getParseError() {
-            return parseError;
-        }
-
-        public String getErrorMessage() {
-            return errorMessage;
-        }
-    }
-}
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
deleted file mode 100644
index a0f5812..0000000
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ /dev/null
@@ -1,3787 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm.parsing;
-
-import static android.content.pm.ActivityInfo.FLAG_ALWAYS_FOCUSABLE;
-import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
-import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
-
-import android.annotation.CallSuper;
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.annotation.StringRes;
-import android.app.ActivityTaskManager;
-import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PathPermission;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.content.res.XmlResourceParser;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.os.PatternMatcher;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.util.Slog;
-import android.util.TypedValue;
-import android.view.Gravity;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.DataClass;
-import com.android.internal.util.XmlUtils;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-
-/**
- * TODO(b/135203078): Move the inner classes out to separate files.
- * TODO(b/135203078): Expose inner classes as immutable through interface methods.
- *
- * @hide
- */
-public class ComponentParseUtils {
-
-    private static final String TAG = ApkParseUtils.TAG;
-
-    // TODO(b/135203078): None of this class's subclasses do anything. Remove in favor of base?
-    public static class ParsedIntentInfo extends IntentFilter {
-
-        /**
-         * <p>
-         * Implementation note: The serialized form for the intent list also contains the name
-         * of the concrete class that's stored in the list, and assumes that every element of the
-         * list is of the same type. This is very similar to the original parcelable mechanism.
-         * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
-         * and is public API. It also declares Parcelable related methods as final which means
-         * we can't extend them. The approach of using composition instead of inheritance leads to
-         * a large set of cascading changes in the PackageManagerService, which seem undesirable.
-         *
-         * <p>
-         * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
-         * to make sure their owner fields are consistent. See {@code fixupOwner}.
-         */
-        public static void writeIntentsList(List<? extends ParsedIntentInfo> list, Parcel out,
-                int flags) {
-            if (list == null) {
-                out.writeInt(-1);
-                return;
-            }
-
-            final int size = list.size();
-            out.writeInt(size);
-
-            // Don't bother writing the component name if the list is empty.
-            if (size > 0) {
-                ParsedIntentInfo info = list.get(0);
-                out.writeString(info.getClass().getName());
-
-                for (int i = 0; i < size; i++) {
-                    list.get(i).writeIntentInfoToParcel(out, flags);
-                }
-            }
-        }
-
-        public static <T extends ParsedIntentInfo> ArrayList<T> createIntentsList(Parcel in) {
-            int size = in.readInt();
-            if (size == -1) {
-                return null;
-            }
-
-            if (size == 0) {
-                return new ArrayList<>(0);
-            }
-
-            String className = in.readString();
-            final ArrayList<T> intentsList;
-            try {
-                final Class<T> cls = (Class<T>) Class.forName(className);
-                final Constructor<T> cons = cls.getConstructor(Parcel.class);
-
-                intentsList = new ArrayList<>(size);
-                for (int i = 0; i < size; ++i) {
-                    intentsList.add(cons.newInstance(in));
-                }
-            } catch (ReflectiveOperationException ree) {
-                throw new AssertionError("Unable to construct intent list for: "
-                        + className, ree);
-            }
-
-            return intentsList;
-        }
-
-        protected String packageName;
-        protected final String className;
-
-        public boolean hasDefault;
-        public int labelRes;
-        public CharSequence nonLocalizedLabel;
-        public int icon;
-
-        protected List<String> rawDataTypes;
-
-        public void addRawDataType(String dataType) throws MalformedMimeTypeException {
-            if (rawDataTypes == null) {
-                rawDataTypes = new ArrayList<>();
-            }
-
-            rawDataTypes.add(dataType);
-            addDataType(dataType);
-        }
-
-        public ParsedIntentInfo(String packageName, String className) {
-            this.packageName = packageName;
-            this.className = className;
-        }
-
-        public ParsedIntentInfo(Parcel in) {
-            super(in);
-            packageName = in.readString();
-            className = in.readString();
-            hasDefault = (in.readInt() == 1);
-            labelRes = in.readInt();
-            nonLocalizedLabel = in.readCharSequence();
-            icon = in.readInt();
-        }
-
-        public void writeIntentInfoToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeString(packageName);
-            dest.writeString(className);
-            dest.writeInt(hasDefault ? 1 : 0);
-            dest.writeInt(labelRes);
-            dest.writeCharSequence(nonLocalizedLabel);
-            dest.writeInt(icon);
-        }
-
-        public String getPackageName() {
-            return packageName;
-        }
-
-        public String getClassName() {
-            return className;
-        }
-    }
-
-    public static class ParsedActivityIntentInfo extends ParsedIntentInfo {
-
-        public ParsedActivityIntentInfo(String packageName, String className) {
-            super(packageName, className);
-        }
-
-        public ParsedActivityIntentInfo(Parcel in) {
-            super(in);
-        }
-
-        public static final Creator<ParsedActivityIntentInfo> CREATOR =
-                new Creator<ParsedActivityIntentInfo>() {
-                    @Override
-                    public ParsedActivityIntentInfo createFromParcel(Parcel source) {
-                        return new ParsedActivityIntentInfo(source);
-                    }
-
-                    @Override
-                    public ParsedActivityIntentInfo[] newArray(int size) {
-                        return new ParsedActivityIntentInfo[size];
-                    }
-                };
-    }
-
-    public static class ParsedServiceIntentInfo extends ParsedIntentInfo {
-
-        public ParsedServiceIntentInfo(String packageName, String className) {
-            super(packageName, className);
-        }
-
-        public ParsedServiceIntentInfo(Parcel in) {
-            super(in);
-        }
-
-        public static final Creator<ParsedServiceIntentInfo> CREATOR =
-                new Creator<ParsedServiceIntentInfo>() {
-                    @Override
-                    public ParsedServiceIntentInfo createFromParcel(Parcel source) {
-                        return new ParsedServiceIntentInfo(source);
-                    }
-
-                    @Override
-                    public ParsedServiceIntentInfo[] newArray(int size) {
-                        return new ParsedServiceIntentInfo[size];
-                    }
-                };
-    }
-
-    public static class ParsedProviderIntentInfo extends ParsedIntentInfo {
-
-        public ParsedProviderIntentInfo(String packageName, String className) {
-            super(packageName, className);
-        }
-
-        public ParsedProviderIntentInfo(Parcel in) {
-            super(in);
-        }
-
-        public static final Creator<ParsedProviderIntentInfo> CREATOR =
-                new Creator<ParsedProviderIntentInfo>() {
-                    @Override
-                    public ParsedProviderIntentInfo createFromParcel(Parcel source) {
-                        return new ParsedProviderIntentInfo(source);
-                    }
-
-                    @Override
-                    public ParsedProviderIntentInfo[] newArray(int size) {
-                        return new ParsedProviderIntentInfo[size];
-                    }
-                };
-    }
-
-    public static class ParsedQueriesIntentInfo extends ParsedIntentInfo {
-
-        public ParsedQueriesIntentInfo(String packageName, String className) {
-            super(packageName, className);
-        }
-
-        public ParsedQueriesIntentInfo(Parcel in) {
-            super(in);
-        }
-
-        public static final Creator<ParsedQueriesIntentInfo> CREATOR =
-                new Creator<ParsedQueriesIntentInfo>() {
-                    @Override
-                    public ParsedQueriesIntentInfo createFromParcel(Parcel source) {
-                        return new ParsedQueriesIntentInfo(source);
-                    }
-
-                    @Override
-                    public ParsedQueriesIntentInfo[] newArray(int size) {
-                        return new ParsedQueriesIntentInfo[size];
-                    }
-                };
-    }
-
-    public static class ParsedComponent<IntentInfoType extends ParsedIntentInfo> implements
-            Parcelable {
-
-        // TODO(b/135203078): Replace with "name", as not all usages are an actual class
-        public String className;
-        public int icon;
-        public int labelRes;
-        public CharSequence nonLocalizedLabel;
-        public int logo;
-        public int banner;
-
-        public int descriptionRes;
-
-        // TODO(b/135203078): Make subclass that contains these fields only for the necessary
-        //  subtypes
-        protected boolean enabled = true;
-        protected boolean directBootAware;
-        public int flags;
-
-        private String packageName;
-        private String splitName;
-
-        // TODO(b/135203078): Make nullable
-        public List<IntentInfoType> intents = new ArrayList<>();
-
-        private transient ComponentName componentName;
-
-        protected Bundle metaData;
-
-        public void setSplitName(String splitName) {
-            this.splitName = splitName;
-        }
-
-        public String getSplitName() {
-            return splitName;
-        }
-
-        @CallSuper
-        public void setPackageName(String packageName) {
-            this.packageName = packageName;
-            this.componentName = null;
-        }
-
-        void setPackageNameInternal(String packageName) {
-            this.packageName = packageName;
-            this.componentName = null;
-        }
-
-        public void setEnabled(boolean enabled) {
-            this.enabled = enabled;
-        }
-
-        public String getPackageName() {
-            return packageName;
-        }
-
-        public final boolean isDirectBootAware() {
-            return directBootAware;
-        }
-
-        public final boolean isEnabled() {
-            return enabled;
-        }
-
-        public final String getName() {
-            return className;
-        }
-
-        public final Bundle getMetaData() {
-            return metaData;
-        }
-
-        @UnsupportedAppUsage
-        public ComponentName getComponentName() {
-            if (componentName != null) {
-                return componentName;
-            }
-            if (className != null) {
-                componentName = new ComponentName(getPackageName(),
-                        className);
-            }
-            return componentName;
-        }
-
-        public void setFrom(ParsedComponent other) {
-            this.metaData = other.metaData;
-            this.className = other.className;
-            this.icon = other.icon;
-            this.labelRes = other.labelRes;
-            this.nonLocalizedLabel = other.nonLocalizedLabel;
-            this.logo = other.logo;
-            this.banner = other.banner;
-
-            this.descriptionRes = other.descriptionRes;
-
-            this.enabled = other.enabled;
-            this.directBootAware = other.directBootAware;
-            this.flags = other.flags;
-
-            this.setPackageName(other.packageName);
-            this.setSplitName(other.getSplitName());
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(this.className);
-            dest.writeInt(this.icon);
-            dest.writeInt(this.labelRes);
-            dest.writeCharSequence(this.nonLocalizedLabel);
-            dest.writeInt(this.logo);
-            dest.writeInt(this.banner);
-            dest.writeInt(this.descriptionRes);
-            dest.writeBoolean(this.enabled);
-            dest.writeBoolean(this.directBootAware);
-            dest.writeInt(this.flags);
-            dest.writeString(this.packageName);
-            dest.writeString(this.splitName);
-            ParsedIntentInfo.writeIntentsList(this.intents, dest, flags);
-            dest.writeBundle(this.metaData);
-        }
-
-        public ParsedComponent() {
-        }
-
-        protected ParsedComponent(Parcel in) {
-            // We use the boot classloader for all classes that we load.
-            final ClassLoader boot = Object.class.getClassLoader();
-            this.className = in.readString();
-            this.icon = in.readInt();
-            this.labelRes = in.readInt();
-            this.nonLocalizedLabel = in.readCharSequence();
-            this.logo = in.readInt();
-            this.banner = in.readInt();
-            this.descriptionRes = in.readInt();
-            this.enabled = in.readByte() != 0;
-            this.directBootAware = in.readByte() != 0;
-            this.flags = in.readInt();
-            this.packageName = in.readString();
-            this.splitName = in.readString();
-            this.intents = ParsedIntentInfo.createIntentsList(in);
-            this.metaData = in.readBundle(boot);
-        }
-    }
-
-    // TODO(b/135203078): Document this. Maybe split out ParsedComponent to be actual components
-    //  that can have their own processes, rather than something like permission which cannot.
-    public static class ParsedMainComponent<IntentInfoType extends ParsedIntentInfo> extends
-            ParsedComponent<IntentInfoType> {
-
-        private String processName;
-        private String permission;
-
-        public void setProcessName(String appProcessName, String processName) {
-            // TODO(b/135203078): Is this even necessary anymore?
-            this.processName = TextUtils.safeIntern(
-                    processName == null ? appProcessName : processName);
-        }
-
-        public String getProcessName() {
-            return processName;
-        }
-
-        public void setPermission(String permission) {
-            // Empty string must be converted to null
-            this.permission = TextUtils.isEmpty(permission) ? null : permission.intern();
-        }
-
-        public String getPermission() {
-            return permission;
-        }
-
-        @Override
-        public void setFrom(ParsedComponent other) {
-            super.setFrom(other);
-            if (other instanceof ParsedMainComponent) {
-                ParsedMainComponent otherMainComponent = (ParsedMainComponent) other;
-                this.setProcessName(otherMainComponent.getProcessName(),
-                        otherMainComponent.getProcessName());
-                this.setPermission(otherMainComponent.getPermission());
-            }
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeString(this.processName);
-            dest.writeString(this.permission);
-        }
-
-        public ParsedMainComponent() {
-        }
-
-        protected ParsedMainComponent(Parcel in) {
-            super(in);
-            this.processName = TextUtils.safeIntern(in.readString());
-            this.permission = TextUtils.safeIntern(in.readString());
-        }
-
-        public static final Creator<ParsedMainComponent> CREATOR =
-                new Creator<ParsedMainComponent>() {
-                    @Override
-                    public ParsedMainComponent createFromParcel(Parcel source) {
-                        return new ParsedMainComponent(source);
-                    }
-
-                    @Override
-                    public ParsedMainComponent[] newArray(int size) {
-                        return new ParsedMainComponent[size];
-                    }
-                };
-    }
-
-    public static class ParsedActivity extends ParsedMainComponent<ParsedActivityIntentInfo>
-            implements Parcelable {
-
-        public boolean exported;
-        public int theme;
-        public int uiOptions;
-
-        public String targetActivity;
-
-        public String parentActivityName;
-        public String taskAffinity;
-        public int privateFlags;
-
-        public int launchMode;
-        public int documentLaunchMode;
-        public int maxRecents;
-        public int configChanges;
-        public int softInputMode;
-        public int persistableMode;
-        public int lockTaskLaunchMode;
-
-        public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
-        public int resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
-
-        public float maxAspectRatio;
-        public boolean hasMaxAspectRatio;
-
-        public float minAspectRatio;
-        public boolean hasMinAspectRatio;
-
-        public String requestedVrComponent;
-        public int rotationAnimation = -1;
-        public int colorMode;
-        public boolean preferMinimalPostProcessing;
-        public int order;
-
-        public ActivityInfo.WindowLayout windowLayout;
-
-        @Override
-        public void setPackageName(String packageName) {
-            super.setPackageName(packageName);
-            for (ParsedIntentInfo intent : this.intents) {
-                intent.packageName = packageName;
-            }
-        }
-
-        public boolean hasMaxAspectRatio() {
-            return hasMaxAspectRatio;
-        }
-
-        public boolean hasMinAspectRatio() {
-            return hasMinAspectRatio;
-        }
-
-        public void setMaxAspectRatio(int resizeMode, float maxAspectRatio) {
-            if (resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE
-                    || resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
-                // Resizeable activities can be put in any aspect ratio.
-                return;
-            }
-
-            if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
-                // Ignore any value lesser than 1.0.
-                return;
-            }
-
-            this.maxAspectRatio = maxAspectRatio;
-            hasMaxAspectRatio = true;
-        }
-
-        public void setMinAspectRatio(int resizeMode, float minAspectRatio) {
-            if (resizeMode == RESIZE_MODE_RESIZEABLE
-                    || resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
-                // Resizeable activities can be put in any aspect ratio.
-                return;
-            }
-
-            if (minAspectRatio < 1.0f && minAspectRatio != 0) {
-                // Ignore any value lesser than 1.0.
-                return;
-            }
-
-            this.minAspectRatio = minAspectRatio;
-            hasMinAspectRatio = true;
-        }
-
-        public void addIntent(ParsedActivityIntentInfo intent) {
-            this.intents.add(intent);
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeBoolean(this.exported);
-            dest.writeInt(this.theme);
-            dest.writeInt(this.uiOptions);
-            dest.writeString(this.targetActivity);
-            dest.writeString(this.parentActivityName);
-            dest.writeString(this.taskAffinity);
-            dest.writeInt(this.privateFlags);
-            dest.writeInt(this.launchMode);
-            dest.writeInt(this.documentLaunchMode);
-            dest.writeInt(this.maxRecents);
-            dest.writeInt(this.configChanges);
-            dest.writeInt(this.softInputMode);
-            dest.writeInt(this.persistableMode);
-            dest.writeInt(this.lockTaskLaunchMode);
-            dest.writeInt(this.screenOrientation);
-            dest.writeInt(this.resizeMode);
-            dest.writeFloat(this.maxAspectRatio);
-            dest.writeBoolean(this.hasMaxAspectRatio);
-            dest.writeFloat(this.minAspectRatio);
-            dest.writeBoolean(this.hasMinAspectRatio);
-            dest.writeString(this.requestedVrComponent);
-            dest.writeInt(this.rotationAnimation);
-            dest.writeInt(this.colorMode);
-            dest.writeBoolean(this.preferMinimalPostProcessing);
-            dest.writeInt(this.order);
-            dest.writeBundle(this.metaData);
-
-            if (windowLayout != null) {
-                dest.writeInt(1);
-                dest.writeInt(windowLayout.width);
-                dest.writeFloat(windowLayout.widthFraction);
-                dest.writeInt(windowLayout.height);
-                dest.writeFloat(windowLayout.heightFraction);
-                dest.writeInt(windowLayout.gravity);
-                dest.writeInt(windowLayout.minWidth);
-                dest.writeInt(windowLayout.minHeight);
-            } else {
-                dest.writeInt(0);
-            }
-        }
-
-        public ParsedActivity() {
-        }
-
-        protected ParsedActivity(Parcel in) {
-            super(in);
-            this.exported = in.readByte() != 0;
-            this.theme = in.readInt();
-            this.uiOptions = in.readInt();
-            this.targetActivity = in.readString();
-            this.parentActivityName = in.readString();
-            this.taskAffinity = in.readString();
-            this.privateFlags = in.readInt();
-            this.launchMode = in.readInt();
-            this.documentLaunchMode = in.readInt();
-            this.maxRecents = in.readInt();
-            this.configChanges = in.readInt();
-            this.softInputMode = in.readInt();
-            this.persistableMode = in.readInt();
-            this.lockTaskLaunchMode = in.readInt();
-            this.screenOrientation = in.readInt();
-            this.resizeMode = in.readInt();
-            this.maxAspectRatio = in.readFloat();
-            this.hasMaxAspectRatio = in.readByte() != 0;
-            this.minAspectRatio = in.readFloat();
-            this.hasMinAspectRatio = in.readByte() != 0;
-            this.requestedVrComponent = in.readString();
-            this.rotationAnimation = in.readInt();
-            this.colorMode = in.readInt();
-            this.preferMinimalPostProcessing = in.readByte() != 0;
-            this.order = in.readInt();
-            this.metaData = in.readBundle();
-            if (in.readInt() == 1) {
-                windowLayout = new ActivityInfo.WindowLayout(in);
-            }
-        }
-
-        public static final Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
-            @Override
-            public ParsedActivity createFromParcel(Parcel source) {
-                return new ParsedActivity(source);
-            }
-
-            @Override
-            public ParsedActivity[] newArray(int size) {
-                return new ParsedActivity[size];
-            }
-        };
-    }
-
-    public static class ParsedService extends ParsedMainComponent<ParsedServiceIntentInfo> {
-
-        public boolean exported;
-        public int flags;
-        public int foregroundServiceType;
-        public int order;
-
-        @Override
-        public void setPackageName(String packageName) {
-            super.setPackageName(packageName);
-            for (ParsedIntentInfo intent : this.intents) {
-                intent.packageName = packageName;
-            }
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeBoolean(this.exported);
-            dest.writeBundle(this.metaData);
-            dest.writeInt(this.flags);
-            dest.writeInt(this.foregroundServiceType);
-            dest.writeInt(this.order);
-        }
-
-        public ParsedService() {
-        }
-
-        protected ParsedService(Parcel in) {
-            super(in);
-            this.exported = in.readByte() != 0;
-            this.metaData = in.readBundle();
-            this.flags = in.readInt();
-            this.foregroundServiceType = in.readInt();
-            this.order = in.readInt();
-        }
-
-        public static final Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
-            @Override
-            public ParsedService createFromParcel(Parcel source) {
-                return new ParsedService(source);
-            }
-
-            @Override
-            public ParsedService[] newArray(int size) {
-                return new ParsedService[size];
-            }
-        };
-    }
-
-    public static class ParsedProvider extends ParsedMainComponent<ParsedProviderIntentInfo> {
-
-        protected boolean exported;
-        protected int flags;
-        protected int order;
-        private String authority;
-        protected boolean isSyncable;
-        private String readPermission;
-        private String writePermission;
-        protected boolean grantUriPermissions;
-        protected boolean forceUriPermissions;
-        protected boolean multiProcess;
-        protected int initOrder;
-        protected PatternMatcher[] uriPermissionPatterns;
-        protected PathPermission[] pathPermissions;
-
-        public ParsedProvider(ParsedProvider other) {
-            this.setFrom(other);
-        }
-
-        protected void setFrom(ParsedProvider other) {
-            super.setFrom(other);
-            this.exported = other.exported;
-
-            this.intents.clear();
-            if (other.intents != null) {
-                this.intents.addAll(other.intents);
-            }
-
-            this.flags = other.flags;
-            this.order = other.order;
-            this.setAuthority(other.getAuthority());
-            this.isSyncable = other.isSyncable;
-            this.setReadPermission(other.getReadPermission());
-            this.setWritePermission(other.getWritePermission());
-            this.grantUriPermissions = other.grantUriPermissions;
-            this.forceUriPermissions = other.forceUriPermissions;
-            this.multiProcess = other.multiProcess;
-            this.initOrder = other.initOrder;
-            this.uriPermissionPatterns = other.uriPermissionPatterns;
-            this.pathPermissions = other.pathPermissions;
-        }
-
-        @Override
-        public void setPackageName(String packageName) {
-            super.setPackageName(packageName);
-            for (ParsedIntentInfo intent : this.intents) {
-                intent.packageName = packageName;
-            }
-        }
-
-        public boolean isExported() {
-            return exported;
-        }
-
-        @VisibleForTesting
-        public void setExported(boolean exported) {
-            this.exported = exported;
-        }
-
-        public List<ParsedProviderIntentInfo> getIntents() {
-            return intents;
-        }
-
-        public int getFlags() {
-            return flags;
-        }
-
-        public int getOrder() {
-            return order;
-        }
-
-        public void setAuthority(String authority) {
-            this.authority = TextUtils.safeIntern(authority);
-        }
-
-        public String getAuthority() {
-            return authority;
-        }
-
-        public void setSyncable(boolean isSyncable) {
-            this.isSyncable = isSyncable;
-        }
-
-        public boolean isSyncable() {
-            return isSyncable;
-        }
-
-        public void setReadPermission(String readPermission) {
-            // Empty string must be converted to null
-            this.readPermission = TextUtils.isEmpty(readPermission)
-                    ? null : readPermission.intern();
-        }
-
-        public String getReadPermission() {
-            return readPermission;
-        }
-
-        public void setWritePermission(String writePermission) {
-            // Empty string must be converted to null
-            this.writePermission = TextUtils.isEmpty(writePermission)
-                    ? null : writePermission.intern();
-        }
-
-        public String getWritePermission() {
-            return writePermission;
-        }
-
-        public boolean isGrantUriPermissions() {
-            return grantUriPermissions;
-        }
-
-        public boolean isForceUriPermissions() {
-            return forceUriPermissions;
-        }
-
-        public boolean isMultiProcess() {
-            return multiProcess;
-        }
-
-        public int getInitOrder() {
-            return initOrder;
-        }
-
-        public PatternMatcher[] getUriPermissionPatterns() {
-            return uriPermissionPatterns;
-        }
-
-        public PathPermission[] getPathPermissions() {
-            return pathPermissions;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeBoolean(this.exported);
-            dest.writeInt(this.flags);
-            dest.writeInt(this.order);
-            dest.writeString(this.authority);
-            dest.writeBoolean(this.isSyncable);
-            dest.writeString(this.readPermission);
-            dest.writeString(this.writePermission);
-            dest.writeBoolean(this.grantUriPermissions);
-            dest.writeBoolean(this.forceUriPermissions);
-            dest.writeBoolean(this.multiProcess);
-            dest.writeInt(this.initOrder);
-            dest.writeTypedArray(this.uriPermissionPatterns, flags);
-            dest.writeTypedArray(this.pathPermissions, flags);
-        }
-
-        public ParsedProvider() {
-        }
-
-        protected ParsedProvider(Parcel in) {
-            super(in);
-            this.exported = in.readByte() != 0;
-            this.flags = in.readInt();
-            this.order = in.readInt();
-            this.authority = TextUtils.safeIntern(in.readString());
-            this.isSyncable = in.readByte() != 0;
-            this.readPermission = TextUtils.safeIntern(in.readString());
-            this.writePermission = TextUtils.safeIntern(in.readString());
-            this.grantUriPermissions = in.readByte() != 0;
-            this.forceUriPermissions = in.readByte() != 0;
-            this.multiProcess = in.readByte() != 0;
-            this.initOrder = in.readInt();
-            this.uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR);
-            this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
-        }
-
-        public static final Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
-            @Override
-            public ParsedProvider createFromParcel(Parcel source) {
-                return new ParsedProvider(source);
-            }
-
-            @Override
-            public ParsedProvider[] newArray(int size) {
-                return new ParsedProvider[size];
-            }
-        };
-    }
-
-    /**
-     * A {@link android.R.styleable#AndroidManifestFeature &lt;feature&gt;} tag parsed from the
-     * manifest.
-     */
-    // @DataClass verifier is broken, hence comment out for now
-    public static class ParsedFeature implements Parcelable {
-        /** Maximum length of featureId */
-        public static final int MAX_FEATURE_ID_LEN = 50;
-
-        /** Maximum amount of features per package */
-        private static final int MAX_NUM_FEATURES = 1000;
-
-        /** Id of the feature */
-        public final @NonNull String id;
-
-        /** User visible label fo the feature */
-        public final @StringRes int label;
-
-        /** Ids of previously declared features this feature inherits from */
-        public final @NonNull List<String> inheritFrom;
-
-        /**
-         * @return Is this set of features a valid combination for a single package?
-         */
-        public static boolean isCombinationValid(@Nullable List<ParsedFeature> features) {
-            if (features == null) {
-                return true;
-            }
-
-            ArraySet<String> featureIds = new ArraySet<>(features.size());
-            ArraySet<String> inheritFromFeatureIds = new ArraySet<>();
-
-            int numFeatures = features.size();
-            if (numFeatures > MAX_NUM_FEATURES) {
-                return false;
-            }
-
-            for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
-                boolean wasAdded = featureIds.add(features.get(featureNum).id);
-                if (!wasAdded) {
-                    // feature id is not unique
-                    return false;
-                }
-            }
-
-            for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
-                ParsedFeature feature = features.get(featureNum);
-
-                int numInheritFrom = feature.inheritFrom.size();
-                for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
-                    String inheritFrom = feature.inheritFrom.get(inheritFromNum);
-
-                    if (featureIds.contains(inheritFrom)) {
-                        // Cannot inherit from a feature that is still defined
-                        return false;
-                    }
-
-                    boolean wasAdded = inheritFromFeatureIds.add(inheritFrom);
-                    if (!wasAdded) {
-                        // inheritFrom is not unique
-                        return false;
-                    }
-                }
-            }
-
-            return true;
-        }
-
-
-
-        // Code below generated by codegen v1.0.14.
-        //
-        // DO NOT MODIFY!
-        // CHECKSTYLE:OFF Generated code
-        //
-        // To regenerate run:
-        // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java
-        //
-        // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
-        //   Settings > Editor > Code Style > Formatter Control
-        //@formatter:off
-
-
-        /**
-         * Creates a new ParsedFeature.
-         *
-         * @param id
-         *   Id of the feature
-         * @param label
-         *   User visible label fo the feature (if defined as resource)
-         * @param inheritFrom
-         *   Ids of previously declared features this feature inherits from
-         */
-        @DataClass.Generated.Member
-        public ParsedFeature(
-                @NonNull String id,
-                @StringRes int label,
-                @NonNull List<String> inheritFrom) {
-            this.id = id;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, id);
-            this.label = label;
-            com.android.internal.util.AnnotationValidations.validate(
-                    StringRes.class, null, label);
-            this.inheritFrom = inheritFrom;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, inheritFrom);
-
-            // onConstructed(); // You can define this method to get a callback
-        }
-
-        @Override
-        @DataClass.Generated.Member
-        public void writeToParcel(@NonNull Parcel dest, int flags) {
-            // You can override field parcelling by defining methods like:
-            // void parcelFieldName(Parcel dest, int flags) { ... }
-
-            dest.writeString(id);
-            dest.writeInt(label);
-            dest.writeStringList(inheritFrom);
-        }
-
-        @Override
-        @DataClass.Generated.Member
-        public int describeContents() { return 0; }
-
-        /** @hide */
-        @SuppressWarnings({"unchecked", "RedundantCast"})
-        @DataClass.Generated.Member
-        protected ParsedFeature(@NonNull Parcel in) {
-            // You can override field unparcelling by defining methods like:
-            // static FieldType unparcelFieldName(Parcel in) { ... }
-
-            String _id = in.readString();
-            int _label = in.readInt();
-            List<String> _inheritFrom = new ArrayList<>();
-            in.readStringList(_inheritFrom);
-
-            this.id = _id;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, id);
-            this.label = _label;
-            com.android.internal.util.AnnotationValidations.validate(
-                    StringRes.class, null, label);
-            this.inheritFrom = _inheritFrom;
-            com.android.internal.util.AnnotationValidations.validate(
-                    NonNull.class, null, inheritFrom);
-
-            // onConstructed(); // You can define this method to get a callback
-        }
-
-        @DataClass.Generated.Member
-        public static final @NonNull Parcelable.Creator<ParsedFeature> CREATOR
-                = new Parcelable.Creator<ParsedFeature>() {
-            @Override
-            public ParsedFeature[] newArray(int size) {
-                return new ParsedFeature[size];
-            }
-
-            @Override
-            public ParsedFeature createFromParcel(@NonNull Parcel in) {
-                return new ParsedFeature(in);
-            }
-        };
-
-        /*@DataClass.Generated(
-                time = 1576783172965L,
-                codegenVersion = "1.0.14",
-                sourceFile = "frameworks/base/core/java/android/content/pm/parsing/ComponentParseUtils.java",
-                inputSignatures = "public final @android.annotation.NonNull java.lang.String id\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static  boolean isCombinationValid(java.util.List<android.content.pm.parsing.ParsedFeature>)\nclass ParsedFeature extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass")
-         */
-        @Deprecated
-        private void __metadata() {}
-
-
-        //@formatter:on
-        // End of generated code
-
-    }
-
-    public static class ParsedPermission extends ParsedComponent<ParsedIntentInfo> {
-
-        public String backgroundPermission;
-        private String group;
-        public int requestRes;
-        public int protectionLevel;
-        public boolean tree;
-
-        public ParsedPermissionGroup parsedPermissionGroup;
-
-        public void setName(String className) {
-            this.className = className;
-        }
-
-        public void setGroup(String group) {
-            this.group = TextUtils.safeIntern(group);
-        }
-
-        public String getGroup() {
-            return group;
-        }
-
-        public boolean isRuntime() {
-            return getProtection() == PermissionInfo.PROTECTION_DANGEROUS;
-        }
-
-        public boolean isAppOp() {
-            return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
-        }
-
-        @PermissionInfo.Protection
-        public int getProtection() {
-            return protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
-        }
-
-        public int getProtectionFlags() {
-            return protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
-        }
-
-        public int calculateFootprint() {
-            int size = getName().length();
-            if (nonLocalizedLabel != null) {
-                size += nonLocalizedLabel.length();
-            }
-            return size;
-        }
-
-        public ParsedPermission() {
-        }
-
-        public ParsedPermission(ParsedPermission other) {
-            // TODO(b/135203078): Better way to copy this? Maybe refactor to the point where copy
-            //  isn't needed.
-            this.className = other.className;
-            this.icon = other.icon;
-            this.labelRes = other.labelRes;
-            this.nonLocalizedLabel = other.nonLocalizedLabel;
-            this.logo = other.logo;
-            this.banner = other.banner;
-            this.descriptionRes = other.descriptionRes;
-            this.enabled = other.enabled;
-            this.directBootAware = other.directBootAware;
-            this.flags = other.flags;
-            this.setSplitName(other.getSplitName());
-            this.setPackageName(other.getPackageName());
-
-            this.intents.addAll(other.intents);
-
-            if (other.metaData != null) {
-                this.metaData = new Bundle();
-                this.metaData.putAll(other.metaData);
-            }
-
-            this.backgroundPermission = other.backgroundPermission;
-            this.setGroup(other.group);
-            this.requestRes = other.requestRes;
-            this.protectionLevel = other.protectionLevel;
-            this.tree = other.tree;
-
-            this.parsedPermissionGroup = other.parsedPermissionGroup;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeString(this.backgroundPermission);
-            dest.writeString(this.group);
-            dest.writeInt(this.requestRes);
-            dest.writeInt(this.protectionLevel);
-            dest.writeBoolean(this.tree);
-            dest.writeParcelable(this.parsedPermissionGroup, flags);
-        }
-
-        protected ParsedPermission(Parcel in) {
-            super(in);
-            // We use the boot classloader for all classes that we load.
-            final ClassLoader boot = Object.class.getClassLoader();
-            this.backgroundPermission = in.readString();
-            this.group = TextUtils.safeIntern(in.readString());
-            this.requestRes = in.readInt();
-            this.protectionLevel = in.readInt();
-            this.tree = in.readBoolean();
-            this.parsedPermissionGroup = in.readParcelable(boot);
-        }
-
-        public static final Creator<ParsedPermission> CREATOR = new Creator<ParsedPermission>() {
-            @Override
-            public ParsedPermission createFromParcel(Parcel source) {
-                return new ParsedPermission(source);
-            }
-
-            @Override
-            public ParsedPermission[] newArray(int size) {
-                return new ParsedPermission[size];
-            }
-        };
-    }
-
-    public static class ParsedPermissionGroup extends ParsedComponent<ParsedIntentInfo> {
-
-        public int requestDetailResourceId;
-        public int backgroundRequestResourceId;
-        public int backgroundRequestDetailResourceId;
-
-        public int requestRes;
-        public int priority;
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeInt(this.requestDetailResourceId);
-            dest.writeInt(this.backgroundRequestResourceId);
-            dest.writeInt(this.backgroundRequestDetailResourceId);
-            dest.writeInt(this.requestRes);
-            dest.writeInt(this.priority);
-        }
-
-        public ParsedPermissionGroup() {
-        }
-
-        protected ParsedPermissionGroup(Parcel in) {
-            super(in);
-            this.requestDetailResourceId = in.readInt();
-            this.backgroundRequestResourceId = in.readInt();
-            this.backgroundRequestDetailResourceId = in.readInt();
-            this.requestRes = in.readInt();
-            this.priority = in.readInt();
-        }
-
-        public static final Creator<ParsedPermissionGroup> CREATOR =
-                new Creator<ParsedPermissionGroup>() {
-                    @Override
-                    public ParsedPermissionGroup createFromParcel(Parcel source) {
-                        return new ParsedPermissionGroup(source);
-                    }
-
-                    @Override
-                    public ParsedPermissionGroup[] newArray(int size) {
-                        return new ParsedPermissionGroup[size];
-                    }
-                };
-    }
-
-    public static class ParsedInstrumentation extends ParsedComponent<ParsedIntentInfo> {
-
-        private String targetPackage;
-        private String targetProcesses;
-        public boolean handleProfiling;
-        public boolean functionalTest;
-
-        public ParsedInstrumentation() {
-        }
-
-        public void setTargetPackage(String targetPackage) {
-            this.targetPackage = TextUtils.safeIntern(targetPackage);
-        }
-
-        public String getTargetPackage() {
-            return targetPackage;
-        }
-
-        public void setTargetProcesses(String targetProcesses) {
-            this.targetProcesses = TextUtils.safeIntern(targetProcesses);
-        }
-
-        public String getTargetProcesses() {
-            return targetProcesses;
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-            dest.writeString(this.targetPackage);
-            dest.writeString(this.targetProcesses);
-            dest.writeBoolean(this.handleProfiling);
-            dest.writeBoolean(this.functionalTest);
-        }
-
-        protected ParsedInstrumentation(Parcel in) {
-            super(in);
-            this.targetPackage = TextUtils.safeIntern(in.readString());
-            this.targetProcesses = TextUtils.safeIntern(in.readString());
-            this.handleProfiling = in.readByte() != 0;
-            this.functionalTest = in.readByte() != 0;
-        }
-
-        public static final Creator<ParsedInstrumentation> CREATOR =
-                new Creator<ParsedInstrumentation>() {
-                    @Override
-                    public ParsedInstrumentation createFromParcel(Parcel source) {
-                        return new ParsedInstrumentation(source);
-                    }
-
-                    @Override
-                    public ParsedInstrumentation[] newArray(int size) {
-                        return new ParsedInstrumentation[size];
-                    }
-                };
-    }
-
-    public static class ParsedProcess implements Parcelable {
-
-        public String name;
-        @Nullable
-        public ArraySet<String> deniedPermissions;
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(this.name);
-            final int numDenied = this.deniedPermissions != null
-                    ? this.deniedPermissions.size() : 0;
-            dest.writeInt(numDenied);
-            for (int i = 0; i < numDenied; i++) {
-                dest.writeString(this.deniedPermissions.valueAt(i));
-            }
-        }
-
-        public ParsedProcess() {
-        }
-
-        public ParsedProcess(@NonNull ParsedProcess other) {
-            name = other.name;
-            if (other.deniedPermissions != null) {
-                deniedPermissions = new ArraySet<>(other.deniedPermissions);
-            }
-        }
-
-        public void addStateFrom(@NonNull ParsedProcess other) {
-            if (other.deniedPermissions != null) {
-                for (int i = other.deniedPermissions.size() - 1; i >= 0; i--) {
-                    if (deniedPermissions == null) {
-                        deniedPermissions = new ArraySet<>(other.deniedPermissions.size());
-                    }
-                    deniedPermissions.add(other.deniedPermissions.valueAt(i));
-                }
-            }
-        }
-
-        protected ParsedProcess(Parcel in) {
-            this.name = TextUtils.safeIntern(in.readString());
-            final int numDenied = in.readInt();
-            if (numDenied > 0) {
-                this.deniedPermissions = new ArraySet<>(numDenied);
-                this.deniedPermissions.add(TextUtils.safeIntern(in.readString()));
-            }
-        }
-
-        public static final Creator<ParsedProcess> CREATOR =
-                new Creator<ParsedProcess>() {
-                    @Override
-                    public ParsedProcess createFromParcel(Parcel source) {
-                        return new ParsedProcess(source);
-                    }
-
-                    @Override
-                    public ParsedProcess[] newArray(int size) {
-                        return new ParsedProcess[size];
-                    }
-                };
-    }
-
-    public static ParsedActivity parseActivity(
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser, int flags, String[] outError,
-            boolean receiver, boolean hardwareAccelerated)
-            throws XmlPullParserException, IOException {
-
-        TypedArray sa = null;
-        boolean visibleToEphemeral;
-        boolean setExported;
-
-        int targetSdkVersion = parsingPackage.getTargetSdkVersion();
-        String packageName = parsingPackage.getPackageName();
-        String packageProcessName = parsingPackage.getProcessName();
-        ParsedActivity result = new ParsedActivity();
-
-        try {
-            sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
-
-            String tag = receiver ? "<receiver>" : "<activity>";
-
-            String name = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_name, 0);
-            if (name == null) {
-                outError[0] = tag + " does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = tag + " invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestActivity_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestActivity_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestActivity_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestActivity_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestActivity_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            CharSequence pname;
-            if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
-                pname = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_process,
-                        Configuration.NATIVE_CONFIG_VERSION);
-            } else {
-                // Some older apps have been seen to use a resource reference
-                // here that on older builds was ignored (with a warning).  We
-                // need to continue to do this for them so they don't break.
-                pname = sa.getNonResourceString(R.styleable.AndroidManifestActivity_process);
-            }
-
-            result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName,
-                    packageProcessName, pname,
-                    flags, separateProcesses, outError));
-
-            result.descriptionRes = sa.getResourceId(
-                    R.styleable.AndroidManifestActivity_description, 0);
-
-            result.enabled = sa.getBoolean(R.styleable.AndroidManifestActivity_enabled, true);
-
-            setExported = sa.hasValue(R.styleable.AndroidManifestActivity_exported);
-            if (setExported) {
-                result.exported = sa.getBoolean(R.styleable.AndroidManifestActivity_exported,
-                        false);
-            }
-
-            result.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
-
-            result.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions,
-                    parsingPackage.getUiOptions());
-
-            String parentName = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestActivity_parentActivityName,
-                    Configuration.NATIVE_CONFIG_VERSION);
-            if (parentName != null) {
-                String parentClassName = ApkParseUtils.buildClassName(packageName, parentName);
-                if (parentClassName == null) {
-                    Log.e(TAG,
-                            "Activity " + result.className
-                                    + " specified invalid parentActivityName " +
-                                    parentName);
-                } else {
-                    result.parentActivityName = parentClassName;
-                }
-            }
-
-            String str;
-            str = sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_permission, 0);
-            if (str == null) {
-                result.setPermission(parsingPackage.getPermission());
-            } else {
-                result.setPermission(str);
-            }
-
-            str = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestActivity_taskAffinity,
-                    Configuration.NATIVE_CONFIG_VERSION);
-            result.taskAffinity = PackageParser.buildTaskAffinityName(
-                    packageName,
-                    parsingPackage.getTaskAffinity(), str, outError);
-
-            result.setSplitName(
-                    sa.getNonConfigurationString(R.styleable.AndroidManifestActivity_splitName, 0));
-
-            result.flags = 0;
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_multiprocess, false)) {
-                result.flags |= ActivityInfo.FLAG_MULTIPROCESS;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnTaskLaunch, false)) {
-                result.flags |= ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_clearTaskOnLaunch, false)) {
-                result.flags |= ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_noHistory, false)) {
-                result.flags |= ActivityInfo.FLAG_NO_HISTORY;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysRetainTaskState, false)) {
-                result.flags |= ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_stateNotNeeded, false)) {
-                result.flags |= ActivityInfo.FLAG_STATE_NOT_NEEDED;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_excludeFromRecents, false)) {
-                result.flags |= ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowTaskReparenting,
-                    (parsingPackage.getFlags() & ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
-                            != 0)) {
-                result.flags |= ActivityInfo.FLAG_ALLOW_TASK_REPARENTING;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs,
-                    false)) {
-                result.flags |= ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_showOnLockScreen, false)
-                    || sa.getBoolean(R.styleable.AndroidManifestActivity_showForAllUsers, false)) {
-                result.flags |= ActivityInfo.FLAG_SHOW_FOR_ALL_USERS;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_immersive, false)) {
-                result.flags |= ActivityInfo.FLAG_IMMERSIVE;
-            }
-
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_systemUserOnly, false)) {
-                result.flags |= ActivityInfo.FLAG_SYSTEM_USER_ONLY;
-            }
-
-            boolean directBootAware;
-
-            if (!receiver) {
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_hardwareAccelerated,
-                        hardwareAccelerated)) {
-                    result.flags |= ActivityInfo.FLAG_HARDWARE_ACCELERATED;
-                }
-
-                result.launchMode = sa.getInt(
-                        R.styleable.AndroidManifestActivity_launchMode,
-                        ActivityInfo.LAUNCH_MULTIPLE);
-                result.documentLaunchMode = sa.getInt(
-                        R.styleable.AndroidManifestActivity_documentLaunchMode,
-                        ActivityInfo.DOCUMENT_LAUNCH_NONE);
-                result.maxRecents = sa.getInt(
-                        R.styleable.AndroidManifestActivity_maxRecents,
-                        ActivityTaskManager.getDefaultAppRecentsLimitStatic());
-                result.configChanges = PackageParser.getActivityConfigChanges(
-                        sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
-                        sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
-                result.softInputMode = sa.getInt(
-                        R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
-
-                result.persistableMode = sa.getInteger(
-                        R.styleable.AndroidManifestActivity_persistableMode,
-                        ActivityInfo.PERSIST_ROOT_ONLY);
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_allowEmbedded, false)) {
-                    result.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_autoRemoveFromRecents,
-                        false)) {
-                    result.flags |= ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_relinquishTaskIdentity,
-                        false)) {
-                    result.flags |= ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_resumeWhilePausing, false)) {
-                    result.flags |= ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
-                }
-
-                int screenOrientation = sa.getInt(
-                        R.styleable.AndroidManifestActivity_screenOrientation,
-                        SCREEN_ORIENTATION_UNSPECIFIED);
-                result.screenOrientation = screenOrientation;
-
-                int resizeMode = getActivityResizeMode(parsingPackage, sa, screenOrientation);
-                result.resizeMode = resizeMode;
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_supportsPictureInPicture,
-                        false)) {
-                    result.flags |= FLAG_SUPPORTS_PICTURE_IN_PICTURE;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_alwaysFocusable, false)) {
-                    result.flags |= FLAG_ALWAYS_FOCUSABLE;
-                }
-
-                if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
-                        && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
-                        == TypedValue.TYPE_FLOAT) {
-                    result.setMaxAspectRatio(resizeMode,
-                            sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
-                                    0 /*default*/));
-                }
-
-                if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
-                        && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
-                        == TypedValue.TYPE_FLOAT) {
-                    result.setMinAspectRatio(resizeMode,
-                            sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
-                                    0 /*default*/));
-                }
-
-                result.lockTaskLaunchMode =
-                        sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
-
-                directBootAware = sa.getBoolean(
-                        R.styleable.AndroidManifestActivity_directBootAware,
-                        false);
-
-                result.requestedVrComponent =
-                        sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
-
-                result.rotationAnimation =
-                        sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation,
-                                ROTATION_ANIMATION_UNSPECIFIED);
-
-                result.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
-                        ActivityInfo.COLOR_MODE_DEFAULT);
-
-                result.preferMinimalPostProcessing = sa.getBoolean(
-                        R.styleable.AndroidManifestActivity_preferMinimalPostProcessing,
-                        ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT);
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_showWhenLocked, false)) {
-                    result.flags |= ActivityInfo.FLAG_SHOW_WHEN_LOCKED;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_turnScreenOn, false)) {
-                    result.flags |= ActivityInfo.FLAG_TURN_SCREEN_ON;
-                }
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_inheritShowWhenLocked,
-                        false)) {
-                    result.privateFlags |= ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED;
-                }
-            } else {
-                result.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
-                result.configChanges = 0;
-
-                if (sa.getBoolean(R.styleable.AndroidManifestActivity_singleUser, false)) {
-                    result.flags |= ActivityInfo.FLAG_SINGLE_USER;
-                }
-                directBootAware = sa.getBoolean(
-                        R.styleable.AndroidManifestActivity_directBootAware,
-                        false);
-            }
-
-            result.directBootAware = directBootAware;
-
-            if (directBootAware) {
-                parsingPackage.setPartiallyDirectBootAware(true);
-            }
-
-            // can't make this final; we may set it later via meta-data
-            visibleToEphemeral = sa.getBoolean(
-                    R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
-            if (visibleToEphemeral) {
-                result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                parsingPackage.setVisibleToInstantApps(true);
-            }
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-
-        if (receiver && (parsingPackage.getPrivateFlags()
-                & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {
-            // A heavy-weight application can not have receives in its main process
-            if (result.getProcessName().equals(packageName)) {
-                outError[0] = "Heavy-weight applications can not have receivers in main process";
-                return null;
-            }
-        }
-
-        if (outError[0] != null) {
-            return null;
-        }
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            if (parser.getName().equals("intent-filter")) {
-                ParsedActivityIntentInfo intentInfo = new ParsedActivityIntentInfo(packageName,
-                        result.className);
-                if (!parseIntentInfo(intentInfo, parsingPackage, res, parser,
-                        true /*allowGlobs*/,
-                        true /*allowAutoVerify*/, outError)) {
-                    return null;
-                }
-                if (intentInfo.countActions() == 0) {
-                    Slog.w(TAG, "No actions in intent filter at "
-                            + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                } else {
-                    result.order = Math.max(intentInfo.getOrder(), result.order);
-                    result.addIntent(intentInfo);
-                }
-                // adjust activity flags when we implicitly expose it via a browsable filter
-                final int visibility = visibleToEphemeral
-                        ? IntentFilter.VISIBILITY_EXPLICIT
-                        : !receiver && isImplicitlyExposedIntent(intentInfo)
-                                ? IntentFilter.VISIBILITY_IMPLICIT
-                                : IntentFilter.VISIBILITY_NONE;
-                intentInfo.setVisibilityToInstantApp(visibility);
-                if (intentInfo.isVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                }
-                if (intentInfo.isImplicitlyVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
-                }
-                if (PackageParser.LOG_UNSAFE_BROADCASTS && receiver
-                        && (targetSdkVersion >= Build.VERSION_CODES.O)) {
-                    for (int i = 0; i < intentInfo.countActions(); i++) {
-                        final String action = intentInfo.getAction(i);
-                        if (action == null || !action.startsWith("android.")) continue;
-                        if (!PackageParser.SAFE_BROADCASTS.contains(action)) {
-                            Slog.w(TAG, "Broadcast " + action + " may never be delivered to "
-                                    + packageName + " as requested at: "
-                                    + parser.getPositionDescription());
-                        }
-                    }
-                }
-            } else if (!receiver && parser.getName().equals("preferred")) {
-                ParsedActivityIntentInfo intentInfo = new ParsedActivityIntentInfo(packageName,
-                        result.className);
-                if (!parseIntentInfo(intentInfo, parsingPackage, res, parser,
-                        false /*allowGlobs*/,
-                        false /*allowAutoVerify*/, outError)) {
-                    return null;
-                }
-                // adjust activity flags when we implicitly expose it via a browsable filter
-                final int visibility = visibleToEphemeral
-                        ? IntentFilter.VISIBILITY_EXPLICIT
-                        : !receiver && isImplicitlyExposedIntent(intentInfo)
-                                ? IntentFilter.VISIBILITY_IMPLICIT
-                                : IntentFilter.VISIBILITY_NONE;
-                intentInfo.setVisibilityToInstantApp(visibility);
-                if (intentInfo.isVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                }
-                if (intentInfo.isImplicitlyVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
-                }
-
-                if (intentInfo.countActions() == 0) {
-                    Slog.w(TAG, "No actions in preferred at "
-                            + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                } else {
-                    parsingPackage.addPreferredActivityFilter(intentInfo);
-                }
-            } else if (parser.getName().equals("meta-data")) {
-                if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser,
-                        result.metaData,
-                        outError)) == null) {
-                    return null;
-                }
-            } else if (!receiver && parser.getName().equals("layout")) {
-                result.windowLayout = parseLayout(res, parser);
-            } else {
-                if (!PackageParser.RIGID_PARSER) {
-                    Slog.w(TAG, "Problem in package " + parsingPackage.getBaseCodePath() + ":");
-                    if (receiver) {
-                        Slog.w(TAG, "Unknown element under <receiver>: " + parser.getName()
-                                + " at " + parsingPackage.getBaseCodePath() + " "
-                                + parser.getPositionDescription());
-                    } else {
-                        Slog.w(TAG, "Unknown element under <activity>: " + parser.getName()
-                                + " at " + parsingPackage.getBaseCodePath() + " "
-                                + parser.getPositionDescription());
-                    }
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-                } else {
-                    if (receiver) {
-                        outError[0] = "Bad element under <receiver>: " + parser.getName();
-                    } else {
-                        outError[0] = "Bad element under <activity>: " + parser.getName();
-                    }
-                    return null;
-                }
-            }
-        }
-
-        if (!setExported) {
-            result.exported = result.intents.size() > 0;
-        }
-
-        return result;
-    }
-
-    public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) {
-        return intentInfo.hasCategory(Intent.CATEGORY_BROWSABLE)
-                || intentInfo.hasAction(Intent.ACTION_SEND)
-                || intentInfo.hasAction(Intent.ACTION_SENDTO)
-                || intentInfo.hasAction(Intent.ACTION_SEND_MULTIPLE);
-    }
-
-    public static int getActivityResizeMode(
-            ParsingPackage parsingPackage,
-            TypedArray sa,
-            int screenOrientation
-    ) {
-        int privateFlags = parsingPackage.getPrivateFlags();
-        final boolean appExplicitDefault = (privateFlags
-                & (ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
-                | ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE)) != 0;
-
-        if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
-                || appExplicitDefault) {
-            // Activity or app explicitly set if it is resizeable or not;
-            final boolean appResizeable = (privateFlags
-                    & ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE) != 0;
-            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
-                    appResizeable)) {
-                return ActivityInfo.RESIZE_MODE_RESIZEABLE;
-            } else {
-                return ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
-            }
-        }
-
-        if ((privateFlags
-                & ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
-                != 0) {
-            // The activity or app didn't explicitly set the resizing option, however we want to
-            // make it resize due to the sdk version it is targeting.
-            return ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-        }
-
-        // resize preference isn't set and target sdk version doesn't support resizing apps by
-        // default. For the app to be resizeable if it isn't fixed orientation or immersive.
-        if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)) {
-            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
-        } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)) {
-            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
-        } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
-            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
-        } else {
-            return ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
-        }
-    }
-
-    public static ParsedService parseService(
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser, int flags, String[] outError
-    ) throws XmlPullParserException, IOException {
-        TypedArray sa = null;
-        boolean visibleToEphemeral;
-        boolean setExported;
-
-        String packageName = parsingPackage.getPackageName();
-        String packageProcessName = parsingPackage.getProcessName();
-        ParsedService result = new ParsedService();
-
-        try {
-            sa = res.obtainAttributes(parser,
-                    R.styleable.AndroidManifestService);
-
-            String name = sa.getNonConfigurationString(R.styleable.AndroidManifestService_name, 0);
-            if (name == null) {
-                outError[0] = "<service> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<service> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestService_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestService_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestService_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestService_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestService_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            CharSequence pname;
-            if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
-                pname = sa.getNonConfigurationString(R.styleable.AndroidManifestService_process,
-                        Configuration.NATIVE_CONFIG_VERSION);
-            } else {
-                // Some older apps have been seen to use a resource reference
-                // here that on older builds was ignored (with a warning).  We
-                // need to continue to do this for them so they don't break.
-                pname = sa.getNonResourceString(R.styleable.AndroidManifestService_process);
-            }
-
-            result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName,
-                    packageProcessName, pname,
-                    flags, separateProcesses, outError));
-
-            result.descriptionRes = sa.getResourceId(
-                    R.styleable.AndroidManifestService_description, 0);
-
-            result.enabled = sa.getBoolean(R.styleable.AndroidManifestService_enabled, true);
-
-            setExported = sa.hasValue(
-                    R.styleable.AndroidManifestService_exported);
-            if (setExported) {
-                result.exported = sa.getBoolean(
-                        R.styleable.AndroidManifestService_exported, false);
-            }
-
-            String str = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestService_permission, 0);
-            if (str == null) {
-                result.setPermission(parsingPackage.getPermission());
-            } else {
-                result.setPermission(str);
-            }
-
-            result.setSplitName(
-                    sa.getNonConfigurationString(R.styleable.AndroidManifestService_splitName, 0));
-
-            result.foregroundServiceType = sa.getInt(
-                    R.styleable.AndroidManifestService_foregroundServiceType,
-                    ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
-
-            result.flags = 0;
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestService_stopWithTask,
-                    false)) {
-                result.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
-            }
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestService_isolatedProcess,
-                    false)) {
-                result.flags |= ServiceInfo.FLAG_ISOLATED_PROCESS;
-            }
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestService_externalService,
-                    false)) {
-                result.flags |= ServiceInfo.FLAG_EXTERNAL_SERVICE;
-            }
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestService_useAppZygote,
-                    false)) {
-                result.flags |= ServiceInfo.FLAG_USE_APP_ZYGOTE;
-            }
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestService_singleUser,
-                    false)) {
-                result.flags |= ServiceInfo.FLAG_SINGLE_USER;
-            }
-
-            result.directBootAware = sa.getBoolean(
-                    R.styleable.AndroidManifestService_directBootAware,
-                    false);
-            if (result.directBootAware) {
-                parsingPackage.setPartiallyDirectBootAware(true);
-            }
-
-            visibleToEphemeral = sa.getBoolean(
-                    R.styleable.AndroidManifestService_visibleToInstantApps, false);
-            if (visibleToEphemeral) {
-                result.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                parsingPackage.setVisibleToInstantApps(true);
-            }
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        if (parsingPackage.cantSaveState()) {
-            // A heavy-weight application can not have services in its main process
-            // We can do direct compare because we intern all strings.
-            if (Objects.equals(result.getProcessName(), parsingPackage.getPackageName())) {
-                outError[0] = "Heavy-weight applications can not have services in main process";
-                return null;
-            }
-        }
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            if (parser.getName().equals("intent-filter")) {
-                ParsedServiceIntentInfo intent = new ParsedServiceIntentInfo(packageName,
-                        result.className);
-                if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/,
-                        false /*allowAutoVerify*/,
-                        outError)) {
-                    return null;
-                }
-                if (visibleToEphemeral) {
-                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                    result.flags |= ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                }
-                result.order = Math.max(intent.getOrder(), result.order);
-                result.intents.add(intent);
-            } else if (parser.getName().equals("meta-data")) {
-                if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser,
-                        result.metaData,
-                        outError)) == null) {
-                    return null;
-                }
-            } else {
-                if (!PackageParser.RIGID_PARSER) {
-                    Slog.w(TAG, "Unknown element under <service>: "
-                            + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-                } else {
-                    outError[0] = "Bad element under <service>: " + parser.getName();
-                    return null;
-                }
-            }
-        }
-
-        if (!setExported) {
-            result.exported = result.intents.size() > 0;
-        }
-
-        return result;
-    }
-
-    public static ParsedProvider parseProvider(
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser, int flags, String[] outError)
-            throws XmlPullParserException, IOException {
-        TypedArray sa = null;
-        String cpname;
-        boolean visibleToEphemeral;
-
-        int targetSdkVersion = parsingPackage.getTargetSdkVersion();
-        String packageName = parsingPackage.getPackageName();
-        String packageProcessName = parsingPackage.getProcessName();
-        ParsedProvider result = new ParsedProvider();
-
-        try {
-            sa = res.obtainAttributes(parser,
-                    R.styleable.AndroidManifestProvider);
-
-            String name = sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_name, 0);
-            if (name == null) {
-                outError[0] = "<provider> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<provider> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestProvider_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestProvider_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestProvider_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestProvider_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestProvider_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            CharSequence pname;
-            if (parsingPackage.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
-                pname = sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_process,
-                        Configuration.NATIVE_CONFIG_VERSION);
-            } else {
-                // Some older apps have been seen to use a resource reference
-                // here that on older builds was ignored (with a warning).  We
-                // need to continue to do this for them so they don't break.
-                pname = sa.getNonResourceString(R.styleable.AndroidManifestProvider_process);
-            }
-
-            result.setProcessName(packageProcessName, PackageParser.buildProcessName(packageName,
-                    packageProcessName, pname,
-                    flags, separateProcesses, outError));
-
-            result.descriptionRes = sa.getResourceId(
-                    R.styleable.AndroidManifestProvider_description, 0);
-
-            result.enabled = sa.getBoolean(R.styleable.AndroidManifestProvider_enabled, true);
-
-            boolean providerExportedDefault = false;
-
-            if (targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1) {
-                // For compatibility, applications targeting API level 16 or lower
-                // should have their content providers exported by default, unless they
-                // specify otherwise.
-                providerExportedDefault = true;
-            }
-
-            result.exported = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_exported,
-                    providerExportedDefault);
-
-            cpname = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestProvider_authorities, 0);
-
-            result.isSyncable = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_syncable,
-                    false);
-
-            String permission = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestProvider_permission, 0);
-            String str = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestProvider_readPermission, 0);
-            if (str == null) {
-                str = permission;
-            }
-            if (str == null) {
-                result.setReadPermission(parsingPackage.getPermission());
-            } else {
-                result.setReadPermission(str);
-            }
-            str = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestProvider_writePermission, 0);
-            if (str == null) {
-                str = permission;
-            }
-            if (str == null) {
-                result.setWritePermission(parsingPackage.getPermission());
-            } else {
-                result.setWritePermission(str);
-            }
-
-            result.grantUriPermissions = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_grantUriPermissions,
-                    false);
-
-            result.forceUriPermissions = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_forceUriPermissions,
-                    false);
-
-            result.multiProcess = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_multiprocess,
-                    false);
-
-            result.initOrder = sa.getInt(
-                    R.styleable.AndroidManifestProvider_initOrder,
-                    0);
-
-            result.setSplitName(
-                    sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_splitName, 0));
-
-            result.flags = 0;
-
-            if (sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_singleUser,
-                    false)) {
-                result.flags |= ProviderInfo.FLAG_SINGLE_USER;
-            }
-
-            result.directBootAware = sa.getBoolean(
-                    R.styleable.AndroidManifestProvider_directBootAware,
-                    false);
-            if (result.directBootAware) {
-                parsingPackage.setPartiallyDirectBootAware(true);
-            }
-
-            visibleToEphemeral =
-                    sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
-            if (visibleToEphemeral) {
-                result.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                parsingPackage.setVisibleToInstantApps(true);
-            }
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        if ((parsingPackage.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
-                != 0) {
-            // A heavy-weight application can not have providers in its main process
-            if (result.getProcessName().equals(packageName)) {
-                outError[0] = "Heavy-weight applications can not have providers in main process";
-                return null;
-            }
-        }
-
-        if (cpname == null) {
-            outError[0] = "<provider> does not include authorities attribute";
-            return null;
-        }
-        if (cpname.length() <= 0) {
-            outError[0] = "<provider> has empty authorities attribute";
-            return null;
-        }
-        result.setAuthority(cpname);
-
-        if (!parseProviderTags(parsingPackage, res, parser, visibleToEphemeral, result, outError)) {
-            return null;
-        }
-
-        return result;
-    }
-
-    public static ParsedQueriesIntentInfo parsedParsedQueriesIntentInfo(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        ParsedQueriesIntentInfo intentInfo = new ParsedQueriesIntentInfo(
-                parsingPackage.getPackageName(),
-                null
-        );
-        if (!parseIntentInfo(
-                intentInfo,
-                parsingPackage,
-                res,
-                parser,
-                true /*allowGlobs*/,
-                true /*allowAutoVerify*/,
-                outError
-        )) {
-            return null;
-        }
-        return intentInfo;
-    }
-
-    private static boolean parseProviderTags(
-            ParsingPackage parsingPackage,
-            Resources res, XmlResourceParser parser,
-            boolean visibleToEphemeral, ParsedProvider outInfo, String[] outError)
-            throws XmlPullParserException, IOException {
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            if (parser.getName().equals("intent-filter")) {
-                ParsedProviderIntentInfo intent = new ParsedProviderIntentInfo(
-                        parsingPackage.getPackageName(), outInfo.className);
-                if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/,
-                        false /*allowAutoVerify*/,
-                        outError)) {
-                    return false;
-                }
-                if (visibleToEphemeral) {
-                    intent.setVisibilityToInstantApp(IntentFilter.VISIBILITY_EXPLICIT);
-                    outInfo.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                }
-                outInfo.order = Math.max(intent.getOrder(), outInfo.order);
-                outInfo.intents.add(intent);
-
-            } else if (parser.getName().equals("meta-data")) {
-                Bundle metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser,
-                        outInfo.metaData, outError);
-                if (metaData == null) {
-                    return false;
-                } else {
-                    outInfo.metaData = metaData;
-                }
-
-            } else if (parser.getName().equals("grant-uri-permission")) {
-                TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestGrantUriPermission);
-
-                PatternMatcher pa = null;
-
-                String str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestGrantUriPermission_path, 0);
-                if (str != null) {
-                    pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
-                if (str != null) {
-                    pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
-                if (str != null) {
-                    pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
-                }
-
-                sa.recycle();
-
-                if (pa != null) {
-                    if (outInfo.uriPermissionPatterns == null) {
-                        outInfo.uriPermissionPatterns = new PatternMatcher[1];
-                        outInfo.uriPermissionPatterns[0] = pa;
-                    } else {
-                        final int N = outInfo.uriPermissionPatterns.length;
-                        PatternMatcher[] newp = new PatternMatcher[N + 1];
-                        System.arraycopy(outInfo.uriPermissionPatterns, 0, newp, 0, N);
-                        newp[N] = pa;
-                        outInfo.uriPermissionPatterns = newp;
-                    }
-                    outInfo.grantUriPermissions = true;
-                } else {
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG, "Unknown element under <path-permission>: "
-                                + parser.getName() + " at " + parsingPackage.getBaseCodePath()
-                                + " "
-                                + parser.getPositionDescription());
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    } else {
-                        outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
-                        return false;
-                    }
-                }
-                XmlUtils.skipCurrentTag(parser);
-
-            } else if (parser.getName().equals("path-permission")) {
-                TypedArray sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestPathPermission);
-
-                PathPermission pa = null;
-
-                String permission = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_permission, 0);
-                String readPermission = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_readPermission, 0);
-                if (readPermission == null) {
-                    readPermission = permission;
-                }
-                String writePermission = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_writePermission, 0);
-                if (writePermission == null) {
-                    writePermission = permission;
-                }
-
-                boolean havePerm = false;
-                if (readPermission != null) {
-                    readPermission = readPermission.intern();
-                    havePerm = true;
-                }
-                if (writePermission != null) {
-                    writePermission = writePermission.intern();
-                    havePerm = true;
-                }
-
-                if (!havePerm) {
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG, "No readPermission or writePermssion for <path-permission>: "
-                                + parser.getName() + " at " + parsingPackage.getBaseCodePath()
-                                + " "
-                                + parser.getPositionDescription());
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    } else {
-                        outError[0] = "No readPermission or writePermssion for <path-permission>";
-                        return false;
-                    }
-                }
-
-                String path = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_path, 0);
-                if (path != null) {
-                    pa = new PathPermission(path,
-                            PatternMatcher.PATTERN_LITERAL, readPermission, writePermission);
-                }
-
-                path = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
-                if (path != null) {
-                    pa = new PathPermission(path,
-                            PatternMatcher.PATTERN_PREFIX, readPermission, writePermission);
-                }
-
-                path = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_pathPattern, 0);
-                if (path != null) {
-                    pa = new PathPermission(path,
-                            PatternMatcher.PATTERN_SIMPLE_GLOB, readPermission, writePermission);
-                }
-
-                path = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
-                if (path != null) {
-                    pa = new PathPermission(path,
-                            PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission, writePermission);
-                }
-
-                sa.recycle();
-
-                if (pa != null) {
-                    if (outInfo.pathPermissions == null) {
-                        outInfo.pathPermissions = new PathPermission[1];
-                        outInfo.pathPermissions[0] = pa;
-                    } else {
-                        final int N = outInfo.pathPermissions.length;
-                        PathPermission[] newp = new PathPermission[N + 1];
-                        System.arraycopy(outInfo.pathPermissions, 0, newp, 0, N);
-                        newp[N] = pa;
-                        outInfo.pathPermissions = newp;
-                    }
-                } else {
-                    if (!PackageParser.RIGID_PARSER) {
-                        Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
-                                + parser.getName() + " at " + parsingPackage.getBaseCodePath()
-                                + " "
-                                + parser.getPositionDescription());
-                        XmlUtils.skipCurrentTag(parser);
-                        continue;
-                    }
-                    outError[0] = "No path, pathPrefix, or pathPattern for <path-permission>";
-                    return false;
-                }
-                XmlUtils.skipCurrentTag(parser);
-
-            } else {
-                if (!PackageParser.RIGID_PARSER) {
-                    Slog.w(TAG, "Unknown element under <provider>: "
-                            + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-                } else {
-                    outError[0] = "Bad element under <provider>: " + parser.getName();
-                    return false;
-                }
-            }
-        }
-        return true;
-    }
-
-    public static ParsedActivity parseActivityAlias(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError)
-            throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestActivityAlias);
-
-        String targetActivity = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestActivityAlias_targetActivity,
-                Configuration.NATIVE_CONFIG_VERSION);
-        if (targetActivity == null) {
-            outError[0] = "<activity-alias> does not specify android:targetActivity";
-            sa.recycle();
-            return null;
-        }
-
-        String packageName = parsingPackage.getPackageName();
-        targetActivity = ApkParseUtils.buildClassName(packageName, targetActivity);
-        if (targetActivity == null) {
-            outError[0] = "Empty class name in package " + packageName;
-            sa.recycle();
-            return null;
-        }
-
-        ParsedActivity target = null;
-
-        List<ParsedActivity> activities = parsingPackage.getActivities();
-        final int NA = activities.size();
-        for (int i = 0; i < NA; i++) {
-            ParsedActivity t = activities.get(i);
-            if (targetActivity.equals(t.className)) {
-                target = t;
-                break;
-            }
-        }
-
-        if (target == null) {
-            outError[0] = "<activity-alias> target activity " + targetActivity
-                    + " not found in manifest with activities = " + parsingPackage.getActivities()
-                    + ", parsedActivities = " + activities;
-            sa.recycle();
-            return null;
-        }
-
-        ParsedActivity result = new ParsedActivity();
-        result.setPackageNameInternal(target.getPackageName());
-        result.targetActivity = targetActivity;
-        result.configChanges = target.configChanges;
-        result.flags = target.flags;
-        result.privateFlags = target.privateFlags;
-        result.icon = target.icon;
-        result.logo = target.logo;
-        result.banner = target.banner;
-        result.labelRes = target.labelRes;
-        result.nonLocalizedLabel = target.nonLocalizedLabel;
-        result.launchMode = target.launchMode;
-        result.lockTaskLaunchMode = target.lockTaskLaunchMode;
-        result.descriptionRes = target.descriptionRes;
-        result.screenOrientation = target.screenOrientation;
-        result.taskAffinity = target.taskAffinity;
-        result.theme = target.theme;
-        result.softInputMode = target.softInputMode;
-        result.uiOptions = target.uiOptions;
-        result.parentActivityName = target.parentActivityName;
-        result.maxRecents = target.maxRecents;
-        result.windowLayout = target.windowLayout;
-        result.resizeMode = target.resizeMode;
-        result.maxAspectRatio = target.maxAspectRatio;
-        result.hasMaxAspectRatio = target.hasMaxAspectRatio;
-        result.minAspectRatio = target.minAspectRatio;
-        result.hasMinAspectRatio = target.hasMinAspectRatio;
-        result.requestedVrComponent = target.requestedVrComponent;
-        result.directBootAware = target.directBootAware;
-
-        result.setProcessName(parsingPackage.getAppInfoProcessName(), target.getProcessName());
-
-        // Not all attributes from the target ParsedActivity are copied to the alias.
-        // Careful when adding an attribute and determine whether or not it should be copied.
-//        result.enabled = target.enabled;
-//        result.exported = target.exported;
-//        result.permission = target.permission;
-//        result.splitName = target.splitName;
-//        result.documentLaunchMode = target.documentLaunchMode;
-//        result.persistableMode = target.persistableMode;
-//        result.rotationAnimation = target.rotationAnimation;
-//        result.colorMode = target.colorMode;
-//        result.intents.addAll(target.intents);
-//        result.order = target.order;
-//        result.metaData = target.metaData;
-
-        String name = sa.getNonConfigurationString(R.styleable.AndroidManifestActivityAlias_name,
-                0);
-        if (name == null) {
-            outError[0] = "<activity-alias> does not specify android:name";
-            return null;
-        } else {
-            String className = ApkParseUtils.buildClassName(packageName, name);
-            if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                outError[0] = "<activity-alias> invalid android:name";
-                return null;
-            } else if (className == null) {
-                outError[0] = "Empty class name in package " + packageName;
-                return null;
-            }
-
-            result.className = className;
-        }
-
-        int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                R.styleable.AndroidManifestActivityAlias_roundIcon, 0) : 0;
-        if (roundIconVal != 0) {
-            result.icon = roundIconVal;
-            result.nonLocalizedLabel = null;
-        } else {
-            int iconVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_icon, 0);
-            if (iconVal != 0) {
-                result.icon = iconVal;
-                result.nonLocalizedLabel = null;
-            }
-        }
-
-        int logoVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_logo, 0);
-        if (logoVal != 0) {
-            result.logo = logoVal;
-        }
-
-        int bannerVal = sa.getResourceId(R.styleable.AndroidManifestActivityAlias_banner, 0);
-        if (bannerVal != 0) {
-            result.banner = bannerVal;
-        }
-
-        TypedValue v = sa.peekValue(R.styleable.AndroidManifestActivityAlias_label);
-        if (v != null && (result.labelRes = v.resourceId) == 0) {
-            result.nonLocalizedLabel = v.coerceToString();
-        }
-
-        result.setPackageNameInternal(packageName);
-
-        result.descriptionRes = sa.getResourceId(
-                R.styleable.AndroidManifestActivityAlias_description, 0);
-
-        result.enabled = sa.getBoolean(R.styleable.AndroidManifestActivityAlias_enabled, true);
-
-        final boolean setExported = sa.hasValue(
-                R.styleable.AndroidManifestActivityAlias_exported);
-        if (setExported) {
-            result.exported = sa.getBoolean(
-                    R.styleable.AndroidManifestActivityAlias_exported, false);
-        }
-
-        String str;
-        str = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestActivityAlias_permission, 0);
-        if (str != null) {
-            result.setPermission(str);
-        }
-
-        String parentName = sa.getNonConfigurationString(
-                R.styleable.AndroidManifestActivityAlias_parentActivityName,
-                Configuration.NATIVE_CONFIG_VERSION);
-        if (parentName != null) {
-            String parentClassName = ApkParseUtils.buildClassName(result.getPackageName(),
-                    parentName);
-            if (parentClassName == null) {
-                Log.e(TAG, "Activity alias " + result.className +
-                        " specified invalid parentActivityName " + parentName);
-                outError[0] = null;
-            } else {
-                result.parentActivityName = parentClassName;
-            }
-        }
-
-        // TODO add visibleToInstantApps attribute to activity alias
-        final boolean visibleToEphemeral =
-                ((result.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
-
-        sa.recycle();
-
-        if (outError[0] != null) {
-            return null;
-        }
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("intent-filter")) {
-                ParsedActivityIntentInfo intent = new ParsedActivityIntentInfo(packageName,
-                        result.className);
-                if (!parseIntentInfo(intent, parsingPackage, res, parser, true /*allowGlobs*/,
-                        true /*allowAutoVerify*/, outError)) {
-                    return null;
-                }
-                if (intent.countActions() == 0) {
-                    Slog.w(TAG, "No actions in intent filter at "
-                            + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                } else {
-                    result.order = Math.max(intent.getOrder(), result.order);
-                    result.addIntent(intent);
-                }
-                // adjust activity flags when we implicitly expose it via a browsable filter
-                final int visibility = visibleToEphemeral
-                        ? IntentFilter.VISIBILITY_EXPLICIT
-                        : isImplicitlyExposedIntent(intent)
-                                ? IntentFilter.VISIBILITY_IMPLICIT
-                                : IntentFilter.VISIBILITY_NONE;
-                intent.setVisibilityToInstantApp(visibility);
-                if (intent.isVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
-                }
-                if (intent.isImplicitlyVisibleToInstantApp()) {
-                    result.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
-                }
-            } else if (tagName.equals("meta-data")) {
-                if ((result.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser,
-                        result.metaData,
-                        outError)) == null) {
-                    return null;
-                }
-            } else {
-                if (!PackageParser.RIGID_PARSER) {
-                    Slog.w(TAG, "Unknown element under <activity-alias>: " + tagName
-                            + " at " + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-                } else {
-                    outError[0] = "Bad element under <activity-alias>: " + tagName;
-                    return null;
-                }
-            }
-        }
-
-        if (!setExported) {
-            result.exported = result.intents.size() > 0;
-        }
-
-        return result;
-    }
-
-    public static ParsedFeature parseFeature(
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        String featureId;
-        int label;
-        List<String> inheritFrom = null;
-
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeature);
-        if (sa == null) {
-            outError[0] = "<feature> could not be parsed";
-            return null;
-        }
-
-        try {
-            featureId = sa.getNonConfigurationString(R.styleable.AndroidManifestFeature_featureId,
-                    0);
-            if (featureId == null) {
-                outError[0] = "<featureId> does not specify android:featureId";
-                return null;
-            }
-            if (featureId.length() > ParsedFeature.MAX_FEATURE_ID_LEN) {
-                outError[0] = "<featureId> is too long. Max length is "
-                        + ParsedFeature.MAX_FEATURE_ID_LEN;
-                return null;
-            }
-
-            label = sa.getResourceId(R.styleable.AndroidManifestFeature_label, 0);
-            if (label == Resources.ID_NULL) {
-                outError[0] = "<featureId> does not specify android:label";
-                return null;
-            }
-        } finally {
-            sa.recycle();
-        }
-
-        int type;
-        final int innerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("inherit-from")) {
-                sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeatureInheritFrom);
-                if (sa == null) {
-                    outError[0] = "<inherit-from> could not be parsed";
-                    return null;
-                }
-
-                try {
-                    String inheritFromId = sa.getNonConfigurationString(
-                            R.styleable.AndroidManifestFeatureInheritFrom_featureId,0);
-
-                    if (inheritFrom == null) {
-                        inheritFrom = new ArrayList<>();
-                    }
-                    inheritFrom.add(inheritFromId);
-                } finally {
-                    sa.recycle();
-                }
-            } else {
-                outError[0] = "Bad element under <feature>: " + tagName;
-                return null;
-            }
-        }
-
-        if (inheritFrom == null) {
-            inheritFrom = Collections.emptyList();
-        } else {
-            ((ArrayList) inheritFrom).trimToSize();
-        }
-
-        return new ParsedFeature(featureId, label, inheritFrom);
-    }
-
-    public static ParsedPermission parsePermission(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = null;
-        String packageName = parsingPackage.getPackageName();
-        ParsedPermission result = new ParsedPermission();
-
-        try {
-            sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermission);
-
-            String name = sa.getNonConfigurationString(R.styleable.AndroidManifestPermission_name,
-                    0);
-            if (name == null) {
-                outError[0] = "<permission> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<permission> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestPermission_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermission_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermission_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermission_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermission_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            result.descriptionRes = sa.getResourceId(
-                    R.styleable.AndroidManifestPermission_description, 0);
-
-            if (sa.hasValue(
-                    R.styleable.AndroidManifestPermission_backgroundPermission)) {
-                if ("android".equals(packageName)) {
-                    result.backgroundPermission = sa.getNonResourceString(
-                            R.styleable
-                                    .AndroidManifestPermission_backgroundPermission);
-                } else {
-                    Slog.w(TAG, packageName + " defines a background permission. Only the "
-                            + "'android' package can do that.");
-                }
-            }
-
-            // Note: don't allow this value to be a reference to a resource
-            // that may change.
-            result.setGroup(sa.getNonResourceString(
-                    R.styleable.AndroidManifestPermission_permissionGroup));
-
-            result.requestRes = sa.getResourceId(
-                    R.styleable.AndroidManifestPermission_request, 0);
-
-            result.protectionLevel = sa.getInt(
-                    R.styleable.AndroidManifestPermission_protectionLevel,
-                    PermissionInfo.PROTECTION_NORMAL);
-
-            result.flags = sa.getInt(
-                    R.styleable.AndroidManifestPermission_permissionFlags, 0);
-
-            // For now only platform runtime permissions can be restricted
-            if (!result.isRuntime() || !"android".equals(result.getPackageName())) {
-                result.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED;
-                result.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED;
-            } else {
-                // The platform does not get to specify conflicting permissions
-                if ((result.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
-                        && (result.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
-                    throw new IllegalStateException("Permission cannot be both soft and hard"
-                            + " restricted: " + result.getName());
-                }
-            }
-
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        if (result.protectionLevel == -1) {
-            outError[0] = "<permission> does not specify protectionLevel";
-            return null;
-        }
-
-        result.protectionLevel = PermissionInfo.fixProtectionLevel(result.protectionLevel);
-
-        if (result.getProtectionFlags() != 0) {
-            if ((result.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
-                    && (result.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY)
-                    == 0
-                    && (result.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) !=
-                    PermissionInfo.PROTECTION_SIGNATURE) {
-                outError[0] = "<permission>  protectionLevel specifies a non-instant flag but is "
-                        + "not based on signature type";
-                return null;
-            }
-        }
-
-        boolean success = parseAllMetaData(parsingPackage, res, parser,
-                "<permission>", result, outError);
-        if (!success || outError[0] != null) {
-            return null;
-        }
-
-        return result;
-    }
-
-    public static ParsedPermission parsePermissionTree(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = null;
-        String packageName = parsingPackage.getPackageName();
-        ParsedPermission result = new ParsedPermission();
-
-        try {
-            sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionTree);
-
-            String name = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestPermissionTree_name, 0);
-            if (name == null) {
-                outError[0] = "<permission-tree> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<permission-tree> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionTree_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermissionTree_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermissionTree_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        int index = result.getName().indexOf('.');
-        if (index > 0) {
-            index = result.getName().indexOf('.', index + 1);
-        }
-        if (index < 0) {
-            outError[0] =
-                    "<permission-tree> name has less than three segments: " + result.getName();
-            return null;
-        }
-
-        result.descriptionRes = 0;
-        result.requestRes = 0;
-        result.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
-        result.tree = true;
-
-        boolean success = parseAllMetaData(parsingPackage, res, parser,
-                "<permission-tree>", result, outError);
-        if (!success || outError[0] != null) {
-            return null;
-        }
-
-        return result;
-    }
-
-    public static ParsedPermissionGroup parsePermissionGroup(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = null;
-        String packageName = parsingPackage.getPackageName();
-        ParsedPermissionGroup result = new ParsedPermissionGroup();
-
-        try {
-            sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionGroup);
-
-            String name = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestPermissionGroup_name, 0);
-            if (name == null) {
-                outError[0] = "<permission> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<permission> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionGroup_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestPermissionGroup_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            result.descriptionRes = sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionGroup_description, 0);
-
-            result.requestDetailResourceId = sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
-            result.backgroundRequestResourceId = sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionGroup_backgroundRequest,
-                    0);
-            result.backgroundRequestDetailResourceId = sa.getResourceId(
-                    R.styleable
-                            .AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
-
-            result.requestRes = sa.getResourceId(
-                    R.styleable.AndroidManifestPermissionGroup_request, 0);
-            result.flags = sa.getInt(
-                    R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags,
-                    0);
-            result.priority = sa.getInt(
-                    R.styleable.AndroidManifestPermissionGroup_priority, 0);
-
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        boolean success = parseAllMetaData(parsingPackage, res, parser,
-                "<permission-group>", result, outError);
-        if (!success || outError[0] != null) {
-            return null;
-        }
-
-        return result;
-    }
-
-    public static ParsedInstrumentation parseInstrumentation(
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = null;
-        String packageName = parsingPackage.getPackageName();
-        ParsedInstrumentation result = new ParsedInstrumentation();
-
-        try {
-            sa = res.obtainAttributes(parser, R.styleable.AndroidManifestInstrumentation);
-
-            // TODO(b/135203078): Re-share all of the configuration for this. ParseComponentArgs was
-            //  un-used for this, but can be adjusted and re-added to share all the initial result
-            //  parsing for icon/logo/name/etc in all of these parse methods.
-            String name = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestInstrumentation_name, 0);
-            if (name == null) {
-                outError[0] = "<instrumentation> does not specify android:name";
-                return null;
-            } else {
-                String className = ApkParseUtils.buildClassName(packageName, name);
-                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
-                    outError[0] = "<instrumentation> invalid android:name";
-                    return null;
-                } else if (className == null) {
-                    outError[0] = "Empty class name in package " + packageName;
-                    return null;
-                }
-
-                result.className = className;
-            }
-
-            int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                    R.styleable.AndroidManifestInstrumentation_roundIcon, 0) : 0;
-            if (roundIconVal != 0) {
-                result.icon = roundIconVal;
-                result.nonLocalizedLabel = null;
-            } else {
-                int iconVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_icon, 0);
-                if (iconVal != 0) {
-                    result.icon = iconVal;
-                    result.nonLocalizedLabel = null;
-                }
-            }
-
-            int logoVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_logo, 0);
-            if (logoVal != 0) {
-                result.logo = logoVal;
-            }
-
-            int bannerVal = sa.getResourceId(R.styleable.AndroidManifestInstrumentation_banner, 0);
-            if (bannerVal != 0) {
-                result.banner = bannerVal;
-            }
-
-            TypedValue v = sa.peekValue(R.styleable.AndroidManifestInstrumentation_label);
-            if (v != null && (result.labelRes = v.resourceId) == 0) {
-                result.nonLocalizedLabel = v.coerceToString();
-            }
-
-            result.setPackageNameInternal(packageName);
-
-            String str;
-            // Note: don't allow this value to be a reference to a resource
-            // that may change.
-            str = sa.getNonResourceString(R.styleable.AndroidManifestInstrumentation_targetPackage);
-            result.setTargetPackage(str);
-
-            str = sa.getNonResourceString(
-                    R.styleable.AndroidManifestInstrumentation_targetProcesses);
-            result.setTargetProcesses(str);
-            result.handleProfiling = sa.getBoolean(
-                    R.styleable.AndroidManifestInstrumentation_handleProfiling, false);
-            result.functionalTest = sa.getBoolean(
-                    R.styleable.AndroidManifestInstrumentation_functionalTest, false);
-
-        } finally {
-            if (sa != null) {
-                sa.recycle();
-            }
-        }
-
-        boolean success = parseAllMetaData(parsingPackage, res, parser,
-                "<instrumentation>", result, outError);
-        if (!success || outError[0] != null) {
-            return null;
-        }
-
-        return result;
-    }
-
-    private static @Nullable ArraySet<String> parseDenyPermission(
-            ArraySet<String> perms,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestDenyPermission);
-        if (sa == null) {
-            outError[0] = "<deny-permission> could not be parsed";
-            return null;
-        }
-
-        try {
-            String perm = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestDenyPermission_name,0);
-            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)) {
-                if (perms == null) {
-                    perms = new ArraySet<>();
-                }
-                perms.add(perm);
-            }
-        } finally {
-            sa.recycle();
-        }
-        XmlUtils.skipCurrentTag(parser);
-        return perms;
-    }
-
-    private static ArraySet<String> parseAllowPermission(
-            ArraySet<String> perms,
-            Resources res,
-            XmlResourceParser parser,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestAllowPermission);
-        if (sa == null) {
-            outError[0] = "<allow-permission> could not be parsed";
-            return null;
-        }
-
-        try {
-            String perm = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestAllowPermission_name,0);
-            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)
-                    && perms != null) {
-                perms.remove(perm);
-                if (perms.size() <= 0) {
-                    perms = null;
-                }
-            }
-        } finally {
-            sa.recycle();
-        }
-        XmlUtils.skipCurrentTag(parser);
-        return perms;
-    }
-
-    public static ParsedProcess parseProcess(
-            ArraySet<String> perms,
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            int flags,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProcess);
-        if (sa == null) {
-            outError[0] = "<process> could not be parsed";
-            return null;
-        }
-
-        ParsedProcess proc = new ParsedProcess();
-        if (perms != null) {
-            proc.deniedPermissions = new ArraySet(perms);
-        }
-
-        try {
-            proc.name = sa.getNonConfigurationString(
-                    R.styleable.AndroidManifestProcess_process,0);
-            proc.name = PackageParser.buildProcessName(parsingPackage.getPackageName(),
-                    parsingPackage.getPackageName(), proc.name, flags, separateProcesses, outError);
-            if (outError[0] != null) {
-                return null;
-            }
-            if (proc.name == null || proc.name.length() <= 0) {
-                outError[0] = "<process> does not specify android:process";
-                return null;
-            }
-        } finally {
-            sa.recycle();
-        }
-
-        int type;
-        final int innerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("deny-permission")) {
-                proc.deniedPermissions = parseDenyPermission(proc.deniedPermissions, res, parser,
-                        outError);
-                if (outError[0] != null) {
-                    return null;
-                }
-            } else if (tagName.equals("allow-permission")) {
-                proc.deniedPermissions = parseAllowPermission(proc.deniedPermissions, res, parser,
-                        outError);
-                if (outError[0] != null) {
-                    return null;
-                }
-            } else {
-                Slog.w(TAG, "Unknown element under <process>: " + tagName
-                        + " at " + parsingPackage.getBaseCodePath() + " "
-                        + parser.getPositionDescription());
-                XmlUtils.skipCurrentTag(parser);
-                continue;
-            }
-        }
-
-        return proc;
-    }
-
-    public static ArrayMap<String, ParsedProcess> parseProcesses(
-            String[] separateProcesses,
-            ParsingPackage parsingPackage,
-            Resources res,
-            XmlResourceParser parser,
-            int flags,
-            String[] outError
-    ) throws IOException, XmlPullParserException {
-        ArraySet<String> deniedPerms = null;
-        ArrayMap<String, ParsedProcess> processes = new ArrayMap<>();
-
-        int type;
-        final int innerDepth = parser.getDepth();
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String tagName = parser.getName();
-            if (tagName.equals("deny-permission")) {
-                deniedPerms = parseDenyPermission(deniedPerms, res, parser, outError);
-                if (outError[0] != null) {
-                    return null;
-                }
-            } else if (tagName.equals("allow-permission")) {
-                deniedPerms = parseAllowPermission(deniedPerms, res, parser, outError);
-                if (outError[0] != null) {
-                    return null;
-                }
-            } else if (tagName.equals("process")) {
-                ParsedProcess proc = parseProcess(deniedPerms, separateProcesses, parsingPackage,
-                        res, parser, flags, outError);
-                if (outError[0] != null) {
-                    return null;
-                }
-                if (processes.get(proc.name) != null) {
-                    outError[0] = "<process> specified existing name '" + proc.name + "'";
-                    return null;
-                }
-                processes.put(proc.name, proc);
-            } else {
-                Slog.w(TAG, "Unknown element under <processes>: " + tagName
-                        + " at " + parsingPackage.getBaseCodePath() + " "
-                        + parser.getPositionDescription());
-                XmlUtils.skipCurrentTag(parser);
-                continue;
-            }
-        }
-
-        return processes;
-    }
-
-    public static ActivityInfo.WindowLayout parseLayout(Resources res, AttributeSet attrs) {
-        TypedArray sw = res.obtainAttributes(attrs,
-                R.styleable.AndroidManifestLayout);
-        int width = -1;
-        float widthFraction = -1f;
-        int height = -1;
-        float heightFraction = -1f;
-        final int widthType = sw.getType(
-                R.styleable.AndroidManifestLayout_defaultWidth);
-        if (widthType == TypedValue.TYPE_FRACTION) {
-            widthFraction = sw.getFraction(
-                    R.styleable.AndroidManifestLayout_defaultWidth,
-                    1, 1, -1);
-        } else if (widthType == TypedValue.TYPE_DIMENSION) {
-            width = sw.getDimensionPixelSize(
-                    R.styleable.AndroidManifestLayout_defaultWidth,
-                    -1);
-        }
-        final int heightType = sw.getType(
-                R.styleable.AndroidManifestLayout_defaultHeight);
-        if (heightType == TypedValue.TYPE_FRACTION) {
-            heightFraction = sw.getFraction(
-                    R.styleable.AndroidManifestLayout_defaultHeight,
-                    1, 1, -1);
-        } else if (heightType == TypedValue.TYPE_DIMENSION) {
-            height = sw.getDimensionPixelSize(
-                    R.styleable.AndroidManifestLayout_defaultHeight,
-                    -1);
-        }
-        int gravity = sw.getInt(
-                R.styleable.AndroidManifestLayout_gravity,
-                Gravity.CENTER);
-        int minWidth = sw.getDimensionPixelSize(
-                R.styleable.AndroidManifestLayout_minWidth,
-                -1);
-        int minHeight = sw.getDimensionPixelSize(
-                R.styleable.AndroidManifestLayout_minHeight,
-                -1);
-        sw.recycle();
-        return new ActivityInfo.WindowLayout(width, widthFraction,
-                height, heightFraction, gravity, minWidth, minHeight);
-    }
-
-    public static boolean parseIntentInfo(
-            ParsedIntentInfo intentInfo,
-            ParsingPackage parsingPackage,
-            Resources res, XmlResourceParser parser, boolean allowGlobs,
-            boolean allowAutoVerify, String[] outError
-    ) throws XmlPullParserException, IOException {
-        TypedArray sa = res.obtainAttributes(parser,
-                R.styleable.AndroidManifestIntentFilter);
-
-        int priority = sa.getInt(
-                R.styleable.AndroidManifestIntentFilter_priority, 0);
-        intentInfo.setPriority(priority);
-
-        int order = sa.getInt(
-                R.styleable.AndroidManifestIntentFilter_order, 0);
-        intentInfo.setOrder(order);
-
-        TypedValue v = sa.peekValue(
-                R.styleable.AndroidManifestIntentFilter_label);
-        if (v != null && (intentInfo.labelRes = v.resourceId) == 0) {
-            intentInfo.nonLocalizedLabel = v.coerceToString();
-        }
-
-        int roundIconVal = PackageParser.sUseRoundIcon ? sa.getResourceId(
-                R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
-        if (roundIconVal != 0) {
-            intentInfo.icon = roundIconVal;
-        } else {
-            intentInfo.icon = sa.getResourceId(
-                    R.styleable.AndroidManifestIntentFilter_icon, 0);
-        }
-
-        if (allowAutoVerify) {
-            intentInfo.setAutoVerify(sa.getBoolean(
-                    R.styleable.AndroidManifestIntentFilter_autoVerify,
-                    false));
-        }
-
-        sa.recycle();
-
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            String nodeName = parser.getName();
-            if (nodeName.equals("action")) {
-                String value = parser.getAttributeValue(
-                        PackageParser.ANDROID_RESOURCES, "name");
-                if (TextUtils.isEmpty(value)) {
-                    outError[0] = "No value supplied for <android:name>";
-                    return false;
-                }
-                XmlUtils.skipCurrentTag(parser);
-
-                intentInfo.addAction(value);
-            } else if (nodeName.equals("category")) {
-                String value = parser.getAttributeValue(
-                        PackageParser.ANDROID_RESOURCES, "name");
-                if (TextUtils.isEmpty(value)) {
-                    outError[0] = "No value supplied for <android:name>";
-                    return false;
-                }
-                XmlUtils.skipCurrentTag(parser);
-
-                intentInfo.addCategory(value);
-
-            } else if (nodeName.equals("data")) {
-                sa = res.obtainAttributes(parser,
-                        R.styleable.AndroidManifestData);
-
-                String str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_mimeType, 0);
-                if (str != null) {
-                    try {
-                        intentInfo.addRawDataType(str);
-                    } catch (IntentFilter.MalformedMimeTypeException e) {
-                        outError[0] = e.toString();
-                        sa.recycle();
-                        return false;
-                    }
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_scheme, 0);
-                if (str != null) {
-                    intentInfo.addDataScheme(str);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_ssp, 0);
-                if (str != null) {
-                    intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_LITERAL);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_sspPrefix, 0);
-                if (str != null) {
-                    intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_PREFIX);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_sspPattern, 0);
-                if (str != null) {
-                    if (!allowGlobs) {
-                        outError[0] = "sspPattern not allowed here; ssp must be literal";
-                        return false;
-                    }
-                    intentInfo.addDataSchemeSpecificPart(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
-                }
-
-                String host = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_host, 0);
-                String port = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_port, 0);
-                if (host != null) {
-                    intentInfo.addDataAuthority(host, port);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_path, 0);
-                if (str != null) {
-                    intentInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_pathPrefix, 0);
-                if (str != null) {
-                    intentInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_pathPattern, 0);
-                if (str != null) {
-                    if (!allowGlobs) {
-                        outError[0] = "pathPattern not allowed here; path must be literal";
-                        return false;
-                    }
-                    intentInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
-                }
-
-                str = sa.getNonConfigurationString(
-                        R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
-                if (str != null) {
-                    if (!allowGlobs) {
-                        outError[0] = "pathAdvancedPattern not allowed here; path must be literal";
-                        return false;
-                    }
-                    intentInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
-                }
-
-                sa.recycle();
-                XmlUtils.skipCurrentTag(parser);
-            } else if (!PackageParser.RIGID_PARSER) {
-                Slog.w(TAG, "Unknown element under <intent-filter>: "
-                        + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " "
-                        + parser.getPositionDescription());
-                XmlUtils.skipCurrentTag(parser);
-            } else {
-                outError[0] = "Bad element under <intent-filter>: " + parser.getName();
-                return false;
-            }
-        }
-
-        intentInfo.hasDefault = intentInfo.hasCategory(Intent.CATEGORY_DEFAULT);
-
-        if (PackageParser.DEBUG_PARSER) {
-            final StringBuilder cats = new StringBuilder("Intent d=");
-            cats.append(intentInfo.hasDefault);
-            cats.append(", cat=");
-
-            final Iterator<String> it = intentInfo.categoriesIterator();
-            if (it != null) {
-                while (it.hasNext()) {
-                    cats.append(' ');
-                    cats.append(it.next());
-                }
-            }
-            Slog.d(TAG, cats.toString());
-        }
-
-        return true;
-    }
-
-    private static boolean parseAllMetaData(
-            ParsingPackage parsingPackage,
-            Resources res, XmlResourceParser parser, String tag,
-            ParsedComponent outInfo,
-            String[] outError
-    ) throws XmlPullParserException, IOException {
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
-                && (type != XmlPullParser.END_TAG
-                || parser.getDepth() > outerDepth)) {
-            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
-                continue;
-            }
-
-            if (parser.getName().equals("meta-data")) {
-                if ((outInfo.metaData = ApkParseUtils.parseMetaData(parsingPackage, res, parser,
-                        outInfo.metaData, outError)) == null) {
-                    return false;
-                }
-            } else {
-                if (!PackageParser.RIGID_PARSER) {
-                    Slog.w(TAG, "Unknown element under " + tag + ": "
-                            + parser.getName() + " at " + parsingPackage.getBaseCodePath() + " "
-                            + parser.getPositionDescription());
-                    XmlUtils.skipCurrentTag(parser);
-                    continue;
-                } else {
-                    outError[0] = "Bad element under " + tag + ": " + parser.getName();
-                }
-            }
-        }
-
-        return true;
-    }
-
-    public static boolean isImplicitlyExposedIntent(IntentFilter intent) {
-        return intent.hasCategory(Intent.CATEGORY_BROWSABLE)
-                || intent.hasAction(Intent.ACTION_SEND)
-                || intent.hasAction(Intent.ACTION_SENDTO)
-                || intent.hasAction(Intent.ACTION_SEND_MULTIPLE);
-    }
-}
diff --git a/core/java/android/content/pm/parsing/PackageImpl.java b/core/java/android/content/pm/parsing/PackageImpl.java
deleted file mode 100644
index 180714a..0000000
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ /dev/null
@@ -1,3353 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package android.content.pm.parsing;
-
-import static android.os.Build.VERSION_CODES.DONUT;
-
-import static java.util.Collections.emptyMap;
-
-import android.annotation.NonNull;
-import android.annotation.Nullable;
-import android.content.Intent;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.ProviderInfo;
-import android.content.pm.ServiceInfo;
-import android.content.pm.SharedLibraryInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
-import android.content.res.TypedArray;
-import android.os.Build;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.Parcel;
-import android.os.UserHandle;
-import android.os.storage.StorageManager;
-import android.text.TextUtils;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.SparseArray;
-
-import com.android.internal.R;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-import com.android.internal.util.CollectionUtils;
-import com.android.server.SystemConfig;
-
-import java.security.PublicKey;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.UUID;
-
-/**
- * The backing data for a package that was parsed from disk.
- *
- * TODO(b/135203078): Convert Lists used as sets into Sets, to better express intended use case
- * TODO(b/135203078): Field nullability annotations
- * TODO(b/135203078): Convert = 1 fields into Booleans
- * TODO(b/135203078): Make all lists nullable and Collections.unmodifiable immutable when returned.
- *   Prefer add/set methods if adding is necessary.
- * TODO(b/135203078): Consider comments to disable auto-format and single-line, single-space all the
- *   get/set methods to make this class far more compact. Maybe even separate some logic into parent
- *   classes, assuming there is no overhead.
- * TODO(b/135203078): Copy documentation from PackageParser#Package for the relevant fields included
- *   here. Should clarify and clean up any differences. Also consider renames if it helps make
- *   things clearer.
- * TODO(b/135203078): Intern all possibl e String values? Initial refactor just mirrored old
- *   behavior.
- *
- * @hide
- */
-public final class PackageImpl implements ParsingPackage, ParsedPackage, AndroidPackage,
-        AndroidPackageWrite {
-
-    private static final String TAG = "PackageImpl";
-
-    // Resource boolean are -1, so 1 means we don't know the value.
-    private int supportsSmallScreens = 1;
-    private int supportsNormalScreens = 1;
-    private int supportsLargeScreens = 1;
-    private int supportsXLargeScreens = 1;
-    private int resizeable = 1;
-    private int anyDensity = 1;
-
-    private long[] lastPackageUsageTimeInMills =
-            new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
-
-    private int versionCode;
-    private int versionCodeMajor;
-    private int baseRevisionCode;
-    private String versionName;
-
-    private boolean coreApp;
-    private int compileSdkVersion;
-    private String compileSdkVersionCodename;
-
-    private String packageName;
-    private String realPackage;
-    private String manifestPackageName;
-    private String baseCodePath;
-
-    private boolean requiredForAllUsers;
-    private String restrictedAccountType;
-    private String requiredAccountType;
-
-    private boolean baseHardwareAccelerated;
-
-    private String overlayTarget;
-    private String overlayTargetName;
-    private String overlayCategory;
-    private int overlayPriority;
-    private boolean overlayIsStatic;
-    private Map<String, String> overlayables = emptyMap();
-
-    private String staticSharedLibName;
-    private long staticSharedLibVersion;
-    private ArrayList<String> libraryNames;
-    private ArrayList<String> usesLibraries;
-    private ArrayList<String> usesOptionalLibraries;
-
-    private ArrayList<String> usesStaticLibraries;
-    private long[] usesStaticLibrariesVersions;
-    private String[][] usesStaticLibrariesCertDigests;
-
-    private String sharedUserId;
-
-    private int sharedUserLabel;
-    private ArrayList<ConfigurationInfo> configPreferences;
-    private ArrayList<FeatureInfo> reqFeatures;
-    private ArrayList<FeatureGroupInfo> featureGroups;
-
-    private byte[] restrictUpdateHash;
-
-    private ArrayList<String> originalPackages;
-    private ArrayList<String> adoptPermissions;
-
-    private ArrayList<String> requestedPermissions;
-    private ArrayList<String> implicitPermissions;
-
-    private ArraySet<String> upgradeKeySets;
-    private Map<String, ArraySet<PublicKey>> keySetMapping;
-
-    private ArrayList<String> protectedBroadcasts;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedActivity> activities;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedActivity> receivers;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedService> services;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedProvider> providers;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedFeature> features;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedPermission> permissions;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedPermissionGroup> permissionGroups;
-
-    @Nullable
-    private ArrayList<ComponentParseUtils.ParsedInstrumentation> instrumentations;
-
-    private ArrayList<ParsedActivityIntentInfo> preferredActivityFilters;
-
-    private Bundle appMetaData;
-
-    private String volumeUuid;
-    private String applicationVolumeUuid;
-    private PackageParser.SigningDetails signingDetails;
-
-    private String codePath;
-
-    private boolean use32BitAbi;
-    private boolean visibleToInstantApps;
-
-    private String cpuAbiOverride;
-
-    private boolean isStub;
-
-    // TODO(b/135203078): Remove, should be unused
-    private int preferredOrder;
-
-    private boolean forceQueryable;
-
-    @Nullable
-    private ArrayList<Intent> queriesIntents;
-
-    @Nullable
-    private ArrayList<String> queriesPackages;
-
-    @Nullable
-    private ArraySet<String> queriesProviders;
-
-    @Nullable
-    private ArrayMap<String, ComponentParseUtils.ParsedProcess> processes;
-
-    private String[] splitClassLoaderNames;
-    private String[] splitCodePaths;
-    private SparseArray<int[]> splitDependencies;
-    private int[] splitFlags;
-    private String[] splitNames;
-    private int[] splitRevisionCodes;
-
-    // TODO(b/135203078): Audit applicationInfo.something usages, which may be different from
-    //  package.something usages. There were differing cases of package.field = versus
-    //  package.appInfo.field =. This class assumes some obvious ones, like packageName,
-    //  were collapsible, but kept the following separate.
-
-    private String applicationInfoBaseResourcePath;
-    private String applicationInfoCodePath;
-    private String applicationInfoResourcePath;
-    private String[] applicationInfoSplitResourcePaths;
-
-    private String appComponentFactory;
-    private String backupAgentName;
-    private int banner;
-    private int category;
-    private String classLoaderName;
-    private String className;
-    private int compatibleWidthLimitDp;
-    private String credentialProtectedDataDir;
-    private String dataDir;
-    private int descriptionRes;
-    private String deviceProtectedDataDir;
-    private boolean enabled;
-    private boolean crossProfile;
-    private int flags;
-    private int fullBackupContent;
-    private boolean hiddenUntilInstalled;
-    private int icon;
-    private int iconRes;
-    private int installLocation = PackageParser.PARSE_DEFAULT_INSTALL_LOCATION;
-    private int labelRes;
-    private int largestWidthLimitDp;
-    private int logo;
-    private String manageSpaceActivityName;
-    private float maxAspectRatio;
-    private float minAspectRatio;
-    private int minSdkVersion;
-    private String name;
-    private String nativeLibraryDir;
-    private String nativeLibraryRootDir;
-    private boolean nativeLibraryRootRequiresIsa;
-    private int networkSecurityConfigRes;
-    private CharSequence nonLocalizedLabel;
-    private String permission;
-    private String primaryCpuAbi;
-    private int privateFlags;
-    private String processName;
-    private int requiresSmallestWidthDp;
-    private int roundIconRes;
-    private String secondaryCpuAbi;
-    private String secondaryNativeLibraryDir;
-    private String seInfo;
-    private String seInfoUser;
-    private int targetSandboxVersion;
-    private int targetSdkVersion;
-    private String taskAffinity;
-    private int theme;
-    private int uid = -1;
-    private int uiOptions;
-    private String[] usesLibraryFiles;
-    private List<SharedLibraryInfo> usesLibraryInfos;
-    private String zygotePreloadName;
-    private boolean preserveLegacyExternalStorage;
-
-    @VisibleForTesting
-    public PackageImpl(
-            String packageName,
-            String baseCodePath,
-            TypedArray manifestArray,
-            boolean isCoreApp
-    ) {
-        this.packageName = TextUtils.safeIntern(packageName);
-        this.manifestPackageName = this.packageName;
-        this.baseCodePath = baseCodePath;
-
-        this.versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0);
-        this.versionCodeMajor = manifestArray.getInteger(
-                R.styleable.AndroidManifest_versionCodeMajor, 0);
-        this.baseRevisionCode = manifestArray.getInteger(R.styleable.AndroidManifest_revisionCode,
-                0);
-        setVersionName(manifestArray.getNonConfigurationString(
-                R.styleable.AndroidManifest_versionName, 0));
-        this.coreApp = isCoreApp;
-
-        this.compileSdkVersion = manifestArray.getInteger(
-                R.styleable.AndroidManifest_compileSdkVersion, 0);
-        setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
-                R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
-    }
-
-    private PackageImpl(String packageName) {
-        this.packageName = TextUtils.safeIntern(packageName);
-        this.manifestPackageName = this.packageName;
-    }
-
-    @VisibleForTesting
-    public static ParsingPackage forParsing(String packageName) {
-        return new PackageImpl(packageName);
-    }
-
-    @VisibleForTesting
-    public static ParsingPackage forParsing(
-            String packageName,
-            String baseCodePath,
-            TypedArray manifestArray,
-            boolean isCoreApp) {
-        return new PackageImpl(packageName, baseCodePath, manifestArray, isCoreApp);
-    }
-
-    /**
-     * Mock an unavailable {@link AndroidPackage} to use when removing a package from the system.
-     * This can occur if the package was installed on a storage device that has since been removed.
-     * Since the infrastructure uses {@link AndroidPackage}, but for this case only cares about
-     * volumeUuid, just fake it rather than having separate method paths.
-     */
-    public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
-        return new PackageImpl(packageName)
-                .setVolumeUuid(volumeUuid)
-                .hideAsParsed()
-                .hideAsFinal();
-    }
-
-    @Override
-    public ParsedPackage hideAsParsed() {
-        return this;
-    }
-
-    @Override
-    public AndroidPackage hideAsFinal() {
-        updateFlags();
-        return this;
-    }
-
-    @Override
-    @Deprecated
-    public AndroidPackageWrite mutate() {
-        return this;
-    }
-
-    private void updateFlags() {
-        if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            this.flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
-        }
-        if (supportsNormalScreens != 0) {
-            this.flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
-        }
-        if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            this.flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
-        }
-        if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.GINGERBREAD)) {
-            this.flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
-        }
-        if (resizeable < 0 || (resizeable > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            this.flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
-        }
-        if (anyDensity < 0 || (anyDensity > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            this.flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
-        }
-    }
-
-    @Override
-    public boolean usesCompatibilityMode() {
-        int flags = 0;
-
-        if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            flags |= ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS;
-        }
-        if (supportsNormalScreens != 0) {
-            flags |= ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS;
-        }
-        if (supportsLargeScreens < 0 || (supportsLargeScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            flags |= ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS;
-        }
-        if (supportsXLargeScreens < 0 || (supportsXLargeScreens > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.GINGERBREAD)) {
-            flags |= ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS;
-        }
-        if (resizeable < 0 || (resizeable > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            flags |= ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS;
-        }
-        if (anyDensity < 0 || (anyDensity > 0
-                && targetSdkVersion
-                >= Build.VERSION_CODES.DONUT)) {
-            flags |= ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES;
-        }
-
-        return targetSdkVersion < DONUT
-                || (flags & (ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS
-                        | ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS
-                        | ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS
-                        | ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS
-                        | ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES
-                        | ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)) == 0;
-    }
-
-    @Override
-    public String getBaseCodePath() {
-        return baseCodePath;
-    }
-
-    @Override
-    public int getTargetSdkVersion() {
-        return targetSdkVersion;
-    }
-
-    @Override
-    public String getPackageName() {
-        return packageName;
-    }
-
-    @Override
-    public String getProcessName() {
-        return processName;
-    }
-
-    @Override
-    public String getPermission() {
-        return permission;
-    }
-
-    @Override
-    public String getStaticSharedLibName() {
-        return staticSharedLibName;
-    }
-
-    @Override
-    public long getStaticSharedLibVersion() {
-        return staticSharedLibVersion;
-    }
-
-    @Override
-    public String getSharedUserId() {
-        return sharedUserId;
-    }
-
-    @Override
-    public List<String> getRequestedPermissions() {
-        return requestedPermissions == null ? Collections.emptyList() : requestedPermissions;
-    }
-
-    @Nullable
-    @Override
-    public List<ParsedInstrumentation> getInstrumentations() {
-        return instrumentations;
-    }
-
-    @Override
-    public Map<String, ArraySet<PublicKey>> getKeySetMapping() {
-        return keySetMapping == null ? emptyMap() : keySetMapping;
-    }
-
-    @Override
-    public float getMaxAspectRatio() {
-        return maxAspectRatio;
-    }
-
-    @Override
-    public float getMinAspectRatio() {
-        return minAspectRatio;
-    }
-
-    @NonNull
-    @Override
-    public List<String> getLibraryNames() {
-        return libraryNames == null ? Collections.emptyList() : libraryNames;
-    }
-
-    @Override
-    public List<ParsedActivity> getActivities() {
-        return activities == null ? Collections.emptyList()
-                : activities;
-    }
-
-    @Override
-    public Bundle getAppMetaData() {
-        return appMetaData;
-    }
-
-    @Nullable
-    @Override
-    public List<String> getUsesLibraries() {
-        return usesLibraries;
-    }
-
-    @Nullable
-    @Override
-    public List<String> getUsesStaticLibraries() {
-        return usesStaticLibraries;
-    }
-
-    @Nullable
-    @Override
-    public ArrayMap<String, ComponentParseUtils.ParsedProcess> getProcesses() {
-        return processes;
-    }
-
-    @Override
-    public boolean isBaseHardwareAccelerated() {
-        return baseHardwareAccelerated;
-    }
-
-    @Override
-    public int getUiOptions() {
-        return uiOptions;
-    }
-
-    // TODO(b/135203078): Checking flags directly can be error prone,
-    //  consider separate interface methods?
-    @Override
-    public int getFlags() {
-        return flags;
-    }
-
-    // TODO(b/135203078): Checking flags directly can be error prone,
-    //  consider separate interface methods?
-    @Override
-    public int getPrivateFlags() {
-        return privateFlags;
-    }
-
-    @Override
-    public String getTaskAffinity() {
-        return taskAffinity;
-    }
-
-    @Nullable
-    @Override
-    public List<String> getOriginalPackages() {
-        return originalPackages;
-    }
-
-    @Override
-    public PackageParser.SigningDetails getSigningDetails() {
-        return signingDetails;
-    }
-
-    @Override
-    public String getVolumeUuid() {
-        return volumeUuid;
-    }
-
-    @Nullable
-    @Override
-    public List<ParsedPermissionGroup> getPermissionGroups() {
-        return permissionGroups;
-    }
-
-    @Nullable
-    @Override
-    public List<ParsedPermission> getPermissions() {
-        return permissions;
-    }
-
-    @Nullable
-    @Override
-    public List<ParsedFeature> getFeatures() {
-        return features;
-    }
-
-    @Override
-    public String getCpuAbiOverride() {
-        return cpuAbiOverride;
-    }
-
-    @Override
-    public String getPrimaryCpuAbi() {
-        return primaryCpuAbi;
-    }
-
-    @Override
-    public String getSecondaryCpuAbi() {
-        return secondaryCpuAbi;
-    }
-
-    @Override
-    public boolean isUse32BitAbi() {
-        return use32BitAbi;
-    }
-
-    @Override
-    public boolean isForceQueryable() {
-        return forceQueryable;
-    }
-
-    @Override
-    public String getCodePath() {
-        return codePath;
-    }
-
-    @Override
-    public String getNativeLibraryDir() {
-        return nativeLibraryDir;
-    }
-
-    @Override
-    public String getNativeLibraryRootDir() {
-        return nativeLibraryRootDir;
-    }
-
-    @Override
-    public boolean isNativeLibraryRootRequiresIsa() {
-        return nativeLibraryRootRequiresIsa;
-    }
-
-    // TODO(b/135203078): Does nothing, remove?
-    @Override
-    public int getPreferredOrder() {
-        return preferredOrder;
-    }
-
-    @Override
-    public long getLongVersionCode() {
-        return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
-    }
-
-    @Override
-    public PackageImpl setIsOverlay(boolean isOverlay) {
-        this.privateFlags = isOverlay
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setExternalStorage(boolean externalStorage) {
-        this.flags = externalStorage
-                ? this.flags | ApplicationInfo.FLAG_EXTERNAL_STORAGE
-                : this.flags & ~ApplicationInfo.FLAG_EXTERNAL_STORAGE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setIsolatedSplitLoading(boolean isolatedSplitLoading) {
-        this.privateFlags = isolatedSplitLoading
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING;
-        return this;
-    }
-
-    @Override
-    public PackageImpl sortActivities() {
-        Collections.sort(this.activities, (a1, a2) -> Integer.compare(a2.order, a1.order));
-        return this;
-    }
-
-    @Override
-    public PackageImpl sortReceivers() {
-        Collections.sort(this.receivers, (a1, a2) -> Integer.compare(a2.order, a1.order));
-        return this;
-    }
-
-    @Override
-    public PackageImpl sortServices() {
-        Collections.sort(this.services, (a1, a2) -> Integer.compare(a2.order, a1.order));
-        return this;
-    }
-
-    @Override
-    public PackageImpl setBaseRevisionCode(int baseRevisionCode) {
-        this.baseRevisionCode = baseRevisionCode;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setPreferredOrder(int preferredOrder) {
-        this.preferredOrder = preferredOrder;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setVersionName(String versionName) {
-        this.versionName = TextUtils.safeIntern(versionName);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage setCompileSdkVersion(int compileSdkVersion) {
-        this.compileSdkVersion = compileSdkVersion;
-        return this;
-    }
-
-    @Override
-    public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
-        this.compileSdkVersionCodename = TextUtils.safeIntern(compileSdkVersionCodename);
-        return this;
-    }
-
-    @Override
-    public PackageImpl setMaxAspectRatio(float maxAspectRatio) {
-        this.maxAspectRatio = maxAspectRatio;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setMinAspectRatio(float minAspectRatio) {
-        this.minAspectRatio = minAspectRatio;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setMinSdkVersion(int minSdkVersion) {
-        this.minSdkVersion = minSdkVersion;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setTargetSdkVersion(int targetSdkVersion) {
-        this.targetSdkVersion = targetSdkVersion;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRealPackage(String realPackage) {
-        this.realPackage = realPackage;
-        return this;
-    }
-
-    @Override
-    public PackageImpl addConfigPreference(ConfigurationInfo configPreference) {
-        this.configPreferences = ArrayUtils.add(this.configPreferences, configPreference);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addReqFeature(FeatureInfo reqFeature) {
-        this.reqFeatures = ArrayUtils.add(this.reqFeatures, reqFeature);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addFeatureGroup(FeatureGroupInfo featureGroup) {
-        this.featureGroups = ArrayUtils.add(this.featureGroups, featureGroup);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addProtectedBroadcast(String protectedBroadcast) {
-        if (this.protectedBroadcasts == null
-                || !this.protectedBroadcasts.contains(protectedBroadcast)) {
-            this.protectedBroadcasts = ArrayUtils.add(this.protectedBroadcasts,
-                    TextUtils.safeIntern(protectedBroadcast));
-        }
-        return this;
-    }
-
-    @Override
-    public PackageImpl addInstrumentation(ParsedInstrumentation instrumentation) {
-        this.instrumentations = ArrayUtils.add(this.instrumentations, instrumentation);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addOriginalPackage(String originalPackage) {
-        this.originalPackages = ArrayUtils.add(this.originalPackages, originalPackage);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addOverlayable(String overlayableName, String actorName) {
-        this.overlayables = CollectionUtils.add(this.overlayables,
-                TextUtils.safeIntern(overlayableName), TextUtils.safeIntern(actorName));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addAdoptPermission(String adoptPermission) {
-        this.adoptPermissions = ArrayUtils.add(this.adoptPermissions, adoptPermission);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addFeature(ParsedFeature feature) {
-        this.features = ArrayUtils.add(this.features, feature);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addPermission(ParsedPermission permission) {
-        this.permissions = ArrayUtils.add(this.permissions, permission);
-        return this;
-    }
-
-    @Override
-    public PackageImpl removePermission(int index) {
-        this.permissions.remove(index);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addPermissionGroup(ParsedPermissionGroup permissionGroup) {
-        this.permissionGroups = ArrayUtils.add(this.permissionGroups, permissionGroup);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addRequestedPermission(String permission) {
-        this.requestedPermissions = ArrayUtils.add(this.requestedPermissions,
-                TextUtils.safeIntern(permission));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addImplicitPermission(String permission) {
-        this.implicitPermissions = ArrayUtils.add(this.implicitPermissions,
-                TextUtils.safeIntern(permission));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addKeySet(String keySetName, PublicKey publicKey) {
-        if (keySetMapping == null) {
-            keySetMapping = new ArrayMap<>();
-        }
-
-        ArraySet<PublicKey> publicKeys = keySetMapping.get(keySetName);
-        if (publicKeys == null) {
-            publicKeys = new ArraySet<>();
-            keySetMapping.put(keySetName, publicKeys);
-        }
-
-        publicKeys.add(publicKey);
-
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addActivity(ParsedActivity parsedActivity) {
-        this.activities = ArrayUtils.add(this.activities, parsedActivity);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addReceiver(ParsedActivity parsedReceiver) {
-        this.receivers = ArrayUtils.add(this.receivers, parsedReceiver);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addService(ParsedService parsedService) {
-        this.services = ArrayUtils.add(this.services, parsedService);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addProvider(ParsedProvider parsedProvider) {
-        this.providers = ArrayUtils.add(this.providers, parsedProvider);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addLibraryName(String libraryName) {
-        this.libraryNames = ArrayUtils.add(this.libraryNames, TextUtils.safeIntern(libraryName));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesLibrary(String libraryName) {
-        this.usesLibraries = ArrayUtils.add(this.usesLibraries, TextUtils.safeIntern(libraryName));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesOptionalLibrary(String libraryName) {
-        this.usesOptionalLibraries = ArrayUtils.add(this.usesOptionalLibraries,
-                TextUtils.safeIntern(libraryName));
-        return this;
-    }
-
-    @Override
-    public PackageImpl removeUsesOptionalLibrary(String libraryName) {
-        this.usesOptionalLibraries = ArrayUtils.remove(this.usesOptionalLibraries, libraryName);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesStaticLibrary(String libraryName) {
-        this.usesStaticLibraries = ArrayUtils.add(this.usesStaticLibraries,
-                TextUtils.safeIntern(libraryName));
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesStaticLibraryVersion(long version) {
-        this.usesStaticLibrariesVersions = ArrayUtils.appendLong(this.usesStaticLibrariesVersions,
-                version, true);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesStaticLibraryCertDigests(String[] certSha256Digests) {
-        this.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
-                this.usesStaticLibrariesCertDigests, certSha256Digests, true);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addPreferredActivityFilter(
-            ParsedActivityIntentInfo parsedActivityIntentInfo) {
-        this.preferredActivityFilters = ArrayUtils.add(this.preferredActivityFilters,
-                parsedActivityIntentInfo);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addQueriesIntent(Intent intent) {
-        this.queriesIntents = ArrayUtils.add(this.queriesIntents, intent);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addQueriesPackage(String packageName) {
-        this.queriesPackages = ArrayUtils.add(this.queriesPackages,
-                TextUtils.safeIntern(packageName));
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addQueriesProvider(String authority) {
-        this.queriesProviders = ArrayUtils.add(this.queriesProviders, authority);
-        return this;
-    }
-
-    @Override
-    public PackageImpl setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes) {
-        this.processes = processes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSupportsSmallScreens(int supportsSmallScreens) {
-        if (supportsSmallScreens == 1) {
-            return this;
-        }
-
-        this.supportsSmallScreens = supportsSmallScreens;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSupportsNormalScreens(int supportsNormalScreens) {
-        if (supportsNormalScreens == 1) {
-            return this;
-        }
-
-        this.supportsNormalScreens = supportsNormalScreens;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSupportsLargeScreens(int supportsLargeScreens) {
-        if (supportsLargeScreens == 1) {
-            return this;
-        }
-
-        this.supportsLargeScreens = supportsLargeScreens;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSupportsXLargeScreens(int supportsXLargeScreens) {
-        if (supportsXLargeScreens == 1) {
-            return this;
-        }
-
-        this.supportsXLargeScreens = supportsXLargeScreens;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setResizeable(int resizeable) {
-        if (resizeable == 1) {
-            return this;
-        }
-
-        this.resizeable = resizeable;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAnyDensity(int anyDensity) {
-        if (anyDensity == 1) {
-            return this;
-        }
-
-        this.anyDensity = anyDensity;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRequiresSmallestWidthDp(int requiresSmallestWidthDp) {
-        this.requiresSmallestWidthDp = requiresSmallestWidthDp;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCompatibleWidthLimitDp(int compatibleWidthLimitDp) {
-        this.compatibleWidthLimitDp = compatibleWidthLimitDp;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setLargestWidthLimitDp(int largestWidthLimitDp) {
-        this.largestWidthLimitDp = largestWidthLimitDp;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setInstallLocation(int installLocation) {
-        this.installLocation = installLocation;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setTargetSandboxVersion(int targetSandboxVersion) {
-        this.targetSandboxVersion = targetSandboxVersion;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRequiredForAllUsers(boolean requiredForAllUsers) {
-        this.requiredForAllUsers = requiredForAllUsers;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRestrictedAccountType(String restrictedAccountType) {
-        this.restrictedAccountType = restrictedAccountType;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRequiredAccountType(String requiredAccountType) {
-        this.requiredAccountType = requiredAccountType;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setBaseHardwareAccelerated(boolean baseHardwareAccelerated) {
-        this.baseHardwareAccelerated = baseHardwareAccelerated;
-
-        this.flags = baseHardwareAccelerated
-                ? this.flags | ApplicationInfo.FLAG_HARDWARE_ACCELERATED
-                : this.flags & ~ApplicationInfo.FLAG_HARDWARE_ACCELERATED;
-
-        return this;
-    }
-
-    @Override
-    public PackageImpl setHasDomainUrls(boolean hasDomainUrls) {
-        this.privateFlags = hasDomainUrls
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAppMetaData(Bundle appMetaData) {
-        this.appMetaData = appMetaData;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setOverlayTarget(String overlayTarget) {
-        this.overlayTarget = overlayTarget;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setOverlayTargetName(String overlayTargetName) {
-        this.overlayTargetName = overlayTargetName;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setOverlayCategory(String overlayCategory) {
-        this.overlayCategory = overlayCategory;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setOverlayPriority(int overlayPriority) {
-        this.overlayPriority = overlayPriority;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setOverlayIsStatic(boolean overlayIsStatic) {
-        this.overlayIsStatic = overlayIsStatic;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setStaticSharedLibName(String staticSharedLibName) {
-        this.staticSharedLibName = TextUtils.safeIntern(staticSharedLibName);
-        return this;
-    }
-
-    @Override
-    public PackageImpl setStaticSharedLibVersion(long staticSharedLibVersion) {
-        this.staticSharedLibVersion = staticSharedLibVersion;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSharedUserId(String sharedUserId) {
-        this.sharedUserId = TextUtils.safeIntern(sharedUserId);
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSharedUserLabel(int sharedUserLabel) {
-        this.sharedUserLabel = sharedUserLabel;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRestrictUpdateHash(byte[] restrictUpdateHash) {
-        this.restrictUpdateHash = restrictUpdateHash;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUpgradeKeySets(ArraySet<String> upgradeKeySets) {
-        this.upgradeKeySets = upgradeKeySets;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setVolumeUuid(String volumeUuid) {
-        this.volumeUuid = volumeUuid;
-        return this;
-    }
-
-    @Deprecated
-    @Override
-    public PackageImpl setApplicationVolumeUuid(String applicationVolumeUuid) {
-        this.applicationVolumeUuid = applicationVolumeUuid;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSigningDetails(PackageParser.SigningDetails signingDetails) {
-        this.signingDetails = signingDetails;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCodePath(String codePath) {
-        this.codePath = codePath;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUse32BitAbi(boolean use32BitAbi) {
-        this.use32BitAbi = use32BitAbi;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCpuAbiOverride(String cpuAbiOverride) {
-        this.cpuAbiOverride = cpuAbiOverride;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setForceQueryable(boolean forceQueryable) {
-        this.forceQueryable = forceQueryable;
-        return this;
-    }
-
-    // TODO(b/135203078): Remove and move PackageManagerService#renameStaticSharedLibraryPackage
-    //  into initial package parsing
-    @Override
-    public PackageImpl setPackageName(String packageName) {
-        this.packageName = packageName.intern();
-
-        if (permissions != null) {
-            for (ParsedPermission permission : permissions) {
-                permission.setPackageName(this.packageName);
-            }
-        }
-
-        if (permissionGroups != null) {
-            for (ParsedPermissionGroup permissionGroup : permissionGroups) {
-                permissionGroup.setPackageName(this.packageName);
-            }
-        }
-
-        if (activities != null) {
-            for (ParsedActivity parsedActivity : activities) {
-                parsedActivity.setPackageName(this.packageName);
-            }
-        }
-
-        if (receivers != null) {
-            for (ParsedActivity receiver : receivers) {
-                receiver.setPackageName(this.packageName);
-            }
-        }
-
-        if (providers != null) {
-            for (ParsedProvider provider : providers) {
-                provider.setPackageName(this.packageName);
-            }
-        }
-
-        if (services != null) {
-            for (ParsedService service : services) {
-                service.setPackageName(this.packageName);
-            }
-        }
-
-        if (instrumentations != null) {
-            for (ParsedInstrumentation instrumentation : instrumentations) {
-                instrumentation.setPackageName(this.packageName);
-            }
-        }
-
-        return this;
-    }
-
-    // Under this is parseBaseApplication
-
-    @Override
-    public PackageImpl setAllowBackup(boolean allowBackup) {
-        this.flags = allowBackup
-                ? this.flags | ApplicationInfo.FLAG_ALLOW_BACKUP
-                : this.flags & ~ApplicationInfo.FLAG_ALLOW_BACKUP;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setKillAfterRestore(boolean killAfterRestore) {
-        this.flags = killAfterRestore
-                ? this.flags | ApplicationInfo.FLAG_KILL_AFTER_RESTORE
-                : this.flags & ~ApplicationInfo.FLAG_KILL_AFTER_RESTORE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRestoreAnyVersion(boolean restoreAnyVersion) {
-        this.flags = restoreAnyVersion
-                ? this.flags | ApplicationInfo.FLAG_RESTORE_ANY_VERSION
-                : this.flags & ~ApplicationInfo.FLAG_RESTORE_ANY_VERSION;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setFullBackupOnly(boolean fullBackupOnly) {
-        this.flags = fullBackupOnly
-                ? this.flags | ApplicationInfo.FLAG_FULL_BACKUP_ONLY
-                : this.flags & ~ApplicationInfo.FLAG_FULL_BACKUP_ONLY;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setPersistent(boolean persistent) {
-        this.flags = persistent
-                ? this.flags | ApplicationInfo.FLAG_PERSISTENT
-                : this.flags & ~ApplicationInfo.FLAG_PERSISTENT;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setDebuggable(boolean debuggable) {
-        this.flags = debuggable
-                ? this.flags | ApplicationInfo.FLAG_DEBUGGABLE
-                : this.flags & ~ApplicationInfo.FLAG_DEBUGGABLE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setProfileableByShell(boolean profileableByShell) {
-        this.privateFlags = profileableByShell
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setVmSafeMode(boolean vmSafeMode) {
-        this.flags = vmSafeMode
-                ? this.flags | ApplicationInfo.FLAG_VM_SAFE_MODE
-                : this.flags & ~ApplicationInfo.FLAG_VM_SAFE_MODE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setHasCode(boolean hasCode) {
-        this.flags = hasCode
-                ? this.flags | ApplicationInfo.FLAG_HAS_CODE
-                : this.flags & ~ApplicationInfo.FLAG_HAS_CODE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAllowTaskReparenting(boolean allowTaskReparenting) {
-        this.flags = allowTaskReparenting
-                ? this.flags | ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING
-                : this.flags & ~ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAllowClearUserData(boolean allowClearUserData) {
-        this.flags = allowClearUserData
-                ? this.flags | ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA
-                : this.flags & ~ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setLargeHeap(boolean largeHeap) {
-        this.flags = largeHeap
-                ? this.flags | ApplicationInfo.FLAG_LARGE_HEAP
-                : this.flags & ~ApplicationInfo.FLAG_LARGE_HEAP;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUsesCleartextTraffic(boolean usesCleartextTraffic) {
-        this.flags = usesCleartextTraffic
-                ? this.flags | ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC
-                : this.flags & ~ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSupportsRtl(boolean supportsRtl) {
-        this.flags = supportsRtl
-                ? this.flags | ApplicationInfo.FLAG_SUPPORTS_RTL
-                : this.flags & ~ApplicationInfo.FLAG_SUPPORTS_RTL;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setTestOnly(boolean testOnly) {
-        this.flags = testOnly
-                ? this.flags | ApplicationInfo.FLAG_TEST_ONLY
-                : this.flags & ~ApplicationInfo.FLAG_TEST_ONLY;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setMultiArch(boolean multiArch) {
-        this.flags = multiArch
-                ? this.flags | ApplicationInfo.FLAG_MULTIARCH
-                : this.flags & ~ApplicationInfo.FLAG_MULTIARCH;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setExtractNativeLibs(boolean extractNativeLibs) {
-        this.flags = extractNativeLibs
-                ? this.flags | ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS
-                : this.flags & ~ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setIsGame(boolean isGame) {
-        this.flags = isGame
-                ? this.flags | ApplicationInfo.FLAG_IS_GAME
-                : this.flags & ~ApplicationInfo.FLAG_IS_GAME;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setBackupInForeground(boolean backupInForeground) {
-        this.privateFlags = backupInForeground
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUseEmbeddedDex(boolean useEmbeddedDex) {
-        this.privateFlags = useEmbeddedDex
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setDefaultToDeviceProtectedStorage(boolean defaultToDeviceProtectedStorage) {
-        this.privateFlags = defaultToDeviceProtectedStorage
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setDirectBootAware(boolean directBootAware) {
-        this.privateFlags = directBootAware
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setPartiallyDirectBootAware(boolean partiallyDirectBootAware) {
-        this.privateFlags = partiallyDirectBootAware
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setActivitiesResizeModeResizeableViaSdkVersion(
-            boolean resizeableViaSdkVersion
-    ) {
-        this.privateFlags = resizeableViaSdkVersion
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setActivitiesResizeModeResizeable(boolean resizeable) {
-        this.privateFlags = resizeable
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
-
-        this.privateFlags = !resizeable
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAllowClearUserDataOnFailedRestore(
-            boolean allowClearUserDataOnFailedRestore
-    ) {
-        this.privateFlags = allowClearUserDataOnFailedRestore
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAllowAudioPlaybackCapture(boolean allowAudioPlaybackCapture) {
-        this.privateFlags = allowAudioPlaybackCapture
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRequestLegacyExternalStorage(boolean requestLegacyExternalStorage) {
-        this.privateFlags = requestLegacyExternalStorage
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAllowNativeHeapPointerTagging(boolean allowNativeHeapPointerTagging) {
-        this.privateFlags = allowNativeHeapPointerTagging
-                ? this.privateFlags | ApplicationInfo
-                        .PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING
-                : this.privateFlags & ~ApplicationInfo
-                        .PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setPreserveLegacyExternalStorage(boolean preserveLegacyExternalStorage) {
-        this.preserveLegacyExternalStorage = preserveLegacyExternalStorage;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUsesNonSdkApi(boolean usesNonSdkApi) {
-        this.privateFlags = usesNonSdkApi
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setHasFragileUserData(boolean hasFragileUserData) {
-        this.privateFlags = hasFragileUserData
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCantSaveState(boolean cantSaveState) {
-        this.privateFlags = cantSaveState
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE;
-        return this;
-    }
-
-    @Override
-    public boolean cantSaveState() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0;
-    }
-
-    @Override
-    public boolean isLibrary() {
-        return staticSharedLibName != null || !ArrayUtils.isEmpty(libraryNames);
-    }
-
-    // TODO(b/135203078): This does nothing until the final stage without applyPolicy being
-    //  part of PackageParser
-    @Override
-    public boolean isSystemApp() {
-        return (flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-
-    // TODO(b/135203078): This does nothing until the final stage without applyPolicy being
-    //  part of PackageParser
-    @Override
-    public boolean isSystemExt() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0;
-    }
-
-    // TODO(b/135203078): This does nothing until the final stage without applyPolicy being
-    //  part of PackageParser
-    @Override
-    public boolean isUpdatedSystemApp() {
-        return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
-    }
-
-    @Override
-    public PackageImpl setStaticSharedLibrary(boolean staticSharedLibrary) {
-        this.privateFlags = staticSharedLibrary
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY;
-        return this;
-    }
-
-    @Override
-    public boolean isStaticSharedLibrary() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY) != 0;
-    }
-
-    @Override
-    public PackageImpl setVisibleToInstantApps(boolean visibleToInstantApps) {
-        this.visibleToInstantApps = visibleToInstantApps;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setIconRes(int iconRes) {
-        this.iconRes = iconRes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setRoundIconRes(int roundIconRes) {
-        this.roundIconRes = roundIconRes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setClassName(String className) {
-        this.className = className;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setManageSpaceActivityName(String manageSpaceActivityName) {
-        this.manageSpaceActivityName = manageSpaceActivityName;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setBackupAgentName(String backupAgentName) {
-        this.backupAgentName = backupAgentName;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setFullBackupContent(int fullBackupContent) {
-        this.fullBackupContent = fullBackupContent;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setTheme(int theme) {
-        this.theme = theme;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setDescriptionRes(int descriptionRes) {
-        this.descriptionRes = descriptionRes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setNetworkSecurityConfigRes(int networkSecurityConfigRes) {
-        this.networkSecurityConfigRes = networkSecurityConfigRes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCategory(int category) {
-        this.category = category;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setPermission(String permission) {
-        this.permission = permission;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setTaskAffinity(String taskAffinity) {
-        this.taskAffinity = taskAffinity;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setAppComponentFactory(String appComponentFactory) {
-        this.appComponentFactory = appComponentFactory;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setProcessName(String processName) {
-        if (processName == null) {
-            this.processName = packageName;
-        } else {
-            this.processName = processName;
-        }
-        return this;
-    }
-
-    @Override
-    public PackageImpl setEnabled(boolean enabled) {
-        this.enabled = enabled;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCrossProfile(boolean crossProfile) {
-        this.crossProfile = crossProfile;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUiOptions(int uiOptions) {
-        this.uiOptions = uiOptions;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setClassLoaderName(String classLoaderName) {
-        this.classLoaderName = classLoaderName;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setZygotePreloadName(String zygotePreloadName) {
-        this.zygotePreloadName = zygotePreloadName;
-        return this;
-    }
-
-    // parsePackageItemInfo
-
-    @Override
-    public String getName() {
-        return name;
-    }
-
-    @Override
-    public PackageImpl setName(String name) {
-        this.name = name;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setIcon(int icon) {
-        this.icon = icon;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setNonLocalizedLabel(CharSequence nonLocalizedLabel) {
-        this.nonLocalizedLabel = nonLocalizedLabel;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setLogo(int logo) {
-        this.logo = logo;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setBanner(int banner) {
-        this.banner = banner;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setLabelRes(int labelRes) {
-        this.labelRes = labelRes;
-        return this;
-    }
-
-    @Override
-    public PackageImpl asSplit(
-            String[] splitNames,
-            String[] splitCodePaths,
-            int[] splitRevisionCodes,
-            SparseArray<int[]> splitDependencies
-    ) {
-        this.splitNames = splitNames;
-
-        if (this.splitNames != null) {
-            for (int index = 0; index < this.splitNames.length; index++) {
-                splitNames[index] = TextUtils.safeIntern(splitNames[index]);
-            }
-        }
-
-        this.splitCodePaths = splitCodePaths;
-        this.splitRevisionCodes = splitRevisionCodes;
-        this.splitDependencies = splitDependencies;
-
-        int count = splitNames.length;
-        this.splitFlags = new int[count];
-        this.splitClassLoaderNames = new String[count];
-        return this;
-    }
-
-    @Override
-    public String[] getSplitNames() {
-        return splitNames;
-    }
-
-    @Override
-    public String[] getSplitCodePaths() {
-        return splitCodePaths;
-    }
-
-    @Override
-    public PackageImpl setSplitHasCode(int splitIndex, boolean splitHasCode) {
-        this.splitFlags[splitIndex] = splitHasCode
-                ? this.splitFlags[splitIndex] | ApplicationInfo.FLAG_HAS_CODE
-                : this.splitFlags[splitIndex] & ~ApplicationInfo.FLAG_HAS_CODE;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSplitClassLoaderName(int splitIndex, String classLoaderName) {
-        this.splitClassLoaderNames[splitIndex] = classLoaderName;
-        return this;
-    }
-
-    @Override
-    public List<String> makeListAllCodePaths() {
-        ArrayList<String> paths = new ArrayList<>();
-        paths.add(baseCodePath);
-
-        if (!ArrayUtils.isEmpty(splitCodePaths)) {
-            Collections.addAll(paths, splitCodePaths);
-        }
-        return paths;
-    }
-
-    @Override
-    public PackageImpl setBaseCodePath(String baseCodePath) {
-        this.baseCodePath = baseCodePath;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSplitCodePaths(String[] splitCodePaths) {
-        this.splitCodePaths = splitCodePaths;
-        return this;
-    }
-
-    @Override
-    public String toString() {
-        return "Package{"
-                + Integer.toHexString(System.identityHashCode(this))
-                + " " + packageName + "}";
-    }
-
-    @Override
-    public PackageImpl setPrimaryCpuAbi(String primaryCpuAbi) {
-        this.primaryCpuAbi = primaryCpuAbi;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSecondaryCpuAbi(String secondaryCpuAbi) {
-        this.secondaryCpuAbi = secondaryCpuAbi;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setNativeLibraryRootDir(String nativeLibraryRootDir) {
-        this.nativeLibraryRootDir = nativeLibraryRootDir;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setNativeLibraryRootRequiresIsa(boolean nativeLibraryRootRequiresIsa) {
-        this.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setNativeLibraryDir(String nativeLibraryDir) {
-        this.nativeLibraryDir = nativeLibraryDir;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSecondaryNativeLibraryDir(String secondaryNativeLibraryDir) {
-        this.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-        return this;
-    }
-
-    @Deprecated
-    @Override
-    public PackageImpl setApplicationInfoCodePath(String applicationInfoCodePath) {
-        this.applicationInfoCodePath = applicationInfoCodePath;
-        return this;
-    }
-
-    @Deprecated
-    @Override
-    public PackageImpl setApplicationInfoResourcePath(String applicationInfoResourcePath) {
-        this.applicationInfoResourcePath = applicationInfoResourcePath;
-        return this;
-    }
-
-    @Deprecated
-    @Override
-    public PackageImpl setApplicationInfoBaseResourcePath(
-            String applicationInfoBaseResourcePath) {
-        this.applicationInfoBaseResourcePath = applicationInfoBaseResourcePath;
-        return this;
-    }
-
-    @Deprecated
-    @Override
-    public PackageImpl setApplicationInfoSplitResourcePaths(
-            String[] applicationInfoSplitResourcePaths) {
-        this.applicationInfoSplitResourcePaths = applicationInfoSplitResourcePaths;
-        return this;
-    }
-
-    @Override
-    public boolean isDirectBootAware() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE) != 0;
-    }
-
-    @Override
-    public PackageImpl setAllComponentsDirectBootAware(boolean allComponentsDirectBootAware) {
-        if (activities != null) {
-            for (ParsedActivity parsedActivity : activities) {
-                parsedActivity.directBootAware = allComponentsDirectBootAware;
-            }
-        }
-
-        if (receivers != null) {
-            for (ParsedActivity parsedReceiver : receivers) {
-                parsedReceiver.directBootAware = allComponentsDirectBootAware;
-            }
-        }
-
-        if (providers != null) {
-            for (ParsedProvider parsedProvider : providers) {
-                parsedProvider.directBootAware = allComponentsDirectBootAware;
-            }
-        }
-
-        if (services != null) {
-            for (ParsedService parsedService : services) {
-                parsedService.directBootAware = allComponentsDirectBootAware;
-            }
-        }
-
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSystem(boolean system) {
-        this.flags = system
-                ? this.flags | ApplicationInfo.FLAG_SYSTEM
-                : this.flags & ~ApplicationInfo.FLAG_SYSTEM;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSystemExt(boolean systemExt) {
-        this.privateFlags = systemExt
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setIsStub(boolean isStub) {
-        this.isStub = isStub;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setCoreApp(boolean coreApp) {
-        this.coreApp = coreApp;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage capPermissionPriorities() {
-        if (permissionGroups != null && !permissionGroups.isEmpty()) {
-            for (int i = permissionGroups.size() - 1; i >= 0; --i) {
-                // TODO(b/135203078): Builder/immutability
-                permissionGroups.get(i).priority = 0;
-            }
-        }
-        return this;
-    }
-
-    @Override
-    public ParsedPackage clearProtectedBroadcasts() {
-        if (protectedBroadcasts != null) {
-            protectedBroadcasts.clear();
-        }
-        return this;
-    }
-
-    @Override
-    public ParsedPackage markNotActivitiesAsNotExportedIfSingleUser() {
-        // ignore export request for single user receivers
-        if (receivers != null) {
-            for (ParsedActivity receiver : receivers) {
-                if ((receiver.flags & ActivityInfo.FLAG_SINGLE_USER) != 0) {
-                    receiver.exported = false;
-                }
-            }
-        }
-        // ignore export request for single user services
-        if (services != null) {
-            for (ParsedService service : services) {
-                if ((service.flags & ServiceInfo.FLAG_SINGLE_USER) != 0) {
-                    service.exported = false;
-                }
-            }
-        }
-        // ignore export request for single user providers
-        if (providers != null) {
-            for (ParsedProvider provider : providers) {
-                if ((provider.flags & ProviderInfo.FLAG_SINGLE_USER) != 0) {
-                    provider.exported = false;
-                }
-            }
-        }
-
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setPrivileged(boolean privileged) {
-        this.privateFlags = privileged
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setOem(boolean oem) {
-        this.privateFlags = oem
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_OEM
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_OEM;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setVendor(boolean vendor) {
-        this.privateFlags = vendor
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_VENDOR
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_VENDOR;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setProduct(boolean product) {
-        this.privateFlags = product
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_PRODUCT
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_PRODUCT;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setOdm(boolean odm) {
-        this.privateFlags = odm
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_ODM
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_ODM;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setSignedWithPlatformKey(boolean signedWithPlatformKey) {
-        this.privateFlags = signedWithPlatformKey
-                ? this.privateFlags | ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY
-                : this.privateFlags & ~ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY;
-        return this;
-    }
-
-    @Override
-    public ParsedPackage clearOriginalPackages() {
-        if (originalPackages != null) {
-            originalPackages.clear();
-        }
-        return this;
-    }
-
-    @Override
-    public ParsedPackage clearAdoptPermissions() {
-        if (adoptPermissions != null) {
-            adoptPermissions.clear();
-        }
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesLibrary(int index, String libraryName) {
-        this.usesLibraries = ArrayUtils.add(usesLibraries, index, libraryName);
-        return this;
-    }
-
-    @Override
-    public ParsedPackage removeUsesLibrary(String libraryName) {
-        this.usesLibraries = ArrayUtils.remove(this.usesLibraries, libraryName);
-        return this;
-    }
-
-    @Override
-    public PackageImpl addUsesOptionalLibrary(int index, String libraryName) {
-        this.usesOptionalLibraries = ArrayUtils.add(usesOptionalLibraries, index, libraryName);
-        return this;
-    }
-
-    @Nullable
-    @Override
-    public List<String> getUsesOptionalLibraries() {
-        return usesOptionalLibraries;
-    }
-
-    @Override
-    public int getVersionCode() {
-        return versionCode;
-    }
-
-    @Nullable
-    @Override
-    public long[] getUsesStaticLibrariesVersions() {
-        return usesStaticLibrariesVersions;
-    }
-
-    @Override
-    public PackageImpl setPackageSettingCallback(PackageSettingCallback packageSettingCallback) {
-        packageSettingCallback.setAndroidPackage(this);
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUpdatedSystemApp(boolean updatedSystemApp) {
-        this.flags = updatedSystemApp
-                ? this.flags | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP
-                : this.flags & ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
-        return this;
-    }
-
-    @Override
-    public boolean isPrivileged() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
-    }
-
-    @Override
-    public PackageImpl setSeInfo(String seInfo) {
-        this.seInfo = seInfo;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setSeInfoUser(String seInfoUser) {
-        this.seInfoUser = seInfoUser;
-        return this;
-    }
-
-    @Override
-    public PackageImpl initForUser(int userId) {
-        // TODO(b/135203078): Move this user state to some other data structure
-        this.uid = UserHandle.getUid(userId, UserHandle.getAppId(this.uid));
-
-        if ("android".equals(packageName)) {
-            dataDir = Environment.getDataSystemDirectory().getAbsolutePath();
-            return this;
-        }
-
-        deviceProtectedDataDir = Environment
-                .getDataUserDePackageDirectory(applicationVolumeUuid, userId, packageName)
-                .getAbsolutePath();
-        credentialProtectedDataDir = Environment
-                .getDataUserCePackageDirectory(applicationVolumeUuid, userId, packageName)
-                .getAbsolutePath();
-
-        if ((privateFlags & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) != 0
-                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
-            dataDir = deviceProtectedDataDir;
-        } else {
-            dataDir = credentialProtectedDataDir;
-        }
-        return this;
-    }
-
-    @Override
-    public ParsedPackage setFactoryTest(boolean factoryTest) {
-        this.flags = factoryTest
-                ? this.flags | ApplicationInfo.FLAG_FACTORY_TEST
-                : this.flags & ~ApplicationInfo.FLAG_FACTORY_TEST;
-        return this;
-    }
-
-    @Override
-    public String getManifestPackageName() {
-        return manifestPackageName;
-    }
-
-    @Override
-    public String getRealPackage() {
-        return realPackage;
-    }
-
-    @Override
-    public String getOverlayTarget() {
-        return overlayTarget;
-    }
-
-    @Override
-    public String getOverlayTargetName() {
-        return overlayTargetName;
-    }
-
-    @Override
-    public Map<String, String> getOverlayables() {
-        return overlayables;
-    }
-
-    @Override
-    public boolean isOverlayIsStatic() {
-        return overlayIsStatic;
-    }
-
-    @Override
-    public int[] getSplitFlags() {
-        return splitFlags;
-    }
-
-    @Deprecated
-    @Override
-    public String getApplicationInfoVolumeUuid() {
-        return applicationVolumeUuid;
-    }
-
-    @Nullable
-    @Override
-    public List<String> getProtectedBroadcasts() {
-        return protectedBroadcasts;
-    }
-
-    @Nullable
-    @Override
-    public Set<String> getUpgradeKeySets() {
-        return upgradeKeySets;
-    }
-
-    @Nullable
-    @Override
-    public String[][] getUsesStaticLibrariesCertDigests() {
-        return usesStaticLibrariesCertDigests;
-    }
-
-    @Override
-    public int getOverlayPriority() {
-        return overlayPriority;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoPackageName() {
-        return packageName;
-    }
-
-    @Override
-    public UUID getStorageUuid() {
-        return StorageManager.convert(applicationVolumeUuid);
-    }
-
-    @Override
-    public int getUid() {
-        return uid;
-    }
-
-    @Override
-    public boolean isStub() {
-        return isStub;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoCodePath() {
-        return applicationInfoCodePath;
-    }
-
-    @Override
-    public boolean isSystem() {
-        return (flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-
-    @Override
-    public boolean isMatch(int flags) {
-        if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
-            return isSystem();
-        }
-        return true;
-    }
-
-    @Override
-    public boolean isVisibleToInstantApps() {
-        return visibleToInstantApps;
-    }
-
-    @Override
-    public PackageImpl setLastPackageUsageTimeInMills(int reason, long time) {
-        lastPackageUsageTimeInMills[reason] = time;
-        return this;
-    }
-
-    @Override
-    public List<SharedLibraryInfo> getUsesLibraryInfos() {
-        return usesLibraryInfos;
-    }
-
-    @NonNull
-    @Override
-    public List<String> getAllCodePaths() {
-        return makeListAllCodePaths();
-    }
-
-    @Nullable
-    @Override
-    public String[] getUsesLibraryFiles() {
-        return usesLibraryFiles;
-    }
-
-    @Override
-    public PackageImpl setUsesLibraryInfos(
-            @Nullable List<SharedLibraryInfo> usesLibraryInfos) {
-        this.usesLibraryInfos = usesLibraryInfos;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUsesLibraryFiles(@Nullable String[] usesLibraryFiles) {
-        this.usesLibraryFiles = usesLibraryFiles;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setUid(int uid) {
-        this.uid = uid;
-        return this;
-    }
-
-    @Override
-    public List<String> getAdoptPermissions() {
-        return adoptPermissions;
-    }
-
-    @Override
-    public ApplicationInfo toAppInfoWithoutState() {
-        updateFlags();
-
-        ApplicationInfo appInfo = new ApplicationInfo();
-        appInfo.packageName = packageName;
-        appInfo.flags = flags;
-        appInfo.privateFlags = privateFlags;
-
-        appInfo.appComponentFactory = appComponentFactory;
-        appInfo.backupAgentName = backupAgentName;
-        appInfo.banner = banner;
-        appInfo.category = category;
-        appInfo.classLoaderName = classLoaderName;
-        appInfo.className = className;
-        appInfo.compatibleWidthLimitDp = compatibleWidthLimitDp;
-        appInfo.compileSdkVersion = compileSdkVersion;
-        appInfo.compileSdkVersionCodename = compileSdkVersionCodename;
-        appInfo.credentialProtectedDataDir = credentialProtectedDataDir;
-        appInfo.dataDir = dataDir;
-        appInfo.descriptionRes = descriptionRes;
-        appInfo.deviceProtectedDataDir = deviceProtectedDataDir;
-        appInfo.enabled = enabled;
-        appInfo.fullBackupContent = fullBackupContent;
-        appInfo.hiddenUntilInstalled = hiddenUntilInstalled;
-        appInfo.icon = icon;
-        appInfo.iconRes = iconRes;
-        appInfo.installLocation = installLocation;
-        appInfo.labelRes = labelRes;
-        appInfo.largestWidthLimitDp = largestWidthLimitDp;
-        appInfo.logo = logo;
-        appInfo.manageSpaceActivityName = manageSpaceActivityName;
-        appInfo.maxAspectRatio = maxAspectRatio;
-        appInfo.metaData = appMetaData;
-        appInfo.minAspectRatio = minAspectRatio;
-        appInfo.minSdkVersion = minSdkVersion;
-        appInfo.name = className;
-        if (appInfo.name != null) {
-            appInfo.name = appInfo.name.trim();
-        }
-        appInfo.nativeLibraryDir = nativeLibraryDir;
-        appInfo.nativeLibraryRootDir = nativeLibraryRootDir;
-        appInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
-        appInfo.networkSecurityConfigRes = networkSecurityConfigRes;
-        appInfo.nonLocalizedLabel = nonLocalizedLabel;
-        if (appInfo.nonLocalizedLabel != null) {
-            appInfo.nonLocalizedLabel = appInfo.nonLocalizedLabel.toString().trim();
-        }
-        appInfo.packageName = packageName;
-        appInfo.permission = permission;
-        appInfo.primaryCpuAbi = primaryCpuAbi;
-        appInfo.processName = getProcessName();
-        appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp;
-        appInfo.roundIconRes = roundIconRes;
-        appInfo.secondaryCpuAbi = secondaryCpuAbi;
-        appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
-        appInfo.seInfo = seInfo;
-        appInfo.seInfoUser = seInfoUser;
-        appInfo.sharedLibraryFiles = usesLibraryFiles;
-        appInfo.sharedLibraryInfos = ArrayUtils.isEmpty(usesLibraryInfos) ? null : usesLibraryInfos;
-        appInfo.splitClassLoaderNames = splitClassLoaderNames;
-        appInfo.splitDependencies = splitDependencies;
-        appInfo.splitNames = splitNames;
-        appInfo.storageUuid = StorageManager.convert(volumeUuid);
-        appInfo.targetSandboxVersion = targetSandboxVersion;
-        appInfo.targetSdkVersion = targetSdkVersion;
-        appInfo.taskAffinity = taskAffinity;
-        appInfo.theme = theme;
-        appInfo.uid = uid;
-        appInfo.uiOptions = uiOptions;
-        appInfo.volumeUuid = volumeUuid;
-        appInfo.zygotePreloadName = zygotePreloadName;
-        appInfo.crossProfile = isCrossProfile();
-
-        appInfo.setBaseCodePath(baseCodePath);
-        appInfo.setBaseResourcePath(baseCodePath);
-        appInfo.setCodePath(codePath);
-        appInfo.setResourcePath(codePath);
-        appInfo.setSplitCodePaths(splitCodePaths);
-        appInfo.setSplitResourcePaths(splitCodePaths);
-        appInfo.setVersionCode(getLongVersionCode());
-
-        // TODO(b/135203078): Can this be removed? Looks only used in ActivityInfo.
-//        appInfo.showUserIcon = pkg.getShowUserIcon();
-        // TODO(b/135203078): Unused?
-//        appInfo.resourceDirs = pkg.getResourceDirs();
-        // TODO(b/135203078): Unused?
-//        appInfo.enabledSetting = pkg.getEnabledSetting();
-        // TODO(b/135203078): See PackageImpl#getHiddenApiEnforcementPolicy
-//        appInfo.mHiddenApiPolicy = pkg.getHiddenApiPolicy();
-
-        return appInfo;
-    }
-
-    @Override
-    public PackageImpl setVersionCode(int versionCode) {
-        this.versionCode = versionCode;
-        return this;
-    }
-
-    @Override
-    public PackageImpl setHiddenUntilInstalled(boolean hidden) {
-        this.hiddenUntilInstalled = hidden;
-        return this;
-    }
-
-    @Override
-    public String getSeInfo() {
-        return seInfo;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoResourcePath() {
-        return applicationInfoResourcePath;
-    }
-
-    @Override
-    public boolean isForwardLocked() {
-        // TODO(b/135203078): Unused? Move to debug flag?
-        return false;
-    }
-
-    @Override
-    public byte[] getRestrictUpdateHash() {
-        return restrictUpdateHash;
-    }
-
-    @Override
-    public boolean hasComponentClassName(String className) {
-        if (activities != null) {
-            for (ParsedActivity parsedActivity : activities) {
-                if (Objects.equals(className, parsedActivity.className)) {
-                    return true;
-                }
-            }
-        }
-
-        if (receivers != null) {
-            for (ParsedActivity receiver : receivers) {
-                if (Objects.equals(className, receiver.className)) {
-                    return true;
-                }
-            }
-        }
-
-        if (providers != null) {
-            for (ParsedProvider provider : providers) {
-                if (Objects.equals(className, provider.className)) {
-                    return true;
-                }
-            }
-        }
-
-        if (services != null) {
-            for (ParsedService service : services) {
-                if (Objects.equals(className, service.className)) {
-                    return true;
-                }
-            }
-        }
-
-        if (instrumentations != null) {
-            for (ParsedInstrumentation instrumentation : instrumentations) {
-                if (Objects.equals(className, instrumentation.className)) {
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    @Override
-    public boolean isDefaultToDeviceProtectedStorage() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
-                != 0;
-    }
-
-    @Override
-    public boolean isInternal() {
-        return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) == 0;
-    }
-
-    @Override
-    public int getBaseRevisionCode() {
-        return baseRevisionCode;
-    }
-
-    @Override
-    public int[] getSplitRevisionCodes() {
-        return splitRevisionCodes;
-    }
-
-    @Override
-    public boolean canHaveOatDir() {
-        // The following app types CANNOT have oat directory
-        // - non-updated system apps
-        return !isSystem() || isUpdatedSystemApp();
-    }
-
-    @Override
-    public long getLatestPackageUseTimeInMills() {
-        long latestUse = 0L;
-        for (long use : lastPackageUsageTimeInMills) {
-            latestUse = Math.max(latestUse, use);
-        }
-        return latestUse;
-    }
-
-    @Override
-    public long getLatestForegroundPackageUseTimeInMills() {
-        int[] foregroundReasons = {
-                PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
-                PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
-        };
-
-        long latestUse = 0L;
-        for (int reason : foregroundReasons) {
-            latestUse = Math.max(latestUse, lastPackageUsageTimeInMills[reason]);
-        }
-        return latestUse;
-    }
-
-    @Override
-    public boolean isCoreApp() {
-        return coreApp;
-    }
-
-    @Override
-    public String getVersionName() {
-        return versionName;
-    }
-
-    @Override
-    public PackageImpl setVersionCodeMajor(int versionCodeMajor) {
-        this.versionCodeMajor = versionCodeMajor;
-        return this;
-    }
-
-    @Override
-    public long[] getLastPackageUsageTimeInMills() {
-        return lastPackageUsageTimeInMills;
-    }
-
-    @Override
-    public String getDataDir() {
-        return dataDir;
-    }
-
-    @Override
-    public boolean isExternal() {
-        return (flags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
-    }
-
-    @Override
-    public List<String> getImplicitPermissions() {
-        return implicitPermissions == null ? Collections.emptyList() : implicitPermissions;
-    }
-
-    /**
-     * TODO(b/135203078): Remove, ensure b/140256621 is fixed or irrelevant
-     * TODO(b/140256621): Remove after fixing instant app check
-     * @deprecated This method always returns false because there's no paired set method
-     */
-    @Deprecated
-    @Override
-    public boolean isInstantApp() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_INSTANT) != 0;
-    }
-
-    @Override
-    public boolean hasRequestedLegacyExternalStorage() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE) != 0;
-    }
-
-    @Override
-    public boolean isVendor() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
-    }
-
-    @Override
-    public boolean isProduct() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
-    }
-
-    @Override
-    public boolean isOem() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
-    }
-
-    @Override
-    public boolean isEncryptionAware() {
-        boolean isPartiallyDirectBootAware =
-                (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0;
-        return isDirectBootAware() || isPartiallyDirectBootAware;
-    }
-
-    @Override
-    public boolean isEmbeddedDexUsed() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX) != 0;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoProcessName() {
-        return processName;
-    }
-
-    @Override
-    public List<String> getAllCodePathsExcludingResourceOnly() {
-        ArrayList<String> paths = new ArrayList<>();
-        if ((flags & ApplicationInfo.FLAG_HAS_CODE) != 0) {
-            paths.add(baseCodePath);
-        }
-        if (!ArrayUtils.isEmpty(splitCodePaths)) {
-            for (int i = 0; i < splitCodePaths.length; i++) {
-                if ((splitFlags[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
-                    paths.add(splitCodePaths[i]);
-                }
-            }
-        }
-        return paths;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoName() {
-        return name;
-    }
-
-    private boolean isSignedWithPlatformKey() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY) != 0;
-    }
-
-    private boolean usesNonSdkApi() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API) != 0;
-    }
-
-    private boolean isPackageWhitelistedForHiddenApis() {
-        return SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(packageName);
-    }
-
-    private boolean isAllowedToUseHiddenApis() {
-        if (isSignedWithPlatformKey()) {
-            return true;
-        } else if (isSystemApp() || isUpdatedSystemApp()) {
-            return usesNonSdkApi() || isPackageWhitelistedForHiddenApis();
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public int getHiddenApiEnforcementPolicy() {
-        if (isAllowedToUseHiddenApis()) {
-            return ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
-        }
-
-        // TODO(b/135203078): Handle maybeUpdateHiddenApiEnforcementPolicy. Right now it's done
-        //  entirely through ApplicationInfo and shouldn't touch this specific class, but that
-        //  may not always hold true.
-//        if (mHiddenApiPolicy != ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT) {
-//            return mHiddenApiPolicy;
-//        }
-        return ApplicationInfo.HIDDEN_API_ENFORCEMENT_ENABLED;
-    }
-
-    @Nullable
-    @Override
-    public SparseArray<int[]> getSplitDependencies() {
-        return splitDependencies;
-    }
-
-    @Override
-    public boolean requestsIsolatedSplitLoading() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING) != 0;
-    }
-
-    @Deprecated
-    @Override
-    public String getAppInfoClassLoaderName() {
-        return classLoaderName;
-    }
-
-    @Override
-    public String getClassLoaderName() {
-        return classLoaderName;
-    }
-
-    @Override
-    public String[] getSplitClassLoaderNames() {
-        return splitClassLoaderNames;
-    }
-
-    @Override
-    public String getOverlayCategory() {
-        return overlayCategory;
-    }
-
-    @Override
-    public boolean isProfileableByShell() {
-        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL) != 0;
-    }
-
-    @Nullable
-    @Override
-    public List<ParsedActivityIntentInfo> getPreferredActivityFilters() {
-        return preferredActivityFilters;
-    }
-
-    @Override
-    public boolean isHiddenUntilInstalled() {
-        return hiddenUntilInstalled;
-    }
-
-    @Override
-    public int getMinSdkVersion() {
-        return minSdkVersion;
-    }
-
-    @Override
-    public String getRestrictedAccountType() {
-        return restrictedAccountType;
-    }
-
-    @Override
-    public String getRequiredAccountType() {
-        return requiredAccountType;
-    }
-
-    @Override
-    public int getInstallLocation() {
-        return installLocation;
-    }
-
-    @Override
-    public List<ParsedActivity> getReceivers() {
-        return receivers;
-    }
-
-    @Override
-    public List<ParsedService> getServices() {
-        return services;
-    }
-
-    @Override
-    public List<ParsedProvider> getProviders() {
-        return providers;
-    }
-
-    @Override
-    public int getSharedUserLabel() {
-        return sharedUserLabel;
-    }
-
-    @Override
-    public int getVersionCodeMajor() {
-        return versionCodeMajor;
-    }
-
-    @Override
-    public boolean isRequiredForAllUsers() {
-        return requiredForAllUsers;
-    }
-
-    @Override
-    public int getCompileSdkVersion() {
-        return compileSdkVersion;
-    }
-
-    @Override
-    public String getCompileSdkVersionCodeName() {
-        return compileSdkVersionCodename;
-    }
-
-    @Nullable
-    @Override
-    public List<ConfigurationInfo> getConfigPreferences() {
-        return configPreferences;
-    }
-
-    @Nullable
-    @Override
-    public List<FeatureInfo> getReqFeatures() {
-        return reqFeatures;
-    }
-
-    @Override
-    public List<FeatureGroupInfo> getFeatureGroups() {
-        return featureGroups;
-    }
-
-    @Override
-    public String getDeviceProtectedDataDir() {
-        return deviceProtectedDataDir;
-    }
-
-    @Override
-    public String getCredentialProtectedDataDir() {
-        return credentialProtectedDataDir;
-    }
-
-    @Override
-    public String getSeInfoUser() {
-        return seInfoUser;
-    }
-
-    @Override
-    public String getClassName() {
-        return className;
-    }
-
-    @Override
-    public int getTheme() {
-        return theme;
-    }
-
-    @Override
-    public int getRequiresSmallestWidthDp() {
-        return requiresSmallestWidthDp;
-    }
-
-    @Override
-    public int getCompatibleWidthLimitDp() {
-        return compatibleWidthLimitDp;
-    }
-
-    @Override
-    public int getLargestWidthLimitDp() {
-        return largestWidthLimitDp;
-    }
-
-    @Override
-    public String getScanSourceDir() {
-        return applicationInfoCodePath;
-    }
-
-    @Override
-    public String getScanPublicSourceDir() {
-        return applicationInfoResourcePath;
-    }
-
-    @Override
-    public String getPublicSourceDir() {
-        return applicationInfoBaseResourcePath;
-    }
-
-    @Override
-    public String[] getSplitPublicSourceDirs() {
-        return applicationInfoSplitResourcePaths;
-    }
-
-    @Override
-    public String getSecondaryNativeLibraryDir() {
-        return secondaryNativeLibraryDir;
-    }
-
-    @Override
-    public boolean isEnabled() {
-        return enabled;
-    }
-
-    @Override
-    public boolean isCrossProfile() {
-        return crossProfile;
-    }
-
-    @Override
-    public String getManageSpaceActivityName() {
-        return manageSpaceActivityName;
-    }
-
-    @Override
-    public int getDescriptionRes() {
-        return descriptionRes;
-    }
-
-    @Override
-    public String getBackupAgentName() {
-        return backupAgentName;
-    }
-
-    @Override
-    public int getFullBackupContent() {
-        return fullBackupContent;
-    }
-
-    @Override
-    public int getNetworkSecurityConfigRes() {
-        return networkSecurityConfigRes;
-    }
-
-    @Override
-    public int getCategory() {
-        return category;
-    }
-
-    @Override
-    public int getTargetSandboxVersion() {
-        return targetSandboxVersion;
-    }
-
-    @Override
-    public String getAppComponentFactory() {
-        return appComponentFactory;
-    }
-
-    @Override
-    public int getIconRes() {
-        return iconRes;
-    }
-
-    @Override
-    public int getRoundIconRes() {
-        return roundIconRes;
-    }
-
-    @Override
-    public String getZygotePreloadName() {
-        return zygotePreloadName;
-    }
-
-    @Override
-    public int getLabelRes() {
-        return labelRes;
-    }
-
-    @Override
-    public CharSequence getNonLocalizedLabel() {
-        return nonLocalizedLabel;
-    }
-
-    @Override
-    public int getIcon() {
-        return icon;
-    }
-
-    @Override
-    public int getBanner() {
-        return banner;
-    }
-
-    @Override
-    public int getLogo() {
-        return logo;
-    }
-
-    @Override
-    public Bundle getMetaData() {
-        return appMetaData;
-    }
-
-    @Override
-    @Nullable
-    public List<Intent> getQueriesIntents() {
-        return queriesIntents;
-    }
-
-    @Override
-    @Nullable
-    public List<String> getQueriesPackages() {
-        return queriesPackages;
-    }
-
-    @Override
-    public Set<String> getQueriesProviders() {
-        return queriesProviders;
-    }
-
-    @Override
-    public boolean hasPreserveLegacyExternalStorage() {
-        return preserveLegacyExternalStorage;
-    }
-
-    private static void internStringArrayList(List<String> list) {
-        if (list != null) {
-            final int N = list.size();
-            for (int i = 0; i < N; ++i) {
-                list.set(i, list.get(i).intern());
-            }
-        }
-    }
-
-    @Override
-    public int describeContents() {
-        return 0;
-    }
-
-    @Override
-    public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(this.supportsSmallScreens);
-        dest.writeInt(this.supportsNormalScreens);
-        dest.writeInt(this.supportsLargeScreens);
-        dest.writeInt(this.supportsXLargeScreens);
-        dest.writeInt(this.resizeable);
-        dest.writeInt(this.anyDensity);
-        dest.writeLongArray(this.lastPackageUsageTimeInMills);
-        dest.writeInt(this.versionCode);
-        dest.writeInt(this.versionCodeMajor);
-        dest.writeInt(this.baseRevisionCode);
-        dest.writeString(this.versionName);
-        dest.writeBoolean(this.coreApp);
-        dest.writeInt(this.compileSdkVersion);
-        dest.writeString(this.compileSdkVersionCodename);
-        dest.writeString(this.packageName);
-        dest.writeString(this.realPackage);
-        dest.writeString(this.manifestPackageName);
-        dest.writeString(this.baseCodePath);
-        dest.writeBoolean(this.requiredForAllUsers);
-        dest.writeString(this.restrictedAccountType);
-        dest.writeString(this.requiredAccountType);
-        dest.writeBoolean(this.baseHardwareAccelerated);
-        dest.writeString(this.overlayTarget);
-        dest.writeString(this.overlayTargetName);
-        dest.writeString(this.overlayCategory);
-        dest.writeInt(this.overlayPriority);
-        dest.writeBoolean(this.overlayIsStatic);
-        dest.writeMap(this.overlayables);
-        dest.writeString(this.staticSharedLibName);
-        dest.writeLong(this.staticSharedLibVersion);
-        dest.writeStringList(this.libraryNames);
-        dest.writeStringList(this.usesLibraries);
-        dest.writeStringList(this.usesOptionalLibraries);
-        dest.writeStringList(this.usesStaticLibraries);
-        dest.writeLongArray(this.usesStaticLibrariesVersions);
-        final int numProcesses = this.processes != null ? this.processes.size() : 0;
-        dest.writeInt(numProcesses);
-        for (int i = 0; i < numProcesses; i++) {
-            this.processes.valueAt(i).writeToParcel(dest, 0);
-        }
-
-        if (this.usesStaticLibrariesCertDigests == null) {
-            dest.writeInt(-1);
-        } else {
-            dest.writeInt(this.usesStaticLibrariesCertDigests.length);
-            for (int index = 0; index < this.usesStaticLibrariesCertDigests.length; index++) {
-                dest.writeStringArray(this.usesStaticLibrariesCertDigests[index]);
-            }
-        }
-
-        dest.writeString(this.sharedUserId);
-        dest.writeInt(this.sharedUserLabel);
-        dest.writeTypedList(this.configPreferences);
-        dest.writeTypedList(this.reqFeatures);
-        dest.writeTypedList(this.featureGroups);
-        dest.writeByteArray(this.restrictUpdateHash);
-        dest.writeStringList(this.originalPackages);
-        dest.writeStringList(this.adoptPermissions);
-        dest.writeStringList(this.requestedPermissions);
-        dest.writeStringList(this.implicitPermissions);
-        dest.writeArraySet(this.upgradeKeySets);
-        dest.writeMap(this.keySetMapping);
-        dest.writeStringList(this.protectedBroadcasts);
-        dest.writeTypedList(this.activities);
-        dest.writeTypedList(this.receivers);
-        dest.writeTypedList(this.services);
-        dest.writeTypedList(this.providers);
-        dest.writeTypedList(this.features);
-        dest.writeTypedList(this.permissions);
-        dest.writeTypedList(this.permissionGroups);
-        dest.writeTypedList(this.instrumentations);
-        ParsedIntentInfo.writeIntentsList(this.preferredActivityFilters, dest, flags);
-        dest.writeBundle(this.appMetaData);
-        dest.writeString(this.volumeUuid);
-        dest.writeString(this.applicationVolumeUuid);
-        dest.writeParcelable(this.signingDetails, flags);
-        dest.writeString(this.codePath);
-        dest.writeBoolean(this.use32BitAbi);
-        dest.writeBoolean(this.visibleToInstantApps);
-        dest.writeString(this.cpuAbiOverride);
-        dest.writeBoolean(this.isStub);
-        dest.writeInt(this.preferredOrder);
-        dest.writeBoolean(this.forceQueryable);
-        dest.writeParcelableList(this.queriesIntents, flags);
-        dest.writeStringList(this.queriesPackages);
-        dest.writeString(this.applicationInfoBaseResourcePath);
-        dest.writeString(this.applicationInfoCodePath);
-        dest.writeString(this.applicationInfoResourcePath);
-        dest.writeStringArray(this.applicationInfoSplitResourcePaths);
-        dest.writeString(this.appComponentFactory);
-        dest.writeString(this.backupAgentName);
-        dest.writeInt(this.banner);
-        dest.writeInt(this.category);
-        dest.writeString(this.classLoaderName);
-        dest.writeString(this.className);
-        dest.writeInt(this.compatibleWidthLimitDp);
-        dest.writeString(this.credentialProtectedDataDir);
-        dest.writeString(this.dataDir);
-        dest.writeInt(this.descriptionRes);
-        dest.writeString(this.deviceProtectedDataDir);
-        dest.writeBoolean(this.enabled);
-        dest.writeBoolean(this.crossProfile);
-        dest.writeInt(this.flags);
-        dest.writeInt(this.fullBackupContent);
-        dest.writeBoolean(this.hiddenUntilInstalled);
-        dest.writeInt(this.icon);
-        dest.writeInt(this.iconRes);
-        dest.writeInt(this.installLocation);
-        dest.writeInt(this.labelRes);
-        dest.writeInt(this.largestWidthLimitDp);
-        dest.writeInt(this.logo);
-        dest.writeString(this.manageSpaceActivityName);
-        dest.writeFloat(this.maxAspectRatio);
-        dest.writeFloat(this.minAspectRatio);
-        dest.writeInt(this.minSdkVersion);
-        dest.writeString(this.name);
-        dest.writeString(this.nativeLibraryDir);
-        dest.writeString(this.nativeLibraryRootDir);
-        dest.writeBoolean(this.nativeLibraryRootRequiresIsa);
-        dest.writeInt(this.networkSecurityConfigRes);
-        dest.writeCharSequence(this.nonLocalizedLabel);
-        dest.writeString(this.permission);
-        dest.writeString(this.primaryCpuAbi);
-        dest.writeInt(this.privateFlags);
-        dest.writeString(this.processName);
-        dest.writeInt(this.requiresSmallestWidthDp);
-        dest.writeInt(this.roundIconRes);
-        dest.writeString(this.secondaryCpuAbi);
-        dest.writeString(this.secondaryNativeLibraryDir);
-        dest.writeString(this.seInfo);
-        dest.writeString(this.seInfoUser);
-        dest.writeInt(this.targetSandboxVersion);
-        dest.writeInt(this.targetSdkVersion);
-        dest.writeString(this.taskAffinity);
-        dest.writeInt(this.theme);
-        dest.writeInt(this.uid);
-        dest.writeInt(this.uiOptions);
-        dest.writeStringArray(this.usesLibraryFiles);
-        dest.writeTypedList(this.usesLibraryInfos);
-        dest.writeString(this.zygotePreloadName);
-        dest.writeStringArray(this.splitClassLoaderNames);
-        dest.writeStringArray(this.splitCodePaths);
-        dest.writeSparseArray(this.splitDependencies);
-        dest.writeIntArray(this.splitFlags);
-        dest.writeStringArray(this.splitNames);
-        dest.writeIntArray(this.splitRevisionCodes);
-    }
-
-    public PackageImpl(Parcel in) {
-        // We use the boot classloader for all classes that we load.
-        final ClassLoader boot = Object.class.getClassLoader();
-        this.supportsSmallScreens = in.readInt();
-        this.supportsNormalScreens = in.readInt();
-        this.supportsLargeScreens = in.readInt();
-        this.supportsXLargeScreens = in.readInt();
-        this.resizeable = in.readInt();
-        this.anyDensity = in.readInt();
-        this.lastPackageUsageTimeInMills = in.createLongArray();
-        this.versionCode = in.readInt();
-        this.versionCodeMajor = in.readInt();
-        this.baseRevisionCode = in.readInt();
-        this.versionName = TextUtils.safeIntern(in.readString());
-        this.coreApp = in.readBoolean();
-        this.compileSdkVersion = in.readInt();
-        this.compileSdkVersionCodename = TextUtils.safeIntern(in.readString());
-        this.packageName = TextUtils.safeIntern(in.readString());
-        this.realPackage = in.readString();
-        this.manifestPackageName = in.readString();
-        this.baseCodePath = in.readString();
-        this.requiredForAllUsers = in.readBoolean();
-        this.restrictedAccountType = in.readString();
-        this.requiredAccountType = in.readString();
-        this.baseHardwareAccelerated = in.readBoolean();
-        this.overlayTarget = in.readString();
-        this.overlayTargetName = in.readString();
-        this.overlayCategory = in.readString();
-        this.overlayPriority = in.readInt();
-        this.overlayIsStatic = in.readBoolean();
-        this.overlayables = new HashMap<>();
-        in.readMap(overlayables, boot);
-        this.staticSharedLibName = TextUtils.safeIntern(in.readString());
-        this.staticSharedLibVersion = in.readLong();
-        this.libraryNames = in.createStringArrayList();
-        internStringArrayList(this.libraryNames);
-        this.usesLibraries = in.createStringArrayList();
-        internStringArrayList(this.usesLibraries);
-        this.usesOptionalLibraries = in.createStringArrayList();
-        internStringArrayList(this.usesOptionalLibraries);
-        this.usesStaticLibraries = in.createStringArrayList();
-        internStringArrayList(usesStaticLibraries);
-        this.usesStaticLibrariesVersions = in.createLongArray();
-        final int numProcesses = in.readInt();
-        if (numProcesses > 0) {
-            this.processes = new ArrayMap<>(numProcesses);
-            for (int i = 0; i < numProcesses; i++) {
-                ComponentParseUtils.ParsedProcess proc = new ComponentParseUtils.ParsedProcess(in);
-                this.processes.put(proc.name, proc);
-            }
-        } else {
-            this.processes = null;
-        }
-
-        int digestsSize = in.readInt();
-        if (digestsSize >= 0) {
-            this.usesStaticLibrariesCertDigests = new String[digestsSize][];
-            for (int index = 0; index < digestsSize; index++) {
-                this.usesStaticLibrariesCertDigests[index] = in.readStringArray();
-            }
-        }
-
-        this.sharedUserId = TextUtils.safeIntern(in.readString());
-        this.sharedUserLabel = in.readInt();
-        this.configPreferences = in.createTypedArrayList(ConfigurationInfo.CREATOR);
-        this.reqFeatures = in.createTypedArrayList(FeatureInfo.CREATOR);
-        this.featureGroups = in.createTypedArrayList(FeatureGroupInfo.CREATOR);
-        this.restrictUpdateHash = in.createByteArray();
-        this.originalPackages = in.createStringArrayList();
-        this.adoptPermissions = in.createStringArrayList();
-        this.requestedPermissions = in.createStringArrayList();
-        internStringArrayList(this.requestedPermissions);
-        this.implicitPermissions = in.createStringArrayList();
-        internStringArrayList(this.implicitPermissions);
-        this.upgradeKeySets = (ArraySet<String>) in.readArraySet(boot);
-        this.keySetMapping = in.readHashMap(boot);
-        this.protectedBroadcasts = in.createStringArrayList();
-        internStringArrayList(this.protectedBroadcasts);
-        this.activities = in.createTypedArrayList(ParsedActivity.CREATOR);
-        this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR);
-        this.services = in.createTypedArrayList(ParsedService.CREATOR);
-        this.providers = in.createTypedArrayList(ParsedProvider.CREATOR);
-        this.features = in.createTypedArrayList(ParsedFeature.CREATOR);
-        this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
-        this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
-        this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR);
-        this.preferredActivityFilters = ParsedIntentInfo.createIntentsList(in);
-        this.appMetaData = in.readBundle(boot);
-        this.volumeUuid = in.readString();
-        this.applicationVolumeUuid = in.readString();
-        this.signingDetails = in.readParcelable(boot);
-        this.codePath = in.readString();
-        this.use32BitAbi = in.readBoolean();
-        this.visibleToInstantApps = in.readBoolean();
-        this.cpuAbiOverride = in.readString();
-        this.isStub = in.readBoolean();
-        this.preferredOrder = in.readInt();
-        this.forceQueryable = in.readBoolean();
-        this.queriesIntents = in.createTypedArrayList(Intent.CREATOR);
-        this.queriesPackages = in.createStringArrayList();
-        internStringArrayList(this.queriesPackages);
-        this.applicationInfoBaseResourcePath = in.readString();
-        this.applicationInfoCodePath = in.readString();
-        this.applicationInfoResourcePath = in.readString();
-        this.applicationInfoSplitResourcePaths = in.createStringArray();
-        this.appComponentFactory = in.readString();
-        this.backupAgentName = in.readString();
-        this.banner = in.readInt();
-        this.category = in.readInt();
-        this.classLoaderName = in.readString();
-        this.className = in.readString();
-        this.compatibleWidthLimitDp = in.readInt();
-        this.credentialProtectedDataDir = in.readString();
-        this.dataDir = in.readString();
-        this.descriptionRes = in.readInt();
-        this.deviceProtectedDataDir = in.readString();
-        this.enabled = in.readBoolean();
-        this.crossProfile = in.readBoolean();
-        this.flags = in.readInt();
-        this.fullBackupContent = in.readInt();
-        this.hiddenUntilInstalled = in.readBoolean();
-        this.icon = in.readInt();
-        this.iconRes = in.readInt();
-        this.installLocation = in.readInt();
-        this.labelRes = in.readInt();
-        this.largestWidthLimitDp = in.readInt();
-        this.logo = in.readInt();
-        this.manageSpaceActivityName = in.readString();
-        this.maxAspectRatio = in.readFloat();
-        this.minAspectRatio = in.readFloat();
-        this.minSdkVersion = in.readInt();
-        this.name = in.readString();
-        this.nativeLibraryDir = in.readString();
-        this.nativeLibraryRootDir = in.readString();
-        this.nativeLibraryRootRequiresIsa = in.readBoolean();
-        this.networkSecurityConfigRes = in.readInt();
-        this.nonLocalizedLabel = in.readCharSequence();
-        this.permission = TextUtils.safeIntern(in.readString());
-        this.primaryCpuAbi = in.readString();
-        this.privateFlags = in.readInt();
-        this.processName = in.readString();
-        this.requiresSmallestWidthDp = in.readInt();
-        this.roundIconRes = in.readInt();
-        this.secondaryCpuAbi = in.readString();
-        this.secondaryNativeLibraryDir = in.readString();
-        this.seInfo = in.readString();
-        this.seInfoUser = in.readString();
-        this.targetSandboxVersion = in.readInt();
-        this.targetSdkVersion = in.readInt();
-        this.taskAffinity = in.readString();
-        this.theme = in.readInt();
-        this.uid = in.readInt();
-        this.uiOptions = in.readInt();
-        this.usesLibraryFiles = in.createStringArray();
-        this.usesLibraryInfos = in.createTypedArrayList(SharedLibraryInfo.CREATOR);
-        this.zygotePreloadName = in.readString();
-        this.splitClassLoaderNames = in.createStringArray();
-        this.splitCodePaths = in.createStringArray();
-        this.splitDependencies = in.readSparseArray(boot);
-        this.splitFlags = in.createIntArray();
-        this.splitNames = in.createStringArray();
-        this.splitRevisionCodes = in.createIntArray();
-    }
-
-    public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
-        @Override
-        public PackageImpl createFromParcel(Parcel source) {
-            return new PackageImpl(source);
-        }
-
-        @Override
-        public PackageImpl[] newArray(int size) {
-            return new PackageImpl[size];
-        }
-    };
-}
diff --git a/core/java/android/content/pm/parsing/PackageInfoUtils.java b/core/java/android/content/pm/parsing/PackageInfoUtils.java
deleted file mode 100644
index 72df189..0000000
--- a/core/java/android/content/pm/parsing/PackageInfoUtils.java
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.content.pm.parsing;
-
-import android.annotation.Nullable;
-import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.ComponentInfo;
-import android.content.pm.ConfigurationInfo;
-import android.content.pm.FallbackCategoryProvider;
-import android.content.pm.FeatureGroupInfo;
-import android.content.pm.FeatureInfo;
-import android.content.pm.InstrumentationInfo;
-import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.PackageParser;
-import android.content.pm.PackageUserState;
-import android.content.pm.PermissionGroupInfo;
-import android.content.pm.PermissionInfo;
-import android.content.pm.ProcessInfo;
-import android.content.pm.ProviderInfo;
-import android.content.pm.SELinuxUtil;
-import android.content.pm.ServiceInfo;
-import android.content.pm.Signature;
-import android.content.pm.SigningInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-
-import com.android.internal.util.ArrayUtils;
-
-import java.util.Set;
-
-/** @hide */
-public class PackageInfoUtils {
-
-    private static final String TAG = ApkParseUtils.TAG;
-
-    /**
-     * Returns true if the package is installed and not hidden, or if the caller
-     * explicitly wanted all uninstalled and hidden packages as well.
-     */
-    private static boolean checkUseInstalledOrHidden(AndroidPackage pkg, PackageUserState state,
-            @PackageManager.PackageInfoFlags int flags) {
-        // Returns false if the package is hidden system app until installed.
-        if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
-                && !state.installed
-                && pkg.isHiddenUntilInstalled()) {
-            return false;
-        }
-
-        // If available for the target user, or trying to match uninstalled packages and it's
-        // a system app.
-        return state.isAvailable(flags)
-                || (pkg.isSystemApp()
-                && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
-                || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
-    }
-
-    public static PackageInfo generate(AndroidPackage pkg, int[] gids,
-            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
-            Set<String> grantedPermissions, PackageUserState state, int userId) {
-        if (!checkUseInstalledOrHidden(pkg, state, flags) || !pkg.isMatch(flags)) {
-            return null;
-        }
-        ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
-
-        PackageInfo pi = new PackageInfo();
-        pi.packageName = pkg.getPackageName();
-        pi.splitNames = pkg.getSplitNames();
-        pi.versionCode = pkg.getVersionCode();
-        pi.versionCodeMajor = pkg.getVersionCodeMajor();
-        pi.baseRevisionCode = pkg.getBaseRevisionCode();
-        pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
-        pi.versionName = pkg.getVersionName();
-        pi.sharedUserId = pkg.getSharedUserId();
-        pi.sharedUserLabel = pkg.getSharedUserLabel();
-        pi.applicationInfo = applicationInfo;
-        pi.installLocation = pkg.getInstallLocation();
-        pi.isStub = pkg.isStub();
-        pi.coreApp = pkg.isCoreApp();
-        if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
-                || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
-            pi.requiredForAllUsers = pkg.isRequiredForAllUsers();
-        }
-        pi.restrictedAccountType = pkg.getRestrictedAccountType();
-        pi.requiredAccountType = pkg.getRequiredAccountType();
-        pi.overlayTarget = pkg.getOverlayTarget();
-        pi.targetOverlayableName = pkg.getOverlayTargetName();
-        pi.overlayCategory = pkg.getOverlayCategory();
-        pi.overlayPriority = pkg.getOverlayPriority();
-        pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
-        pi.compileSdkVersion = pkg.getCompileSdkVersion();
-        pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
-        pi.firstInstallTime = firstInstallTime;
-        pi.lastUpdateTime = lastUpdateTime;
-        if ((flags & PackageManager.GET_GIDS) != 0) {
-            pi.gids = gids;
-        }
-        if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
-            int size = pkg.getConfigPreferences() != null ? pkg.getConfigPreferences().size() : 0;
-            if (size > 0) {
-                pi.configPreferences = new ConfigurationInfo[size];
-                pkg.getConfigPreferences().toArray(pi.configPreferences);
-            }
-            size = pkg.getReqFeatures() != null ? pkg.getReqFeatures().size() : 0;
-            if (size > 0) {
-                pi.reqFeatures = new FeatureInfo[size];
-                pkg.getReqFeatures().toArray(pi.reqFeatures);
-            }
-            size = pkg.getFeatureGroups() != null ? pkg.getFeatureGroups().size() : 0;
-            if (size > 0) {
-                pi.featureGroups = new FeatureGroupInfo[size];
-                pkg.getFeatureGroups().toArray(pi.featureGroups);
-            }
-        }
-        if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
-            if (pkg.getActivities() != null) {
-                final int N = pkg.getActivities().size();
-                if (N > 0) {
-                    int num = 0;
-                    final ActivityInfo[] res = new ActivityInfo[N];
-                    for (int i = 0; i < N; i++) {
-                        final ParsedActivity a = pkg.getActivities().get(i);
-                        if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), a, flags)) {
-                            if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
-                                    a.className)) {
-                                continue;
-                            }
-                            res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
-                                    userId);
-                        }
-                    }
-                    pi.activities = ArrayUtils.trimToSize(res, num);
-                }
-            }
-        }
-        if ((flags & PackageManager.GET_RECEIVERS) != 0) {
-            if (pkg.getReceivers() != null) {
-                final int size = pkg.getReceivers().size();
-                if (size > 0) {
-                    int num = 0;
-                    final ActivityInfo[] res = new ActivityInfo[size];
-                    for (int i = 0; i < size; i++) {
-                        final ParsedActivity a = pkg.getReceivers().get(i);
-                        if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), a, flags)) {
-                            res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
-                                    userId);
-                        }
-                    }
-                    pi.receivers = ArrayUtils.trimToSize(res, num);
-                }
-            }
-        }
-        if ((flags & PackageManager.GET_SERVICES) != 0) {
-            if (pkg.getServices() != null) {
-                final int size = pkg.getServices().size();
-                if (size > 0) {
-                    int num = 0;
-                    final ServiceInfo[] res = new ServiceInfo[size];
-                    for (int i = 0; i < size; i++) {
-                        final ComponentParseUtils.ParsedService s = pkg.getServices().get(i);
-                        if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), s, flags)) {
-                            res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
-                                    userId);
-                        }
-                    }
-                    pi.services = ArrayUtils.trimToSize(res, num);
-                }
-            }
-        }
-        if ((flags & PackageManager.GET_PROVIDERS) != 0) {
-            if (pkg.getProviders() != null) {
-                final int size = pkg.getProviders().size();
-                if (size > 0) {
-                    int num = 0;
-                    final ProviderInfo[] res = new ProviderInfo[size];
-                    for (int i = 0; i < size; i++) {
-                        final ComponentParseUtils.ParsedProvider pr = pkg.getProviders()
-                                .get(i);
-                        if (state.isMatch(pkg.isSystem(), pkg.isEnabled(), pr, flags)) {
-                            res[num++] = generateProviderInfo(pkg, pr, flags, state,
-                                    applicationInfo, userId);
-                        }
-                    }
-                    pi.providers = ArrayUtils.trimToSize(res, num);
-                }
-            }
-        }
-        if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
-            if (pkg.getInstrumentations() != null) {
-                int N = pkg.getInstrumentations().size();
-                if (N > 0) {
-                    pi.instrumentation = new InstrumentationInfo[N];
-                    for (int i = 0; i < N; i++) {
-                        pi.instrumentation[i] = generateInstrumentationInfo(
-                                pkg.getInstrumentations().get(i), pkg, flags);
-                    }
-                }
-            }
-        }
-        if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
-            if (pkg.getPermissions() != null) {
-                int N = ArrayUtils.size(pkg.getPermissions());
-                if (N > 0) {
-                    pi.permissions = new PermissionInfo[N];
-                    for (int i = 0; i < N; i++) {
-                        pi.permissions[i] = generatePermissionInfo(
-                                pkg.getPermissions().get(i),
-                                flags
-                        );
-                    }
-                }
-            }
-            if (pkg.getRequestedPermissions() != null) {
-                int N = pkg.getRequestedPermissions().size();
-                if (N > 0) {
-                    pi.requestedPermissions = new String[N];
-                    pi.requestedPermissionsFlags = new int[N];
-                    for (int i = 0; i < N; i++) {
-                        final String perm = pkg.getRequestedPermissions().get(i);
-                        pi.requestedPermissions[i] = perm;
-                        // The notion of required permissions is deprecated but for compatibility.
-                        pi.requestedPermissionsFlags[i] |=
-                                PackageInfo.REQUESTED_PERMISSION_REQUIRED;
-                        if (grantedPermissions != null && grantedPermissions.contains(perm)) {
-                            pi.requestedPermissionsFlags[i] |=
-                                    PackageInfo.REQUESTED_PERMISSION_GRANTED;
-                        }
-                    }
-                }
-            }
-        }
-
-        PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();
-        // deprecated method of getting signing certificates
-        if ((flags & PackageManager.GET_SIGNATURES) != 0) {
-            if (signingDetails.hasPastSigningCertificates()) {
-                // Package has included signing certificate rotation information.  Return the oldest
-                // cert so that programmatic checks keep working even if unaware of key rotation.
-                pi.signatures = new Signature[1];
-                pi.signatures[0] = signingDetails.pastSigningCertificates[0];
-            } else if (signingDetails.hasSignatures()) {
-                // otherwise keep old behavior
-                int numberOfSigs = signingDetails.signatures.length;
-                pi.signatures = new Signature[numberOfSigs];
-                System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,
-                        numberOfSigs);
-            }
-        }
-
-        // replacement for GET_SIGNATURES
-        if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
-            if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {
-                // only return a valid SigningInfo if there is signing information to report
-                pi.signingInfo = new SigningInfo(signingDetails);
-            } else {
-                pi.signingInfo = null;
-            }
-        }
-
-        return pi;
-    }
-
-    @Nullable
-    public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
-            @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
-
-        if (pkg == null) return null;
-        if (!checkUseInstalledOrHidden(pkg, state, flags) || !pkg.isMatch(flags)) {
-            return null;
-        }
-
-        // Make shallow copy so we can store the metadata/libraries safely
-        ApplicationInfo ai = pkg.toAppInfoWithoutState();
-        ai.initForUser(userId);
-        if ((flags & PackageManager.GET_META_DATA) == 0) {
-            ai.metaData = null;
-        }
-        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
-            ai.sharedLibraryFiles = null;
-            ai.sharedLibraryInfos = null;
-        }
-        if (state.stopped) {
-            ai.flags |= ApplicationInfo.FLAG_STOPPED;
-        } else {
-            ai.flags &= ~ApplicationInfo.FLAG_STOPPED;
-        }
-        updateApplicationInfo(ai, flags, state);
-
-        return ai;
-    }
-
-    private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
-            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
-            @Nullable ApplicationInfo applicationInfo, int userId) {
-        if (a == null) return null;
-        if (!checkUseInstalledOrHidden(pkg, state, flags)) {
-            return null;
-        }
-        if (applicationInfo == null) {
-            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
-        }
-        // Make shallow copies so we can store the metadata safely
-        ActivityInfo ai = new ActivityInfo();
-        assignSharedFieldsForComponentInfo(ai, a);
-        ai.targetActivity = a.targetActivity;
-        ai.processName = a.getProcessName();
-        ai.exported = a.exported;
-        ai.theme = a.theme;
-        ai.uiOptions = a.uiOptions;
-        ai.parentActivityName = a.parentActivityName;
-        ai.permission = a.getPermission();
-        ai.taskAffinity = a.taskAffinity;
-        ai.flags = a.flags;
-        ai.privateFlags = a.privateFlags;
-        ai.launchMode = a.launchMode;
-        ai.documentLaunchMode = a.documentLaunchMode;
-        ai.maxRecents = a.maxRecents;
-        ai.configChanges = a.configChanges;
-        ai.softInputMode = a.softInputMode;
-        ai.persistableMode = a.persistableMode;
-        ai.lockTaskLaunchMode = a.lockTaskLaunchMode;
-        ai.screenOrientation = a.screenOrientation;
-        ai.resizeMode = a.resizeMode;
-        ai.maxAspectRatio = a.maxAspectRatio;
-        ai.minAspectRatio = a.minAspectRatio;
-        ai.requestedVrComponent = a.requestedVrComponent;
-        ai.rotationAnimation = a.rotationAnimation;
-        ai.colorMode = a.colorMode;
-        ai.preferMinimalPostProcessing = a.preferMinimalPostProcessing;
-        ai.windowLayout = a.windowLayout;
-        ai.metaData = a.metaData;
-        ai.applicationInfo = applicationInfo;
-        return ai;
-    }
-
-    public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
-            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
-        return generateActivityInfo(pkg, a, flags, state, null, userId);
-    }
-
-    private static ServiceInfo generateServiceInfo(AndroidPackage pkg,
-            ComponentParseUtils.ParsedService s, @PackageManager.ComponentInfoFlags int flags,
-            PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId) {
-        if (s == null) return null;
-        if (!checkUseInstalledOrHidden(pkg, state, flags)) {
-            return null;
-        }
-        if (applicationInfo == null) {
-            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
-        }
-        // Make shallow copies so we can store the metadata safely
-        ServiceInfo si = new ServiceInfo();
-        assignSharedFieldsForComponentInfo(si, s);
-        si.exported = s.exported;
-        si.flags = s.flags;
-        si.metaData = s.metaData;
-        si.permission = s.getPermission();
-        si.processName = s.getProcessName();
-        si.mForegroundServiceType = s.foregroundServiceType;
-        si.metaData = s.metaData;
-        si.applicationInfo = applicationInfo;
-        return si;
-    }
-
-    public static ServiceInfo generateServiceInfo(AndroidPackage pkg,
-            ComponentParseUtils.ParsedService s, @PackageManager.ComponentInfoFlags int flags,
-            PackageUserState state, int userId) {
-        return generateServiceInfo(pkg, s, flags, state, null, userId);
-    }
-
-    private static ProviderInfo generateProviderInfo(AndroidPackage pkg,
-            ComponentParseUtils.ParsedProvider p, @PackageManager.ComponentInfoFlags int flags,
-            PackageUserState state, @Nullable ApplicationInfo applicationInfo, int userId) {
-        if (p == null) return null;
-        if (!checkUseInstalledOrHidden(pkg, state, flags)) {
-            return null;
-        }
-        if (applicationInfo == null) {
-            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
-        }
-        // Make shallow copies so we can store the metadata safely
-        ProviderInfo pi = new ProviderInfo();
-        assignSharedFieldsForComponentInfo(pi, p);
-        pi.exported = p.exported;
-        pi.flags = p.flags;
-        pi.processName = p.getProcessName();
-        pi.authority = p.getAuthority();
-        pi.isSyncable = p.isSyncable;
-        pi.readPermission = p.getReadPermission();
-        pi.writePermission = p.getWritePermission();
-        pi.grantUriPermissions = p.grantUriPermissions;
-        pi.forceUriPermissions = p.forceUriPermissions;
-        pi.multiprocess = p.multiProcess;
-        pi.initOrder = p.initOrder;
-        pi.uriPermissionPatterns = p.uriPermissionPatterns;
-        pi.pathPermissions = p.pathPermissions;
-        pi.metaData = p.metaData;
-        if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
-            pi.uriPermissionPatterns = null;
-        }
-        pi.applicationInfo = applicationInfo;
-        return pi;
-    }
-
-    public static ProviderInfo generateProviderInfo(AndroidPackage pkg,
-            ComponentParseUtils.ParsedProvider p, @PackageManager.ComponentInfoFlags int flags,
-            PackageUserState state, int userId) {
-        return generateProviderInfo(pkg, p, flags, state, null, userId);
-    }
-
-    public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
-            AndroidPackage pkg, @PackageManager.ComponentInfoFlags int flags) {
-        if (i == null) return null;
-
-        InstrumentationInfo ii = new InstrumentationInfo();
-        assignSharedFieldsForPackageItemInfo(ii, i);
-        ii.targetPackage = i.getTargetPackage();
-        ii.targetProcesses = i.getTargetProcesses();
-        ii.handleProfiling = i.handleProfiling;
-        ii.functionalTest = i.functionalTest;
-
-        ii.sourceDir = pkg.getBaseCodePath();
-        ii.publicSourceDir = pkg.getBaseCodePath();
-        ii.splitNames = pkg.getSplitNames();
-        ii.splitSourceDirs = pkg.getSplitCodePaths();
-        ii.splitPublicSourceDirs = pkg.getSplitCodePaths();
-        ii.splitDependencies = pkg.getSplitDependencies();
-        ii.dataDir = pkg.getDataDir();
-        ii.deviceProtectedDataDir = pkg.getDeviceProtectedDataDir();
-        ii.credentialProtectedDataDir = pkg.getCredentialProtectedDataDir();
-        ii.primaryCpuAbi = pkg.getPrimaryCpuAbi();
-        ii.secondaryCpuAbi = pkg.getSecondaryCpuAbi();
-        ii.nativeLibraryDir = pkg.getNativeLibraryDir();
-        ii.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
-
-        if ((flags & PackageManager.GET_META_DATA) == 0) {
-            return ii;
-        }
-        ii.metaData = i.metaData;
-        return ii;
-    }
-
-    public static ArrayMap<String, ProcessInfo> generateProcessInfo(
-            ArrayMap<String, ComponentParseUtils.ParsedProcess> procs,
-            @PackageManager.ComponentInfoFlags int flags) {
-        if (procs == null) {
-            return null;
-        }
-
-        final int numProcs = procs.size();
-        ArrayMap<String, ProcessInfo> retProcs = new ArrayMap(numProcs);
-        for (int i = 0; i < numProcs; i++) {
-            ComponentParseUtils.ParsedProcess proc = procs.valueAt(i);
-            retProcs.put(proc.name, new ProcessInfo(proc.name,
-                    proc.deniedPermissions != null
-                            ? new ArraySet<>(proc.deniedPermissions) : null));
-        }
-        return retProcs;
-    }
-
-    public static PermissionInfo generatePermissionInfo(ParsedPermission p,
-            @PackageManager.ComponentInfoFlags int flags) {
-        if (p == null) return null;
-
-        PermissionInfo pi = new PermissionInfo(p.backgroundPermission);
-        assignSharedFieldsForPackageItemInfo(pi, p);
-        pi.group = p.getGroup();
-        pi.requestRes = p.requestRes;
-        pi.protectionLevel = p.protectionLevel;
-        pi.descriptionRes = p.descriptionRes;
-        pi.flags = p.flags;
-
-        if ((flags & PackageManager.GET_META_DATA) == 0) {
-            return pi;
-        }
-        pi.metaData = p.metaData;
-        return pi;
-    }
-
-    public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
-            @PackageManager.ComponentInfoFlags int flags) {
-        if (pg == null) return null;
-
-        PermissionGroupInfo pgi = new PermissionGroupInfo(
-                pg.requestDetailResourceId,
-                pg.backgroundRequestResourceId,
-                pg.backgroundRequestDetailResourceId
-        );
-        assignSharedFieldsForPackageItemInfo(pgi, pg);
-        pgi.descriptionRes = pg.descriptionRes;
-        pgi.priority = pg.priority;
-        pgi.requestRes = pg.requestRes;
-        pgi.flags = pg.flags;
-
-        if ((flags & PackageManager.GET_META_DATA) == 0) {
-            return pgi;
-        }
-        pgi.metaData = pg.metaData;
-        return pgi;
-    }
-
-    private static void updateApplicationInfo(ApplicationInfo ai,
-            @PackageManager.ApplicationInfoFlags int flags,
-            PackageUserState state) {
-        // CompatibilityMode is global state.
-        if (!PackageParser.sCompatibilityModeEnabled) {
-            ai.disableCompatibilityMode();
-        }
-        if (state.installed) {
-            ai.flags |= ApplicationInfo.FLAG_INSTALLED;
-        } else {
-            ai.flags &= ~ApplicationInfo.FLAG_INSTALLED;
-        }
-        if (state.suspended) {
-            ai.flags |= ApplicationInfo.FLAG_SUSPENDED;
-        } else {
-            ai.flags &= ~ApplicationInfo.FLAG_SUSPENDED;
-        }
-        if (state.instantApp) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_INSTANT;
-        } else {
-            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_INSTANT;
-        }
-        if (state.virtualPreload) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
-        } else {
-            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD;
-        }
-        if (state.hidden) {
-            ai.privateFlags |= ApplicationInfo.PRIVATE_FLAG_HIDDEN;
-        } else {
-            ai.privateFlags &= ~ApplicationInfo.PRIVATE_FLAG_HIDDEN;
-        }
-        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
-            ai.enabled = true;
-        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
-            ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
-        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
-                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
-            ai.enabled = false;
-        }
-        ai.enabledSetting = state.enabled;
-        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
-            ai.category = state.categoryHint;
-        }
-        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
-            ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
-        }
-        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
-        ai.resourceDirs = state.getAllOverlayPaths();
-        ai.icon = (PackageParser.sUseRoundIcon && ai.roundIconRes != 0)
-                ? ai.roundIconRes : ai.iconRes;
-    }
-
-    private static void assignSharedFieldsForPackageItemInfo(PackageItemInfo packageItemInfo,
-            ComponentParseUtils.ParsedComponent parsedComponent) {
-        packageItemInfo.banner = parsedComponent.banner;
-        packageItemInfo.icon = parsedComponent.icon;
-        packageItemInfo.labelRes = parsedComponent.labelRes;
-        packageItemInfo.logo = parsedComponent.logo;
-        packageItemInfo.name = parsedComponent.className;
-        packageItemInfo.nonLocalizedLabel = parsedComponent.nonLocalizedLabel;
-        packageItemInfo.packageName = parsedComponent.getPackageName();
-    }
-
-    private static void assignSharedFieldsForComponentInfo(ComponentInfo componentInfo,
-            ComponentParseUtils.ParsedComponent parsedComponent) {
-        assignSharedFieldsForPackageItemInfo(componentInfo, parsedComponent);
-        componentInfo.descriptionRes = parsedComponent.descriptionRes;
-        componentInfo.directBootAware = parsedComponent.directBootAware;
-        componentInfo.enabled = parsedComponent.enabled;
-        componentInfo.splitName = parsedComponent.getSplitName();
-    }
-
-}
diff --git a/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
new file mode 100644
index 0000000..e7d91c2
--- /dev/null
+++ b/core/java/android/content/pm/parsing/PackageInfoWithoutStateUtils.java
@@ -0,0 +1,697 @@
+/*
+ * 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.content.pm.parsing;
+
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.apex.ApexInfo;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FallbackCategoryProvider;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.SELinuxUtil;
+import android.content.pm.ServiceInfo;
+import android.content.pm.Signature;
+import android.content.pm.SigningInfo;
+import android.content.pm.parsing.ParsingPackage;
+import android.os.Environment;
+import android.os.UserHandle;
+
+import com.android.internal.util.ArrayUtils;
+import android.content.pm.parsing.component.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+
+import libcore.util.EmptyArray;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Set;
+
+/** @hide **/
+public class PackageInfoWithoutStateUtils {
+
+    @Nullable
+    public static PackageInfo generate(ParsingPackageRead pkg, int[] gids,
+            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+            Set<String> grantedPermissions, PackageUserState state, int userId) {
+        return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime, grantedPermissions,
+                state, userId, null);
+    }
+
+    @Nullable
+    public static PackageInfo generate(ParsingPackageRead pkg, ApexInfo apexInfo, int flags) {
+        return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(),
+                new PackageUserState(), UserHandle.getCallingUserId(), apexInfo);
+    }
+
+    @Nullable
+    private static PackageInfo generateWithComponents(ParsingPackageRead pkg, int[] gids,
+            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+            Set<String> grantedPermissions, PackageUserState state, int userId,
+            @Nullable ApexInfo apexInfo) {
+        ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
+        if (applicationInfo == null) {
+            return null;
+        }
+        PackageInfo info = generateWithoutComponents(pkg, gids, flags, firstInstallTime,
+                lastUpdateTime, grantedPermissions, state, userId, apexInfo, applicationInfo);
+
+        if (info == null) {
+            return null;
+        }
+
+        if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
+            final int N = pkg.getActivities().size();
+            if (N > 0) {
+                int num = 0;
+                final ActivityInfo[] res = new ActivityInfo[N];
+                for (int i = 0; i < N; i++) {
+                    final ParsedActivity a = pkg.getActivities().get(i);
+                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
+                            flags)) {
+                        if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
+                                a.getName())) {
+                            continue;
+                        }
+                        res[num++] = generateActivityInfo(pkg, a, flags, state,
+                                applicationInfo, userId);
+                    }
+                }
+                info.activities = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_RECEIVERS) != 0) {
+            final int size = pkg.getReceivers().size();
+            if (size > 0) {
+                int num = 0;
+                final ActivityInfo[] res = new ActivityInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedActivity a = pkg.getReceivers().get(i);
+                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), a,
+                            flags)) {
+                        res[num++] = generateActivityInfo(pkg, a, flags, state,
+                                applicationInfo, userId);
+                    }
+                }
+                info.receivers = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_SERVICES) != 0) {
+            final int size = pkg.getServices().size();
+            if (size > 0) {
+                int num = 0;
+                final ServiceInfo[] res = new ServiceInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedService s = pkg.getServices().get(i);
+                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), s,
+                            flags)) {
+                        res[num++] = generateServiceInfo(pkg, s, flags, state,
+                                applicationInfo, userId);
+                    }
+                }
+                info.services = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_PROVIDERS) != 0) {
+            final int size = pkg.getProviders().size();
+            if (size > 0) {
+                int num = 0;
+                final ProviderInfo[] res = new ProviderInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedProvider pr = pkg.getProviders()
+                            .get(i);
+                    if (ComponentParseUtils.isMatch(state, false, pkg.isEnabled(), pr,
+                            flags)) {
+                        res[num++] = generateProviderInfo(pkg, pr, flags, state,
+                                applicationInfo, userId);
+                    }
+                }
+                info.providers = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
+            int N = pkg.getInstrumentations().size();
+            if (N > 0) {
+                info.instrumentation = new InstrumentationInfo[N];
+                for (int i = 0; i < N; i++) {
+                    info.instrumentation[i] = generateInstrumentationInfo(
+                            pkg.getInstrumentations().get(i), pkg, flags, userId);
+                }
+            }
+        }
+
+        return info;
+    }
+
+    @Nullable
+    public static PackageInfo generateWithoutComponents(ParsingPackageRead pkg, int[] gids,
+            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+            Set<String> grantedPermissions, PackageUserState state, int userId,
+            @Nullable ApexInfo apexInfo, @NonNull ApplicationInfo applicationInfo) {
+        if (!checkUseInstalled(pkg, state, flags)) {
+            return null;
+        }
+
+        PackageInfo pi = new PackageInfo();
+        pi.packageName = pkg.getPackageName();
+        pi.splitNames = pkg.getSplitNames();
+        pi.versionCode = pkg.getVersionCode();
+        pi.versionCodeMajor = pkg.getVersionCodeMajor();
+        pi.baseRevisionCode = pkg.getBaseRevisionCode();
+        pi.splitRevisionCodes = pkg.getSplitRevisionCodes();
+        pi.versionName = pkg.getVersionName();
+        pi.sharedUserId = pkg.getSharedUserId();
+        pi.sharedUserLabel = pkg.getSharedUserLabel();
+        pi.applicationInfo = applicationInfo;
+        pi.installLocation = pkg.getInstallLocation();
+        if ((pi.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0
+                || (pi.applicationInfo.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0) {
+            pi.requiredForAllUsers = pkg.isRequiredForAllUsers();
+        }
+        pi.restrictedAccountType = pkg.getRestrictedAccountType();
+        pi.requiredAccountType = pkg.getRequiredAccountType();
+        pi.overlayTarget = pkg.getOverlayTarget();
+        pi.targetOverlayableName = pkg.getOverlayTargetName();
+        pi.overlayCategory = pkg.getOverlayCategory();
+        pi.overlayPriority = pkg.getOverlayPriority();
+        pi.mOverlayIsStatic = pkg.isOverlayIsStatic();
+        pi.compileSdkVersion = pkg.getCompileSdkVersion();
+        pi.compileSdkVersionCodename = pkg.getCompileSdkVersionCodeName();
+        pi.firstInstallTime = firstInstallTime;
+        pi.lastUpdateTime = lastUpdateTime;
+        if ((flags & PackageManager.GET_GIDS) != 0) {
+            pi.gids = gids;
+        }
+        if ((flags & PackageManager.GET_CONFIGURATIONS) != 0) {
+            int size = pkg.getConfigPreferences().size();
+            if (size > 0) {
+                pi.configPreferences = new ConfigurationInfo[size];
+                pkg.getConfigPreferences().toArray(pi.configPreferences);
+            }
+            size = pkg.getReqFeatures().size();
+            if (size > 0) {
+                pi.reqFeatures = new FeatureInfo[size];
+                pkg.getReqFeatures().toArray(pi.reqFeatures);
+            }
+            size = pkg.getFeatureGroups().size();
+            if (size > 0) {
+                pi.featureGroups = new FeatureGroupInfo[size];
+                pkg.getFeatureGroups().toArray(pi.featureGroups);
+            }
+        }
+        if ((flags & PackageManager.GET_PERMISSIONS) != 0) {
+            int size = ArrayUtils.size(pkg.getPermissions());
+            if (size > 0) {
+                pi.permissions = new PermissionInfo[size];
+                for (int i = 0; i < size; i++) {
+                    pi.permissions[i] = generatePermissionInfo(pkg.getPermissions().get(i),
+                            flags);
+                }
+            }
+            size = pkg.getRequestedPermissions().size();
+            if (size > 0) {
+                pi.requestedPermissions = new String[size];
+                pi.requestedPermissionsFlags = new int[size];
+                for (int i = 0; i < size; i++) {
+                    final String perm = pkg.getRequestedPermissions().get(i);
+                    pi.requestedPermissions[i] = perm;
+                    // The notion of required permissions is deprecated but for compatibility.
+                    pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_REQUIRED;
+                    if (grantedPermissions != null && grantedPermissions.contains(perm)) {
+                        pi.requestedPermissionsFlags[i] |= PackageInfo.REQUESTED_PERMISSION_GRANTED;
+                    }
+                }
+            }
+        }
+
+        if (apexInfo != null) {
+            File apexFile = new File(apexInfo.modulePath);
+
+            pi.applicationInfo.sourceDir = apexFile.getPath();
+            pi.applicationInfo.publicSourceDir = apexFile.getPath();
+            if (apexInfo.isFactory) {
+                pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
+            } else {
+                pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_SYSTEM;
+            }
+            if (apexInfo.isActive) {
+                pi.applicationInfo.flags |= ApplicationInfo.FLAG_INSTALLED;
+            } else {
+                pi.applicationInfo.flags &= ~ApplicationInfo.FLAG_INSTALLED;
+            }
+            pi.isApex = true;
+        }
+
+        PackageParser.SigningDetails signingDetails = pkg.getSigningDetails();
+        // deprecated method of getting signing certificates
+        if ((flags & PackageManager.GET_SIGNATURES) != 0) {
+            if (signingDetails.hasPastSigningCertificates()) {
+                // Package has included signing certificate rotation information.  Return the oldest
+                // cert so that programmatic checks keep working even if unaware of key rotation.
+                pi.signatures = new Signature[1];
+                pi.signatures[0] = signingDetails.pastSigningCertificates[0];
+            } else if (signingDetails.hasSignatures()) {
+                // otherwise keep old behavior
+                int numberOfSigs = signingDetails.signatures.length;
+                pi.signatures = new Signature[numberOfSigs];
+                System.arraycopy(signingDetails.signatures, 0, pi.signatures, 0,
+                        numberOfSigs);
+            }
+        }
+
+        // replacement for GET_SIGNATURES
+        if ((flags & PackageManager.GET_SIGNING_CERTIFICATES) != 0) {
+            if (signingDetails != PackageParser.SigningDetails.UNKNOWN) {
+                // only return a valid SigningInfo if there is signing information to report
+                pi.signingInfo = new SigningInfo(signingDetails);
+            } else {
+                pi.signingInfo = null;
+            }
+        }
+
+        return pi;
+    }
+
+    @Nullable
+    public static ApplicationInfo generateApplicationInfo(ParsingPackageRead pkg,
+            @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId) {
+        if (pkg == null) {
+            return null;
+        }
+
+        if (!checkUseInstalled(pkg, state, flags)) {
+            return null;
+        }
+
+        // Make shallow copy so we can store the metadata/libraries safely
+        ApplicationInfo ai = pkg.toAppInfoWithoutState();
+        // Init handles data directories
+        // TODO(b/135203078): Consolidate the data directory logic, remove initForUser
+        ai.initForUser(userId);
+
+        ai.flags = appInfoFlags(pkg);
+        ai.privateFlags = appInfoPrivateFlags(pkg);
+
+        if ((flags & PackageManager.GET_META_DATA) == 0) {
+            ai.metaData = null;
+        }
+        if ((flags & PackageManager.GET_SHARED_LIBRARY_FILES) == 0) {
+            ai.sharedLibraryFiles = null;
+            ai.sharedLibraryInfos = null;
+        }
+
+        // CompatibilityMode is global state.
+        if (!PackageParser.sCompatibilityModeEnabled) {
+            ai.disableCompatibilityMode();
+        }
+
+        ai.flags |= flag(state.stopped, ApplicationInfo.FLAG_STOPPED)
+                | flag(state.installed, ApplicationInfo.FLAG_INSTALLED)
+                | flag(state.suspended, ApplicationInfo.FLAG_SUSPENDED);
+        ai.privateFlags |= flag(state.instantApp, ApplicationInfo.PRIVATE_FLAG_INSTANT)
+                | flag(state.virtualPreload, ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD)
+                | flag(state.hidden, ApplicationInfo.PRIVATE_FLAG_HIDDEN);
+
+        if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_ENABLED) {
+            ai.enabled = true;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
+            ai.enabled = (flags & PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS) != 0;
+        } else if (state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
+                || state.enabled == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
+            ai.enabled = false;
+        }
+        ai.enabledSetting = state.enabled;
+        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
+            ai.category = state.categoryHint;
+        }
+        if (ai.category == ApplicationInfo.CATEGORY_UNDEFINED) {
+            ai.category = FallbackCategoryProvider.getFallbackCategory(ai.packageName);
+        }
+        ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
+        ai.resourceDirs = state.getOverlayPaths();
+
+        return ai;
+    }
+
+    @Nullable
+    public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId) {
+        if (a == null) return null;
+        if (!checkUseInstalled(pkg, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
+        }
+        // Make shallow copies so we can store the metadata safely
+        ActivityInfo ai = new ActivityInfo();
+        assignSharedFieldsForComponentInfo(ai, a);
+        ai.targetActivity = a.getTargetActivity();
+        ai.processName = a.getProcessName();
+        ai.exported = a.isExported();
+        ai.theme = a.getTheme();
+        ai.uiOptions = a.getUiOptions();
+        ai.parentActivityName = a.getParentActivityName();
+        ai.permission = a.getPermission();
+        ai.taskAffinity = a.getTaskAffinity();
+        ai.flags = a.getFlags();
+        ai.privateFlags = a.getPrivateFlags();
+        ai.launchMode = a.getLaunchMode();
+        ai.documentLaunchMode = a.getDocumentLaunchMode();
+        ai.maxRecents = a.getMaxRecents();
+        ai.configChanges = a.getConfigChanges();
+        ai.softInputMode = a.getSoftInputMode();
+        ai.persistableMode = a.getPersistableMode();
+        ai.lockTaskLaunchMode = a.getLockTaskLaunchMode();
+        ai.screenOrientation = a.getScreenOrientation();
+        ai.resizeMode = a.getResizeMode();
+        Float maxAspectRatio = a.getMaxAspectRatio();
+        ai.maxAspectRatio = maxAspectRatio != null ? maxAspectRatio : 0f;
+        Float minAspectRatio = a.getMinAspectRatio();
+        ai.minAspectRatio = minAspectRatio != null ? minAspectRatio : 0f;
+        ai.requestedVrComponent = a.getRequestedVrComponent();
+        ai.rotationAnimation = a.getRotationAnimation();
+        ai.colorMode = a.getColorMode();
+        ai.preferMinimalPostProcessing = a.isPreferMinimalPostProcessing();
+        ai.windowLayout = a.getWindowLayout();
+        ai.metaData = a.getMetaData();
+        ai.applicationInfo = applicationInfo;
+        return ai;
+    }
+
+    @Nullable
+    public static ActivityInfo generateActivityInfo(ParsingPackageRead pkg, ParsedActivity a,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
+        return generateActivityInfo(pkg, a, flags, state, null, userId);
+    }
+
+    @Nullable
+    public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId) {
+        if (s == null) return null;
+        if (!checkUseInstalled(pkg, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
+        }
+        // Make shallow copies so we can store the metadata safely
+        ServiceInfo si = new ServiceInfo();
+        assignSharedFieldsForComponentInfo(si, s);
+        si.exported = s.isExported();
+        si.flags = s.getFlags();
+        si.metaData = s.getMetaData();
+        si.permission = s.getPermission();
+        si.processName = s.getProcessName();
+        si.mForegroundServiceType = s.getForegroundServiceType();
+        si.applicationInfo = applicationInfo;
+        return si;
+    }
+
+    @Nullable
+    public static ServiceInfo generateServiceInfo(ParsingPackageRead pkg, ParsedService s,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
+        return generateServiceInfo(pkg, s, flags, state, null, userId);
+    }
+
+    @Nullable
+    public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId) {
+        if (p == null) return null;
+        if (!checkUseInstalled(pkg, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId);
+        }
+        // Make shallow copies so we can store the metadata safely
+        ProviderInfo pi = new ProviderInfo();
+        assignSharedFieldsForComponentInfo(pi, p);
+        pi.exported = p.isExported();
+        pi.flags = p.getFlags();
+        pi.processName = p.getProcessName();
+        pi.authority = p.getAuthority();
+        pi.isSyncable = p.isSyncable();
+        pi.readPermission = p.getReadPermission();
+        pi.writePermission = p.getWritePermission();
+        pi.grantUriPermissions = p.isGrantUriPermissions();
+        pi.forceUriPermissions = p.isForceUriPermissions();
+        pi.multiprocess = p.isMultiProcess();
+        pi.initOrder = p.getInitOrder();
+        pi.uriPermissionPatterns = p.getUriPermissionPatterns();
+        pi.pathPermissions = p.getPathPermissions();
+        pi.metaData = p.getMetaData();
+        if ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) == 0) {
+            pi.uriPermissionPatterns = null;
+        }
+        pi.applicationInfo = applicationInfo;
+        return pi;
+    }
+
+    @Nullable
+    public static ProviderInfo generateProviderInfo(ParsingPackageRead pkg, ParsedProvider p,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId) {
+        return generateProviderInfo(pkg, p, flags, state, null, userId);
+    }
+
+    @Nullable
+    public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
+            ParsingPackageRead pkg, @PackageManager.ComponentInfoFlags int flags, int userId) {
+        if (i == null) return null;
+
+        InstrumentationInfo ii = new InstrumentationInfo();
+        assignSharedFieldsForPackageItemInfo(ii, i);
+        ii.targetPackage = i.getTargetPackage();
+        ii.targetProcesses = i.getTargetProcesses();
+        ii.handleProfiling = i.isHandleProfiling();
+        ii.functionalTest = i.isFunctionalTest();
+
+        ii.sourceDir = pkg.getBaseCodePath();
+        ii.publicSourceDir = pkg.getBaseCodePath();
+        ii.splitNames = pkg.getSplitNames();
+        ii.splitSourceDirs = pkg.getSplitCodePaths();
+        ii.splitPublicSourceDirs = pkg.getSplitCodePaths();
+        ii.splitDependencies = pkg.getSplitDependencies();
+        ii.dataDir = getDataDir(pkg, userId).getAbsolutePath();
+        ii.deviceProtectedDataDir = getDeviceProtectedDataDir(pkg, userId).getAbsolutePath();
+        ii.credentialProtectedDataDir = getCredentialProtectedDataDir(pkg,
+                userId).getAbsolutePath();
+
+        if ((flags & PackageManager.GET_META_DATA) == 0) {
+            return ii;
+        }
+        ii.metaData = i.getMetaData();
+        return ii;
+    }
+
+    @Nullable
+    public static PermissionInfo generatePermissionInfo(ParsedPermission p,
+            @PackageManager.ComponentInfoFlags int flags) {
+        if (p == null) return null;
+
+        PermissionInfo pi = new PermissionInfo(p.getBackgroundPermission());
+
+        assignSharedFieldsForPackageItemInfo(pi, p);
+
+        pi.group = p.getGroup();
+        pi.requestRes = p.getRequestRes();
+        pi.protectionLevel = p.getProtectionLevel();
+        pi.descriptionRes = p.getDescriptionRes();
+        pi.flags = p.getFlags();
+
+        if ((flags & PackageManager.GET_META_DATA) == 0) {
+            return pi;
+        }
+        pi.metaData = p.getMetaData();
+        return pi;
+    }
+
+    @Nullable
+    public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
+            @PackageManager.ComponentInfoFlags int flags) {
+        if (pg == null) return null;
+
+        PermissionGroupInfo pgi = new PermissionGroupInfo(
+                pg.getRequestDetailResourceId(),
+                pg.getBackgroundRequestResourceId(),
+                pg.getBackgroundRequestDetailResourceId()
+        );
+
+        assignSharedFieldsForPackageItemInfo(pgi, pg);
+        pgi.descriptionRes = pg.getDescriptionRes();
+        pgi.priority = pg.getPriority();
+        pgi.requestRes = pg.getRequestRes();
+        pgi.flags = pg.getFlags();
+
+        if ((flags & PackageManager.GET_META_DATA) == 0) {
+            return pgi;
+        }
+        pgi.metaData = pg.getMetaData();
+        return pgi;
+    }
+
+    private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
+            @NonNull ParsedMainComponent mainComponent) {
+        assignSharedFieldsForPackageItemInfo(componentInfo, mainComponent);
+        componentInfo.descriptionRes = mainComponent.getDescriptionRes();
+        componentInfo.directBootAware = mainComponent.isDirectBootAware();
+        componentInfo.enabled = mainComponent.isEnabled();
+        componentInfo.splitName = mainComponent.getSplitName();
+    }
+
+    private static void assignSharedFieldsForPackageItemInfo(
+            @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component) {
+        packageItemInfo.nonLocalizedLabel = ComponentParseUtils.getNonLocalizedLabel(component);
+        packageItemInfo.icon = ComponentParseUtils.getIcon(component);
+
+        packageItemInfo.banner = component.getBanner();
+        packageItemInfo.labelRes = component.getLabelRes();
+        packageItemInfo.logo = component.getLogo();
+        packageItemInfo.name = component.getName();
+        packageItemInfo.packageName = component.getPackageName();
+    }
+
+    @CheckResult
+    private static int flag(boolean hasFlag, int flag) {
+        if (hasFlag) {
+            return flag;
+        } else {
+            return 0;
+        }
+    }
+
+    /** @see ApplicationInfo#flags */
+    public static int appInfoFlags(ParsingPackageRead pkg) {
+        // @formatter:off
+        return flag(pkg.isExternalStorage(), ApplicationInfo.FLAG_EXTERNAL_STORAGE)
+                | flag(pkg.isBaseHardwareAccelerated(), ApplicationInfo.FLAG_HARDWARE_ACCELERATED)
+                | flag(pkg.isAllowBackup(), ApplicationInfo.FLAG_ALLOW_BACKUP)
+                | flag(pkg.isKillAfterRestore(), ApplicationInfo.FLAG_KILL_AFTER_RESTORE)
+                | flag(pkg.isRestoreAnyVersion(), ApplicationInfo.FLAG_RESTORE_ANY_VERSION)
+                | flag(pkg.isFullBackupOnly(), ApplicationInfo.FLAG_FULL_BACKUP_ONLY)
+                | flag(pkg.isPersistent(), ApplicationInfo.FLAG_PERSISTENT)
+                | flag(pkg.isDebuggable(), ApplicationInfo.FLAG_DEBUGGABLE)
+                | flag(pkg.isVmSafeMode(), ApplicationInfo.FLAG_VM_SAFE_MODE)
+                | flag(pkg.isHasCode(), ApplicationInfo.FLAG_HAS_CODE)
+                | flag(pkg.isAllowTaskReparenting(), ApplicationInfo.FLAG_ALLOW_TASK_REPARENTING)
+                | flag(pkg.isAllowClearUserData(), ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA)
+                | flag(pkg.isLargeHeap(), ApplicationInfo.FLAG_LARGE_HEAP)
+                | flag(pkg.isUsesCleartextTraffic(), ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC)
+                | flag(pkg.isSupportsRtl(), ApplicationInfo.FLAG_SUPPORTS_RTL)
+                | flag(pkg.isTestOnly(), ApplicationInfo.FLAG_TEST_ONLY)
+                | flag(pkg.isMultiArch(), ApplicationInfo.FLAG_MULTIARCH)
+                | flag(pkg.isExtractNativeLibs(), ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS)
+                | flag(pkg.isGame(), ApplicationInfo.FLAG_IS_GAME)
+                | flag(pkg.isSupportsSmallScreens(), ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS)
+                | flag(pkg.isSupportsNormalScreens(), ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS)
+                | flag(pkg.isSupportsLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS)
+                | flag(pkg.isSupportsExtraLargeScreens(), ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS)
+                | flag(pkg.isResizeable(), ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS)
+                | flag(pkg.isAnyDensity(), ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES);
+        // @formatter:on
+    }
+
+    /** @see ApplicationInfo#privateFlags */
+    public static int appInfoPrivateFlags(ParsingPackageRead pkg) {
+        // @formatter:off
+        int privateFlags = flag(pkg.isStaticSharedLibrary(), ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY)
+                | flag(pkg.isOverlay(), ApplicationInfo.PRIVATE_FLAG_IS_RESOURCE_OVERLAY)
+                | flag(pkg.isIsolatedSplitLoading(), ApplicationInfo.PRIVATE_FLAG_ISOLATED_SPLIT_LOADING)
+                | flag(pkg.isHasDomainUrls(), ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS)
+                | flag(pkg.isProfileableByShell(), ApplicationInfo.PRIVATE_FLAG_PROFILEABLE_BY_SHELL)
+                | flag(pkg.isBackupInForeground(), ApplicationInfo.PRIVATE_FLAG_BACKUP_IN_FOREGROUND)
+                | flag(pkg.isUseEmbeddedDex(), ApplicationInfo.PRIVATE_FLAG_USE_EMBEDDED_DEX)
+                | flag(pkg.isDefaultToDeviceProtectedStorage(), ApplicationInfo.PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE)
+                | flag(pkg.isDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE)
+                | flag(pkg.isPartiallyDirectBootAware(), ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE)
+                | flag(pkg.isAllowClearUserDataOnFailedRestore(), ApplicationInfo.PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE)
+                | flag(pkg.isAllowAudioPlaybackCapture(), ApplicationInfo.PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE)
+                | flag(pkg.isRequestLegacyExternalStorage(), ApplicationInfo.PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE)
+                | flag(pkg.isUsesNonSdkApi(), ApplicationInfo.PRIVATE_FLAG_USES_NON_SDK_API)
+                | flag(pkg.isHasFragileUserData(), ApplicationInfo.PRIVATE_FLAG_HAS_FRAGILE_USER_DATA)
+                | flag(pkg.isCantSaveState(), ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE)
+                | flag(pkg.isResizeableActivityViaSdkVersion(), ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION)
+                | flag(pkg.isAllowNativeHeapPointerTagging(), ApplicationInfo.PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING);
+        // @formatter:on
+
+        Boolean resizeableActivity = pkg.getResizeableActivity();
+        if (resizeableActivity != null) {
+            if (resizeableActivity) {
+                privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE;
+            } else {
+                privateFlags |= ApplicationInfo.PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE;
+            }
+        }
+
+        return privateFlags;
+    }
+
+    private static boolean checkUseInstalled(ParsingPackageRead pkg, PackageUserState state,
+            @PackageManager.PackageInfoFlags int flags) {
+        // If available for the target user
+        return state.isAvailable(flags);
+    }
+
+    @NonNull
+    public static File getDataDir(ParsingPackageRead pkg, int userId) {
+        if ("android".equals(pkg.getPackageName())) {
+            return Environment.getDataSystemDirectory();
+        }
+
+        if (pkg.isDefaultToDeviceProtectedStorage()
+                && PackageManager.APPLY_DEFAULT_TO_DEVICE_PROTECTED_STORAGE) {
+            return getDeviceProtectedDataDir(pkg, userId);
+        } else {
+            return getCredentialProtectedDataDir(pkg, userId);
+        }
+    }
+
+    @NonNull
+    public static File getDeviceProtectedDataDir(ParsingPackageRead pkg, int userId) {
+        return Environment.getDataUserDePackageDirectory(pkg.getVolumeUuid(), userId,
+                pkg.getPackageName());
+    }
+
+    @NonNull
+    public static File getCredentialProtectedDataDir(ParsingPackageRead pkg, int userId) {
+        return Environment.getDataUserCePackageDirectory(pkg.getVolumeUuid(), userId,
+                pkg.getPackageName());
+    }
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackage.java b/core/java/android/content/pm/parsing/ParsingPackage.java
index 74a2640..aa93d80 100644
--- a/core/java/android/content/pm/parsing/ParsingPackage.java
+++ b/core/java/android/content/pm/parsing/ParsingPackage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -16,35 +16,36 @@
 
 package android.content.pm.parsing;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Intent;
 import android.content.pm.ConfigurationInfo;
 import android.content.pm.FeatureGroupInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
 import android.os.Bundle;
-import android.util.ArrayMap;
-import android.util.ArraySet;
 import android.util.SparseArray;
 
 import java.security.PublicKey;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Methods used for mutation during direct package parsing.
  *
- * Java disallows defining this as an inner interface, so this must be a separate file.
- *
  * @hide
  */
-public interface ParsingPackage extends AndroidPackage {
+@SuppressWarnings("UnusedReturnValue")
+public interface ParsingPackage extends ParsingPackageRead {
 
     ParsingPackage addActivity(ParsedActivity parsedActivity);
 
@@ -66,18 +67,18 @@
 
     ParsingPackage addOverlayable(String overlayableName, String actorName);
 
-    ParsingPackage addFeature(ParsedFeature permission);
-
     ParsingPackage addPermission(ParsedPermission permission);
 
     ParsingPackage addPermissionGroup(ParsedPermissionGroup permissionGroup);
 
-    ParsingPackage addPreferredActivityFilter(ParsedActivityIntentInfo activityIntentInfo);
+    ParsingPackage addPreferredActivityFilter(String className, ParsedIntentInfo intentInfo);
 
     ParsingPackage addProtectedBroadcast(String protectedBroadcast);
 
     ParsingPackage addProvider(ParsedProvider parsedProvider);
 
+    ParsingPackage addFeature(ParsedFeature permission);
+
     ParsingPackage addReceiver(ParsedActivity parsedReceiver);
 
     ParsingPackage addReqFeature(FeatureInfo reqFeature);
@@ -102,7 +103,7 @@
 
     ParsingPackage addQueriesProvider(String authority);
 
-    ParsingPackage setProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> processes);
+    ParsingPackage setProcesses(@NonNull Map<String, ParsedProcess> processes);
 
     ParsingPackage asSplit(
             String[] splitNames,
@@ -111,7 +112,7 @@
             @Nullable SparseArray<int[]> splitDependencies
     );
 
-    ParsingPackage setAppMetaData(Bundle appMetaData);
+    ParsingPackage setMetaData(Bundle metaData);
 
     ParsingPackage setForceQueryable(boolean forceQueryable);
 
@@ -119,8 +120,6 @@
 
     ParsingPackage setMinAspectRatio(float minAspectRatio);
 
-    ParsingPackage setName(String name);
-
     ParsingPackage setPermission(String permission);
 
     ParsingPackage setProcessName(String processName);
@@ -137,9 +136,9 @@
 
     ParsingPackage setBaseHardwareAccelerated(boolean baseHardwareAccelerated);
 
-    ParsingPackage setActivitiesResizeModeResizeable(boolean resizeable);
+    ParsingPackage setResizeableActivity(Boolean resizeable);
 
-    ParsingPackage setActivitiesResizeModeResizeableViaSdkVersion(boolean resizeableViaSdkVersion);
+    ParsingPackage setResizeableActivityViaSdkVersion(boolean resizeableViaSdkVersion);
 
     ParsingPackage setAllowAudioPlaybackCapture(boolean allowAudioPlaybackCapture);
 
@@ -151,7 +150,7 @@
 
     ParsingPackage setAllowTaskReparenting(boolean allowTaskReparenting);
 
-    ParsingPackage setIsOverlay(boolean isOverlay);
+    ParsingPackage setOverlay(boolean isOverlay);
 
     ParsingPackage setBackupInForeground(boolean backupInForeground);
 
@@ -173,7 +172,7 @@
 
     ParsingPackage setHasFragileUserData(boolean hasFragileUserData);
 
-    ParsingPackage setIsGame(boolean isGame);
+    ParsingPackage setGame(boolean isGame);
 
     ParsingPackage setIsolatedSplitLoading(boolean isolatedSplitLoading);
 
@@ -221,8 +220,6 @@
 
     ParsingPackage setAppComponentFactory(String appComponentFactory);
 
-    ParsingPackage setApplicationVolumeUuid(String applicationVolumeUuid);
-
     ParsingPackage setBackupAgentName(String backupAgentName);
 
     ParsingPackage setBanner(int banner);
@@ -233,8 +230,6 @@
 
     ParsingPackage setClassName(String className);
 
-    ParsingPackage setCodePath(String codePath);
-
     ParsingPackage setCompatibleWidthLimitDp(int compatibleWidthLimitDp);
 
     ParsingPackage setDescriptionRes(int descriptionRes);
@@ -247,8 +242,6 @@
 
     ParsingPackage setHasDomainUrls(boolean hasDomainUrls);
 
-    ParsingPackage setIcon(int icon);
-
     ParsingPackage setIconRes(int iconRes);
 
     ParsingPackage setInstallLocation(int installLocation);
@@ -307,17 +300,17 @@
 
     ParsingPackage setSupportsSmallScreens(int supportsSmallScreens);
 
-    ParsingPackage setSupportsXLargeScreens(int supportsXLargeScreens);
+    ParsingPackage setSupportsExtraLargeScreens(int supportsExtraLargeScreens);
 
     ParsingPackage setTargetSandboxVersion(int targetSandboxVersion);
 
     ParsingPackage setTheme(int theme);
 
-    ParsingPackage setUpgradeKeySets(ArraySet<String> upgradeKeySets);
+    ParsingPackage setUpgradeKeySets(@NonNull Set<String> upgradeKeySets);
 
     ParsingPackage setUse32BitAbi(boolean use32BitAbi);
 
-    ParsingPackage setVolumeUuid(String volumeUuid);
+    ParsingPackage setVolumeUuid(@Nullable String volumeUuid);
 
     ParsingPackage setZygotePreloadName(String zygotePreloadName);
 
@@ -327,17 +320,16 @@
 
     ParsingPackage sortServices();
 
-    ParsedPackage hideAsParsed();
-
     ParsingPackage setBaseRevisionCode(int baseRevisionCode);
 
-    ParsingPackage setPreferredOrder(int preferredOrder);
-
     ParsingPackage setVersionName(String versionName);
 
     ParsingPackage setCompileSdkVersion(int compileSdkVersion);
 
     ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename);
 
-    boolean usesCompatibilityMode();
+    // TODO(b/135203078): This class no longer has access to ParsedPackage, find a replacement
+    //  for moving to the next step
+    @Deprecated
+    Object hideAsParsed();
 }
diff --git a/core/java/android/content/pm/parsing/ParsingPackageImpl.java b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
new file mode 100644
index 0000000..c3eea2b
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingPackageImpl.java
@@ -0,0 +1,2584 @@
+/*
+ * 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.content.pm.parsing;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.emptySet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.storage.StorageManager;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForBoolean;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringArray;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringList;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedStringValueMap;
+
+import java.security.PublicKey;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * The backing data for a package that was parsed from disk.
+ *
+ * The field nullability annotations here are for internal reference. For effective nullability,
+ * see the parent interfaces.
+ *
+ * TODO(b/135203078): Convert Lists used as sets into Sets, to better express intended use case
+ *
+ * @hide
+ */
+public class ParsingPackageImpl implements ParsingPackage, Parcelable {
+
+    private static final String TAG = "PackageImpl";
+
+    public static ForBoolean sForBoolean = Parcelling.Cache.getOrCreate(ForBoolean.class);
+    public static ForInternedString sForString = Parcelling.Cache.getOrCreate(
+            ForInternedString.class);
+    public static ForInternedStringArray sForStringArray = Parcelling.Cache.getOrCreate(
+            ForInternedStringArray.class);
+    public static ForInternedStringList sForStringList = Parcelling.Cache.getOrCreate(
+            ForInternedStringList.class);
+    public static ForInternedStringValueMap sForStringValueMap = Parcelling.Cache.getOrCreate(
+            ForInternedStringValueMap.class);
+    public static ForInternedStringSet sForStringSet = Parcelling.Cache.getOrCreate(
+            ForInternedStringSet.class);
+    protected static ParsedIntentInfo.StringPairListParceler sForIntentInfoPairs =
+            Parcelling.Cache.getOrCreate(ParsedIntentInfo.StringPairListParceler.class);
+
+    private static final Comparator<ParsedMainComponent> ORDER_COMPARATOR =
+            (first, second) -> Integer.compare(second.getOrder(), first.getOrder());
+
+    // These are objects because null represents not explicitly set
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean supportsSmallScreens;
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean supportsNormalScreens;
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean supportsLargeScreens;
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean supportsExtraLargeScreens;
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean resizeable;
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean anyDensity;
+
+    protected int versionCode;
+    protected int versionCodeMajor;
+    private int baseRevisionCode;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String versionName;
+
+    private int compileSdkVersion;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String compileSdkVersionCodeName;
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String packageName;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String realPackage;
+
+    @NonNull
+    protected String baseCodePath;
+
+    private boolean requiredForAllUsers;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String restrictedAccountType;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String requiredAccountType;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String overlayTarget;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String overlayTargetName;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String overlayCategory;
+    private int overlayPriority;
+    private boolean overlayIsStatic;
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringValueMap.class)
+    private Map<String, String> overlayables = emptyMap();
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String staticSharedLibName;
+    private long staticSharedLibVersion;
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> libraryNames = emptyList();
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    protected List<String> usesLibraries = emptyList();
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    protected List<String> usesOptionalLibraries = emptyList();
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> usesStaticLibraries = emptyList();
+    @Nullable
+    private long[] usesStaticLibrariesVersions;
+
+    @Nullable
+    private String[][] usesStaticLibrariesCertDigests;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String sharedUserId;
+
+    private int sharedUserLabel;
+    @NonNull
+    private List<ConfigurationInfo> configPreferences = emptyList();
+    @NonNull
+    private List<FeatureInfo> reqFeatures = emptyList();
+    @NonNull
+    private List<FeatureGroupInfo> featureGroups = emptyList();
+
+    @Nullable
+    private byte[] restrictUpdateHash;
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    protected List<String> originalPackages = emptyList();
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    protected List<String> adoptPermissions = emptyList();
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> requestedPermissions = emptyList();
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> implicitPermissions = emptyList();
+
+    @NonNull
+    private Set<String> upgradeKeySets = emptySet();
+    @NonNull
+    private Map<String, ArraySet<PublicKey>> keySetMapping = emptyMap();
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    protected List<String> protectedBroadcasts = emptyList();
+
+    @NonNull
+    protected List<ParsedActivity> activities = emptyList();
+
+    @NonNull
+    protected List<ParsedActivity> receivers = emptyList();
+
+    @NonNull
+    protected List<ParsedService> services = emptyList();
+
+    @NonNull
+    protected List<ParsedProvider> providers = emptyList();
+
+    @NonNull
+    private List<ParsedFeature> features = emptyList();
+
+    @NonNull
+    protected List<ParsedPermission> permissions = emptyList();
+
+    @NonNull
+    protected List<ParsedPermissionGroup> permissionGroups = emptyList();
+
+    @NonNull
+    protected List<ParsedInstrumentation> instrumentations = emptyList();
+
+    @NonNull
+    @DataClass.ParcelWith(ParsedIntentInfo.ListParceler.class)
+    private List<Pair<String, ParsedIntentInfo>> preferredActivityFilters = emptyList();
+
+    @NonNull
+    private Map<String, ParsedProcess> processes = emptyMap();
+
+    @Nullable
+    private Bundle metaData;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String volumeUuid;
+    @Nullable
+    private PackageParser.SigningDetails signingDetails;
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String codePath;
+
+    private boolean use32BitAbi;
+    private boolean visibleToInstantApps;
+
+    private boolean forceQueryable;
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<Intent> queriesIntents = emptyList();
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringList.class)
+    private List<String> queriesPackages = emptyList();
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedStringSet.class)
+    private Set<String> queriesProviders = emptySet();
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedStringArray.class)
+    private String[] splitClassLoaderNames;
+    @Nullable
+    protected String[] splitCodePaths;
+    @Nullable
+    private SparseArray<int[]> splitDependencies;
+    @Nullable
+    private int[] splitFlags;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedStringArray.class)
+    private String[] splitNames;
+    @Nullable
+    private int[] splitRevisionCodes;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String appComponentFactory;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String backupAgentName;
+    private int banner;
+    private int category;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String classLoaderName;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String className;
+    private int compatibleWidthLimitDp;
+    private int descriptionRes;
+    private boolean enabled;
+    private boolean crossProfile;
+    private int fullBackupContent;
+    private int iconRes;
+    private int installLocation = PackageParser.PARSE_DEFAULT_INSTALL_LOCATION;
+    private int labelRes;
+    private int largestWidthLimitDp;
+    private int logo;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String manageSpaceActivityName;
+    private float maxAspectRatio;
+    private float minAspectRatio;
+    private int minSdkVersion;
+    private int networkSecurityConfigRes;
+    @Nullable
+    private CharSequence nonLocalizedLabel;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String permission;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String processName;
+    private int requiresSmallestWidthDp;
+    private int roundIconRes;
+    private int targetSandboxVersion;
+    private int targetSdkVersion;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String taskAffinity;
+    private int theme;
+
+    private int uiOptions;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String zygotePreloadName;
+
+    private boolean externalStorage;
+    private boolean baseHardwareAccelerated;
+    private boolean allowBackup;
+    private boolean killAfterRestore;
+    private boolean restoreAnyVersion;
+    private boolean fullBackupOnly;
+    private boolean persistent;
+    private boolean debuggable;
+    private boolean vmSafeMode;
+    private boolean hasCode;
+    private boolean allowTaskReparenting;
+    private boolean allowClearUserData;
+    private boolean largeHeap;
+    private boolean usesCleartextTraffic;
+    private boolean supportsRtl;
+    private boolean testOnly;
+    private boolean multiArch;
+    private boolean extractNativeLibs;
+    private boolean game;
+
+    /**
+     * @see ParsingPackageRead#getResizeableActivity()
+     */
+    @Nullable
+    @DataClass.ParcelWith(ForBoolean.class)
+    private Boolean resizeableActivity;
+
+    private boolean staticSharedLibrary;
+    private boolean overlay;
+    private boolean isolatedSplitLoading;
+    private boolean hasDomainUrls;
+    private boolean profileableByShell;
+    private boolean backupInForeground;
+    private boolean useEmbeddedDex;
+    private boolean defaultToDeviceProtectedStorage;
+    private boolean directBootAware;
+    private boolean partiallyDirectBootAware;
+    private boolean resizeableActivityViaSdkVersion;
+    private boolean allowClearUserDataOnFailedRestore;
+    private boolean allowAudioPlaybackCapture;
+    private boolean requestLegacyExternalStorage;
+    private boolean usesNonSdkApi;
+    private boolean hasFragileUserData;
+    private boolean cantSaveState;
+    private boolean allowNativeHeapPointerTagging;
+    private boolean preserveLegacyExternalStorage;
+
+    // TODO(chiuwinson): Non-null
+    @Nullable
+    private ArraySet<String> mimeGroups;
+
+    @VisibleForTesting
+    public ParsingPackageImpl(@NonNull String packageName, @NonNull String baseCodePath,
+            @NonNull String codePath, @Nullable TypedArray manifestArray) {
+        this.packageName = TextUtils.safeIntern(packageName);
+        this.baseCodePath = TextUtils.safeIntern(baseCodePath);
+        this.codePath = TextUtils.safeIntern(codePath);
+
+        if (manifestArray != null) {
+            versionCode = manifestArray.getInteger(R.styleable.AndroidManifest_versionCode, 0);
+            versionCodeMajor = manifestArray.getInteger(
+                    R.styleable.AndroidManifest_versionCodeMajor, 0);
+            setBaseRevisionCode(
+                    manifestArray.getInteger(R.styleable.AndroidManifest_revisionCode, 0));
+            setVersionName(manifestArray.getNonConfigurationString(
+                    R.styleable.AndroidManifest_versionName, 0));
+
+            setCompileSdkVersion(manifestArray.getInteger(
+                    R.styleable.AndroidManifest_compileSdkVersion, 0));
+            setCompileSdkVersionCodename(manifestArray.getNonConfigurationString(
+                    R.styleable.AndroidManifest_compileSdkVersionCodename, 0));
+        }
+    }
+
+    public boolean isSupportsSmallScreens() {
+        if (supportsSmallScreens == null) {
+            return targetSdkVersion >= Build.VERSION_CODES.DONUT;
+        }
+
+        return supportsSmallScreens;
+    }
+
+    public boolean isSupportsNormalScreens() {
+        return supportsNormalScreens == null || supportsNormalScreens;
+    }
+
+    public boolean isSupportsLargeScreens() {
+        if (supportsLargeScreens == null) {
+            return targetSdkVersion >= Build.VERSION_CODES.DONUT;
+        }
+
+        return supportsLargeScreens;
+    }
+
+    public boolean isSupportsExtraLargeScreens() {
+        if (supportsExtraLargeScreens == null) {
+            return targetSdkVersion >= Build.VERSION_CODES.GINGERBREAD;
+        }
+
+        return supportsExtraLargeScreens;
+    }
+
+    public boolean isResizeable() {
+        if (resizeable == null) {
+            return targetSdkVersion >= Build.VERSION_CODES.DONUT;
+        }
+
+        return resizeable;
+    }
+
+    public boolean isAnyDensity() {
+        if (anyDensity == null) {
+            return targetSdkVersion >= Build.VERSION_CODES.DONUT;
+        }
+
+        return anyDensity;
+    }
+
+    @Override
+    public ParsingPackageImpl sortActivities() {
+        Collections.sort(this.activities, ORDER_COMPARATOR);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl sortReceivers() {
+        Collections.sort(this.receivers, ORDER_COMPARATOR);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl sortServices() {
+        Collections.sort(this.services, ORDER_COMPARATOR);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setVersionName(String versionName) {
+        this.versionName = TextUtils.safeIntern(versionName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackage setCompileSdkVersionCodename(String compileSdkVersionCodename) {
+        this.compileSdkVersionCodeName = TextUtils.safeIntern(compileSdkVersionCodename);
+        return this;
+    }
+
+    @Override
+    public Object hideAsParsed() {
+        // There is no equivalent for core-only parsing
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ParsingPackageImpl addConfigPreference(ConfigurationInfo configPreference) {
+        this.configPreferences = CollectionUtils.add(this.configPreferences, configPreference);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addReqFeature(FeatureInfo reqFeature) {
+        this.reqFeatures = CollectionUtils.add(this.reqFeatures, reqFeature);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addFeatureGroup(FeatureGroupInfo featureGroup) {
+        this.featureGroups = CollectionUtils.add(this.featureGroups, featureGroup);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addProtectedBroadcast(String protectedBroadcast) {
+        if (!this.protectedBroadcasts.contains(protectedBroadcast)) {
+            this.protectedBroadcasts = CollectionUtils.add(this.protectedBroadcasts,
+                    TextUtils.safeIntern(protectedBroadcast));
+        }
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addInstrumentation(ParsedInstrumentation instrumentation) {
+        this.instrumentations = CollectionUtils.add(this.instrumentations, instrumentation);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addOriginalPackage(String originalPackage) {
+        this.originalPackages = CollectionUtils.add(this.originalPackages,
+                TextUtils.safeIntern(originalPackage));
+        return this;
+    }
+
+    @Override
+    public ParsingPackage addOverlayable(String overlayableName, String actorName) {
+        this.overlayables = CollectionUtils.add(this.overlayables,
+                TextUtils.safeIntern(overlayableName), TextUtils.safeIntern(actorName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addAdoptPermission(String adoptPermission) {
+        this.adoptPermissions = CollectionUtils.add(this.adoptPermissions,
+                TextUtils.safeIntern(adoptPermission));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addPermission(ParsedPermission permission) {
+        this.permissions = CollectionUtils.add(this.permissions, permission);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addPermissionGroup(ParsedPermissionGroup permissionGroup) {
+        this.permissionGroups = CollectionUtils.add(this.permissionGroups, permissionGroup);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addRequestedPermission(String permission) {
+        this.requestedPermissions = CollectionUtils.add(this.requestedPermissions,
+                TextUtils.safeIntern(permission));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addImplicitPermission(String permission) {
+        this.implicitPermissions = CollectionUtils.add(this.implicitPermissions,
+                TextUtils.safeIntern(permission));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addKeySet(String keySetName, PublicKey publicKey) {
+        ArraySet<PublicKey> publicKeys = keySetMapping.get(keySetName);
+        if (publicKeys == null) {
+            publicKeys = new ArraySet<>();
+        }
+        publicKeys.add(publicKey);
+        keySetMapping = CollectionUtils.add(this.keySetMapping, keySetName, publicKeys);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addActivity(ParsedActivity parsedActivity) {
+        this.activities = CollectionUtils.add(this.activities, parsedActivity);
+        addMimeGroupsFromComponent(parsedActivity);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addReceiver(ParsedActivity parsedReceiver) {
+        this.receivers = CollectionUtils.add(this.receivers, parsedReceiver);
+        addMimeGroupsFromComponent(parsedReceiver);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addService(ParsedService parsedService) {
+        this.services = CollectionUtils.add(this.services, parsedService);
+        addMimeGroupsFromComponent(parsedService);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addProvider(ParsedProvider parsedProvider) {
+        this.providers = CollectionUtils.add(this.providers, parsedProvider);
+        addMimeGroupsFromComponent(parsedProvider);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addFeature(ParsedFeature feature) {
+        this.features = CollectionUtils.add(this.features, feature);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addLibraryName(String libraryName) {
+        this.libraryNames = CollectionUtils.add(this.libraryNames,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesOptionalLibrary(String libraryName) {
+        this.usesOptionalLibraries = CollectionUtils.add(this.usesOptionalLibraries,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesLibrary(String libraryName) {
+        this.usesLibraries = CollectionUtils.add(this.usesLibraries,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl removeUsesOptionalLibrary(String libraryName) {
+        this.usesOptionalLibraries = CollectionUtils.remove(this.usesOptionalLibraries,
+                libraryName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesStaticLibrary(String libraryName) {
+        this.usesStaticLibraries = CollectionUtils.add(this.usesStaticLibraries,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesStaticLibraryVersion(long version) {
+        this.usesStaticLibrariesVersions = ArrayUtils.appendLong(this.usesStaticLibrariesVersions,
+                version, true);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addUsesStaticLibraryCertDigests(String[] certSha256Digests) {
+        this.usesStaticLibrariesCertDigests = ArrayUtils.appendElement(String[].class,
+                this.usesStaticLibrariesCertDigests, certSha256Digests, true);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addPreferredActivityFilter(String className,
+            ParsedIntentInfo intentInfo) {
+        this.preferredActivityFilters = CollectionUtils.add(this.preferredActivityFilters,
+                Pair.create(className, intentInfo));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addQueriesIntent(Intent intent) {
+        this.queriesIntents = CollectionUtils.add(this.queriesIntents, intent);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addQueriesPackage(String packageName) {
+        this.queriesPackages = CollectionUtils.add(this.queriesPackages,
+                TextUtils.safeIntern(packageName));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl addQueriesProvider(String authority) {
+        this.queriesProviders = CollectionUtils.add(this.queriesProviders,
+                TextUtils.safeIntern(authority));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSupportsSmallScreens(int supportsSmallScreens) {
+        if (supportsSmallScreens == 1) {
+            return this;
+        }
+
+        this.supportsSmallScreens = supportsSmallScreens < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSupportsNormalScreens(int supportsNormalScreens) {
+        if (supportsNormalScreens == 1) {
+            return this;
+        }
+
+        this.supportsNormalScreens = supportsNormalScreens < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSupportsLargeScreens(int supportsLargeScreens) {
+        if (supportsLargeScreens == 1) {
+            return this;
+        }
+
+        this.supportsLargeScreens = supportsLargeScreens < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSupportsExtraLargeScreens(int supportsExtraLargeScreens) {
+        if (supportsExtraLargeScreens == 1) {
+            return this;
+        }
+
+        this.supportsExtraLargeScreens = supportsExtraLargeScreens < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setResizeable(int resizeable) {
+        if (resizeable == 1) {
+            return this;
+        }
+
+        this.resizeable = resizeable < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAnyDensity(int anyDensity) {
+        if (anyDensity == 1) {
+            return this;
+        }
+
+        this.anyDensity = anyDensity < 0;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl asSplit(
+            String[] splitNames,
+            String[] splitCodePaths,
+            int[] splitRevisionCodes,
+            SparseArray<int[]> splitDependencies
+    ) {
+        this.splitNames = splitNames;
+
+        if (this.splitNames != null) {
+            for (int index = 0; index < this.splitNames.length; index++) {
+                splitNames[index] = TextUtils.safeIntern(splitNames[index]);
+            }
+        }
+
+        this.splitCodePaths = splitCodePaths;
+        this.splitRevisionCodes = splitRevisionCodes;
+        this.splitDependencies = splitDependencies;
+
+        int count = splitNames.length;
+        this.splitFlags = new int[count];
+        this.splitClassLoaderNames = new String[count];
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSplitHasCode(int splitIndex, boolean splitHasCode) {
+        this.splitFlags[splitIndex] = splitHasCode
+                ? this.splitFlags[splitIndex] | ApplicationInfo.FLAG_HAS_CODE
+                : this.splitFlags[splitIndex] & ~ApplicationInfo.FLAG_HAS_CODE;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSplitClassLoaderName(int splitIndex, String classLoaderName) {
+        this.splitClassLoaderNames[splitIndex] = classLoaderName;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setProcessName(String processName) {
+        this.processName = TextUtils.safeIntern(processName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRealPackage(@Nullable String realPackage) {
+        this.realPackage = TextUtils.safeIntern(realPackage);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRestrictedAccountType(@Nullable String restrictedAccountType) {
+        this.restrictedAccountType = TextUtils.safeIntern(restrictedAccountType);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRequiredAccountType(@Nullable String requiredAccountType) {
+        this.requiredAccountType = TextUtils.nullIfEmpty(TextUtils.safeIntern(requiredAccountType));
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlayTarget(@Nullable String overlayTarget) {
+        this.overlayTarget = TextUtils.safeIntern(overlayTarget);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlayTargetName(@Nullable String overlayTargetName) {
+        this.overlayTargetName = TextUtils.safeIntern(overlayTargetName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlayCategory(@Nullable String overlayCategory) {
+        this.overlayCategory = TextUtils.safeIntern(overlayCategory);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setVolumeUuid(@Nullable String volumeUuid) {
+        this.volumeUuid = TextUtils.safeIntern(volumeUuid);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAppComponentFactory(@Nullable String appComponentFactory) {
+        this.appComponentFactory = TextUtils.safeIntern(appComponentFactory);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setBackupAgentName(@Nullable String backupAgentName) {
+        this.backupAgentName = TextUtils.safeIntern(backupAgentName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setClassLoaderName(@Nullable String classLoaderName) {
+        this.classLoaderName = TextUtils.safeIntern(classLoaderName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setClassName(@Nullable String className) {
+        this.className = TextUtils.safeIntern(className);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setManageSpaceActivityName(@Nullable String manageSpaceActivityName) {
+        this.manageSpaceActivityName = TextUtils.safeIntern(manageSpaceActivityName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setPermission(@Nullable String permission) {
+        this.permission = TextUtils.safeIntern(permission);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setTaskAffinity(@Nullable String taskAffinity) {
+        this.taskAffinity = TextUtils.safeIntern(taskAffinity);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setZygotePreloadName(@Nullable String zygotePreloadName) {
+        this.zygotePreloadName = TextUtils.safeIntern(zygotePreloadName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setStaticSharedLibName(String staticSharedLibName) {
+        this.staticSharedLibName = TextUtils.safeIntern(staticSharedLibName);
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSharedUserId(String sharedUserId) {
+        this.sharedUserId = TextUtils.safeIntern(sharedUserId);
+        return this;
+    }
+
+    @NonNull
+    @Override
+    public String getProcessName() {
+        return processName != null ? processName : packageName;
+    }
+
+    @Override
+    public String toString() {
+        return "Package{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + packageName + "}";
+    }
+
+    @Deprecated
+    @Override
+    public ApplicationInfo toAppInfoWithoutState() {
+        ApplicationInfo appInfo = new ApplicationInfo();
+        appInfo.flags = PackageInfoWithoutStateUtils.appInfoFlags(this);
+        appInfo.privateFlags = PackageInfoWithoutStateUtils.appInfoPrivateFlags(this);
+
+        appInfo.appComponentFactory = appComponentFactory;
+        appInfo.backupAgentName = backupAgentName;
+        appInfo.banner = banner;
+        appInfo.category = category;
+        appInfo.classLoaderName = classLoaderName;
+        appInfo.className = className;
+        appInfo.compatibleWidthLimitDp = compatibleWidthLimitDp;
+        appInfo.compileSdkVersion = compileSdkVersion;
+        appInfo.compileSdkVersionCodename = compileSdkVersionCodeName;
+//        appInfo.credentialProtectedDataDir = credentialProtectedDataDir;
+//        appInfo.dataDir = dataDir;
+        appInfo.descriptionRes = descriptionRes;
+//        appInfo.deviceProtectedDataDir = deviceProtectedDataDir;
+        appInfo.enabled = enabled;
+        appInfo.fullBackupContent = fullBackupContent;
+//        appInfo.hiddenUntilInstalled = hiddenUntilInstalled;
+        appInfo.icon = (PackageParser.sUseRoundIcon && roundIconRes != 0) ? roundIconRes : iconRes;
+        appInfo.iconRes = iconRes;
+        appInfo.roundIconRes = roundIconRes;
+        appInfo.installLocation = installLocation;
+        appInfo.labelRes = labelRes;
+        appInfo.largestWidthLimitDp = largestWidthLimitDp;
+        appInfo.logo = logo;
+        appInfo.manageSpaceActivityName = manageSpaceActivityName;
+        appInfo.maxAspectRatio = maxAspectRatio;
+        appInfo.metaData = metaData;
+        appInfo.minAspectRatio = minAspectRatio;
+        appInfo.minSdkVersion = minSdkVersion;
+        appInfo.name = className;
+        if (appInfo.name != null) {
+            appInfo.name = appInfo.name.trim();
+        }
+//        appInfo.nativeLibraryDir = nativeLibraryDir;
+//        appInfo.nativeLibraryRootDir = nativeLibraryRootDir;
+//        appInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
+        appInfo.networkSecurityConfigRes = networkSecurityConfigRes;
+        appInfo.nonLocalizedLabel = nonLocalizedLabel;
+        if (appInfo.nonLocalizedLabel != null) {
+            appInfo.nonLocalizedLabel = appInfo.nonLocalizedLabel.toString().trim();
+        }
+        appInfo.packageName = packageName;
+        appInfo.permission = permission;
+//        appInfo.primaryCpuAbi = primaryCpuAbi;
+        appInfo.processName = getProcessName();
+        appInfo.requiresSmallestWidthDp = requiresSmallestWidthDp;
+//        appInfo.secondaryCpuAbi = secondaryCpuAbi;
+//        appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
+//        appInfo.seInfo = seInfo;
+//        appInfo.seInfoUser = seInfoUser;
+//        appInfo.sharedLibraryFiles = usesLibraryFiles.isEmpty()
+//                ? null : usesLibraryFiles.toArray(new String[0]);
+//        appInfo.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+        appInfo.splitClassLoaderNames = splitClassLoaderNames;
+        appInfo.splitDependencies = splitDependencies;
+        appInfo.splitNames = splitNames;
+        appInfo.storageUuid = StorageManager.convert(volumeUuid);
+        appInfo.targetSandboxVersion = targetSandboxVersion;
+        appInfo.targetSdkVersion = targetSdkVersion;
+        appInfo.taskAffinity = taskAffinity;
+        appInfo.theme = theme;
+//        appInfo.uid = uid;
+        appInfo.uiOptions = uiOptions;
+        appInfo.volumeUuid = volumeUuid;
+        appInfo.zygotePreloadName = zygotePreloadName;
+        appInfo.crossProfile = isCrossProfile();
+
+        appInfo.setBaseCodePath(baseCodePath);
+        appInfo.setBaseResourcePath(baseCodePath);
+        appInfo.setCodePath(codePath);
+        appInfo.setResourcePath(codePath);
+        appInfo.setSplitCodePaths(splitCodePaths);
+        appInfo.setSplitResourcePaths(splitCodePaths);
+        appInfo.setVersionCode(PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode));
+
+        // TODO(b/135203078): Can this be removed? Looks only used in ActivityInfo.
+//        appInfo.showUserIcon = pkg.getShowUserIcon();
+        // TODO(b/135203078): Unused?
+//        appInfo.resourceDirs = pkg.getResourceDirs();
+        // TODO(b/135203078): Unused?
+//        appInfo.enabledSetting = pkg.getEnabledSetting();
+        // TODO(b/135203078): See ParsingPackageImpl#getHiddenApiEnforcementPolicy
+//        appInfo.mHiddenApiPolicy = pkg.getHiddenApiPolicy();
+
+        return appInfo;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        sForBoolean.parcel(this.supportsSmallScreens, dest, flags);
+        sForBoolean.parcel(this.supportsNormalScreens, dest, flags);
+        sForBoolean.parcel(this.supportsLargeScreens, dest, flags);
+        sForBoolean.parcel(this.supportsExtraLargeScreens, dest, flags);
+        sForBoolean.parcel(this.resizeable, dest, flags);
+        sForBoolean.parcel(this.anyDensity, dest, flags);
+        dest.writeInt(this.versionCode);
+        dest.writeInt(this.versionCodeMajor);
+        dest.writeInt(this.baseRevisionCode);
+        sForString.parcel(this.versionName, dest, flags);
+        dest.writeInt(this.compileSdkVersion);
+        sForString.parcel(this.compileSdkVersionCodeName, dest, flags);
+        sForString.parcel(this.packageName, dest, flags);
+        sForString.parcel(this.realPackage, dest, flags);
+        sForString.parcel(this.baseCodePath, dest, flags);
+        dest.writeBoolean(this.requiredForAllUsers);
+        sForString.parcel(this.restrictedAccountType, dest, flags);
+        sForString.parcel(this.requiredAccountType, dest, flags);
+        sForString.parcel(this.overlayTarget, dest, flags);
+        sForString.parcel(this.overlayTargetName, dest, flags);
+        sForString.parcel(this.overlayCategory, dest, flags);
+        dest.writeInt(this.overlayPriority);
+        dest.writeBoolean(this.overlayIsStatic);
+        sForStringValueMap.parcel(this.overlayables, dest, flags);
+        sForString.parcel(this.staticSharedLibName, dest, flags);
+        dest.writeLong(this.staticSharedLibVersion);
+        sForStringList.parcel(this.libraryNames, dest, flags);
+        sForStringList.parcel(this.usesLibraries, dest, flags);
+        sForStringList.parcel(this.usesOptionalLibraries, dest, flags);
+        sForStringList.parcel(this.usesStaticLibraries, dest, flags);
+        dest.writeLongArray(this.usesStaticLibrariesVersions);
+
+        if (this.usesStaticLibrariesCertDigests == null) {
+            dest.writeInt(-1);
+        } else {
+            dest.writeInt(this.usesStaticLibrariesCertDigests.length);
+            for (int index = 0; index < this.usesStaticLibrariesCertDigests.length; index++) {
+                sForStringArray.parcel(this.usesStaticLibrariesCertDigests[index], dest, flags);
+            }
+        }
+
+        sForString.parcel(this.sharedUserId, dest, flags);
+        dest.writeInt(this.sharedUserLabel);
+        dest.writeTypedList(this.configPreferences);
+        dest.writeTypedList(this.reqFeatures);
+        dest.writeTypedList(this.featureGroups);
+        dest.writeByteArray(this.restrictUpdateHash);
+        sForStringList.parcel(this.originalPackages, dest, flags);
+        sForStringList.parcel(this.adoptPermissions, dest, flags);
+        sForStringList.parcel(this.requestedPermissions, dest, flags);
+        sForStringList.parcel(this.implicitPermissions, dest, flags);
+        sForStringSet.parcel(this.upgradeKeySets, dest, flags);
+        dest.writeMap(this.keySetMapping);
+        sForStringList.parcel(this.protectedBroadcasts, dest, flags);
+        dest.writeTypedList(this.activities);
+        dest.writeTypedList(this.receivers);
+        dest.writeTypedList(this.services);
+        dest.writeTypedList(this.providers);
+        dest.writeTypedList(this.features);
+        dest.writeTypedList(this.permissions);
+        dest.writeTypedList(this.permissionGroups);
+        dest.writeTypedList(this.instrumentations);
+        sForIntentInfoPairs.parcel(this.preferredActivityFilters, dest, flags);
+        dest.writeMap(this.processes);
+        dest.writeBundle(this.metaData);
+        sForString.parcel(this.volumeUuid, dest, flags);
+        dest.writeParcelable(this.signingDetails, flags);
+        sForString.parcel(this.codePath, dest, flags);
+        dest.writeBoolean(this.use32BitAbi);
+        dest.writeBoolean(this.visibleToInstantApps);
+        dest.writeBoolean(this.forceQueryable);
+        dest.writeParcelableList(this.queriesIntents, flags);
+        sForStringList.parcel(this.queriesPackages, dest, flags);
+        sForString.parcel(this.appComponentFactory, dest, flags);
+        sForString.parcel(this.backupAgentName, dest, flags);
+        dest.writeInt(this.banner);
+        dest.writeInt(this.category);
+        sForString.parcel(this.classLoaderName, dest, flags);
+        sForString.parcel(this.className, dest, flags);
+        dest.writeInt(this.compatibleWidthLimitDp);
+        dest.writeInt(this.descriptionRes);
+        dest.writeBoolean(this.enabled);
+        dest.writeBoolean(this.crossProfile);
+        dest.writeInt(this.fullBackupContent);
+        dest.writeInt(this.iconRes);
+        dest.writeInt(this.installLocation);
+        dest.writeInt(this.labelRes);
+        dest.writeInt(this.largestWidthLimitDp);
+        dest.writeInt(this.logo);
+        sForString.parcel(this.manageSpaceActivityName, dest, flags);
+        dest.writeFloat(this.maxAspectRatio);
+        dest.writeFloat(this.minAspectRatio);
+        dest.writeInt(this.minSdkVersion);
+        dest.writeInt(this.networkSecurityConfigRes);
+        dest.writeCharSequence(this.nonLocalizedLabel);
+        sForString.parcel(this.permission, dest, flags);
+        sForString.parcel(this.processName, dest, flags);
+        dest.writeInt(this.requiresSmallestWidthDp);
+        dest.writeInt(this.roundIconRes);
+        dest.writeInt(this.targetSandboxVersion);
+        dest.writeInt(this.targetSdkVersion);
+        sForString.parcel(this.taskAffinity, dest, flags);
+        dest.writeInt(this.theme);
+        dest.writeInt(this.uiOptions);
+        sForString.parcel(this.zygotePreloadName, dest, flags);
+        sForStringArray.parcel(this.splitClassLoaderNames, dest, flags);
+        sForStringArray.parcel(this.splitCodePaths, dest, flags);
+        dest.writeSparseArray(this.splitDependencies);
+        dest.writeIntArray(this.splitFlags);
+        sForStringArray.parcel(this.splitNames, dest, flags);
+        dest.writeIntArray(this.splitRevisionCodes);
+
+        dest.writeBoolean(this.externalStorage);
+        dest.writeBoolean(this.baseHardwareAccelerated);
+        dest.writeBoolean(this.allowBackup);
+        dest.writeBoolean(this.killAfterRestore);
+        dest.writeBoolean(this.restoreAnyVersion);
+        dest.writeBoolean(this.fullBackupOnly);
+        dest.writeBoolean(this.persistent);
+        dest.writeBoolean(this.debuggable);
+        dest.writeBoolean(this.vmSafeMode);
+        dest.writeBoolean(this.hasCode);
+        dest.writeBoolean(this.allowTaskReparenting);
+        dest.writeBoolean(this.allowClearUserData);
+        dest.writeBoolean(this.largeHeap);
+        dest.writeBoolean(this.usesCleartextTraffic);
+        dest.writeBoolean(this.supportsRtl);
+        dest.writeBoolean(this.testOnly);
+        dest.writeBoolean(this.multiArch);
+        dest.writeBoolean(this.extractNativeLibs);
+        dest.writeBoolean(this.game);
+
+        sForBoolean.parcel(this.resizeableActivity, dest, flags);
+
+        dest.writeBoolean(this.staticSharedLibrary);
+        dest.writeBoolean(this.overlay);
+        dest.writeBoolean(this.isolatedSplitLoading);
+        dest.writeBoolean(this.hasDomainUrls);
+        dest.writeBoolean(this.profileableByShell);
+        dest.writeBoolean(this.backupInForeground);
+        dest.writeBoolean(this.useEmbeddedDex);
+        dest.writeBoolean(this.defaultToDeviceProtectedStorage);
+        dest.writeBoolean(this.directBootAware);
+        dest.writeBoolean(this.partiallyDirectBootAware);
+        dest.writeBoolean(this.resizeableActivityViaSdkVersion);
+        dest.writeBoolean(this.allowClearUserDataOnFailedRestore);
+        dest.writeBoolean(this.allowAudioPlaybackCapture);
+        dest.writeBoolean(this.requestLegacyExternalStorage);
+        dest.writeBoolean(this.usesNonSdkApi);
+        dest.writeBoolean(this.hasFragileUserData);
+        dest.writeBoolean(this.cantSaveState);
+        dest.writeBoolean(this.allowNativeHeapPointerTagging);
+        dest.writeBoolean(this.preserveLegacyExternalStorage);
+        dest.writeArraySet(this.mimeGroups);
+    }
+
+    public ParsingPackageImpl(Parcel in) {
+        // We use the boot classloader for all classes that we load.
+        final ClassLoader boot = Object.class.getClassLoader();
+        this.supportsSmallScreens = sForBoolean.unparcel(in);
+        this.supportsNormalScreens = sForBoolean.unparcel(in);
+        this.supportsLargeScreens = sForBoolean.unparcel(in);
+        this.supportsExtraLargeScreens = sForBoolean.unparcel(in);
+        this.resizeable = sForBoolean.unparcel(in);
+        this.anyDensity = sForBoolean.unparcel(in);
+        this.versionCode = in.readInt();
+        this.versionCodeMajor = in.readInt();
+        this.baseRevisionCode = in.readInt();
+        this.versionName = sForString.unparcel(in);
+        this.compileSdkVersion = in.readInt();
+        this.compileSdkVersionCodeName = sForString.unparcel(in);
+        this.packageName = sForString.unparcel(in);
+        this.realPackage = sForString.unparcel(in);
+        this.baseCodePath = sForString.unparcel(in);
+        this.requiredForAllUsers = in.readBoolean();
+        this.restrictedAccountType = sForString.unparcel(in);
+        this.requiredAccountType = sForString.unparcel(in);
+        this.overlayTarget = sForString.unparcel(in);
+        this.overlayTargetName = sForString.unparcel(in);
+        this.overlayCategory = sForString.unparcel(in);
+        this.overlayPriority = in.readInt();
+        this.overlayIsStatic = in.readBoolean();
+        this.overlayables = sForStringValueMap.unparcel(in);
+        this.staticSharedLibName = sForString.unparcel(in);
+        this.staticSharedLibVersion = in.readLong();
+        this.libraryNames = sForStringList.unparcel(in);
+        this.usesLibraries = sForStringList.unparcel(in);
+        this.usesOptionalLibraries = sForStringList.unparcel(in);
+        this.usesStaticLibraries = sForStringList.unparcel(in);
+        this.usesStaticLibrariesVersions = in.createLongArray();
+
+        int digestsSize = in.readInt();
+        if (digestsSize >= 0) {
+            this.usesStaticLibrariesCertDigests = new String[digestsSize][];
+            for (int index = 0; index < digestsSize; index++) {
+                this.usesStaticLibrariesCertDigests[index] = sForStringArray.unparcel(in);
+            }
+        }
+
+        this.sharedUserId = sForString.unparcel(in);
+        this.sharedUserLabel = in.readInt();
+        this.configPreferences = in.createTypedArrayList(ConfigurationInfo.CREATOR);
+        this.reqFeatures = in.createTypedArrayList(FeatureInfo.CREATOR);
+        this.featureGroups = in.createTypedArrayList(FeatureGroupInfo.CREATOR);
+        this.restrictUpdateHash = in.createByteArray();
+        this.originalPackages = sForStringList.unparcel(in);
+        this.adoptPermissions = sForStringList.unparcel(in);
+        this.requestedPermissions = sForStringList.unparcel(in);
+        this.implicitPermissions = sForStringList.unparcel(in);
+        this.upgradeKeySets = sForStringSet.unparcel(in);
+        this.keySetMapping = in.readHashMap(boot);
+        this.protectedBroadcasts = sForStringList.unparcel(in);
+        this.activities = in.createTypedArrayList(ParsedActivity.CREATOR);
+        this.receivers = in.createTypedArrayList(ParsedActivity.CREATOR);
+        this.services = in.createTypedArrayList(ParsedService.CREATOR);
+        this.providers = in.createTypedArrayList(ParsedProvider.CREATOR);
+        this.features = in.createTypedArrayList(ParsedFeature.CREATOR);
+        this.permissions = in.createTypedArrayList(ParsedPermission.CREATOR);
+        this.permissionGroups = in.createTypedArrayList(ParsedPermissionGroup.CREATOR);
+        this.instrumentations = in.createTypedArrayList(ParsedInstrumentation.CREATOR);
+        this.preferredActivityFilters = sForIntentInfoPairs.unparcel(in);
+        this.processes = in.readHashMap(boot);
+        this.metaData = in.readBundle(boot);
+        this.volumeUuid = sForString.unparcel(in);
+        this.signingDetails = in.readParcelable(boot);
+        this.codePath = sForString.unparcel(in);
+        this.use32BitAbi = in.readBoolean();
+        this.visibleToInstantApps = in.readBoolean();
+        this.forceQueryable = in.readBoolean();
+        this.queriesIntents = in.createTypedArrayList(Intent.CREATOR);
+        this.queriesPackages = sForStringList.unparcel(in);
+        this.appComponentFactory = sForString.unparcel(in);
+        this.backupAgentName = sForString.unparcel(in);
+        this.banner = in.readInt();
+        this.category = in.readInt();
+        this.classLoaderName = sForString.unparcel(in);
+        this.className = sForString.unparcel(in);
+        this.compatibleWidthLimitDp = in.readInt();
+        this.descriptionRes = in.readInt();
+        this.enabled = in.readBoolean();
+        this.crossProfile = in.readBoolean();
+        this.fullBackupContent = in.readInt();
+        this.iconRes = in.readInt();
+        this.installLocation = in.readInt();
+        this.labelRes = in.readInt();
+        this.largestWidthLimitDp = in.readInt();
+        this.logo = in.readInt();
+        this.manageSpaceActivityName = sForString.unparcel(in);
+        this.maxAspectRatio = in.readFloat();
+        this.minAspectRatio = in.readFloat();
+        this.minSdkVersion = in.readInt();
+        this.networkSecurityConfigRes = in.readInt();
+        this.nonLocalizedLabel = in.readCharSequence();
+        this.permission = sForString.unparcel(in);
+        this.processName = sForString.unparcel(in);
+        this.requiresSmallestWidthDp = in.readInt();
+        this.roundIconRes = in.readInt();
+        this.targetSandboxVersion = in.readInt();
+        this.targetSdkVersion = in.readInt();
+        this.taskAffinity = sForString.unparcel(in);
+        this.theme = in.readInt();
+        this.uiOptions = in.readInt();
+        this.zygotePreloadName = sForString.unparcel(in);
+        this.splitClassLoaderNames = sForStringArray.unparcel(in);
+        this.splitCodePaths = sForStringArray.unparcel(in);
+        this.splitDependencies = in.readSparseArray(boot);
+        this.splitFlags = in.createIntArray();
+        this.splitNames = sForStringArray.unparcel(in);
+        this.splitRevisionCodes = in.createIntArray();
+        this.externalStorage = in.readBoolean();
+        this.baseHardwareAccelerated = in.readBoolean();
+        this.allowBackup = in.readBoolean();
+        this.killAfterRestore = in.readBoolean();
+        this.restoreAnyVersion = in.readBoolean();
+        this.fullBackupOnly = in.readBoolean();
+        this.persistent = in.readBoolean();
+        this.debuggable = in.readBoolean();
+        this.vmSafeMode = in.readBoolean();
+        this.hasCode = in.readBoolean();
+        this.allowTaskReparenting = in.readBoolean();
+        this.allowClearUserData = in.readBoolean();
+        this.largeHeap = in.readBoolean();
+        this.usesCleartextTraffic = in.readBoolean();
+        this.supportsRtl = in.readBoolean();
+        this.testOnly = in.readBoolean();
+        this.multiArch = in.readBoolean();
+        this.extractNativeLibs = in.readBoolean();
+        this.game = in.readBoolean();
+
+        this.resizeableActivity = sForBoolean.unparcel(in);
+
+        this.staticSharedLibrary = in.readBoolean();
+        this.overlay = in.readBoolean();
+        this.isolatedSplitLoading = in.readBoolean();
+        this.hasDomainUrls = in.readBoolean();
+        this.profileableByShell = in.readBoolean();
+        this.backupInForeground = in.readBoolean();
+        this.useEmbeddedDex = in.readBoolean();
+        this.defaultToDeviceProtectedStorage = in.readBoolean();
+        this.directBootAware = in.readBoolean();
+        this.partiallyDirectBootAware = in.readBoolean();
+        this.resizeableActivityViaSdkVersion = in.readBoolean();
+        this.allowClearUserDataOnFailedRestore = in.readBoolean();
+        this.allowAudioPlaybackCapture = in.readBoolean();
+        this.requestLegacyExternalStorage = in.readBoolean();
+        this.usesNonSdkApi = in.readBoolean();
+        this.hasFragileUserData = in.readBoolean();
+        this.cantSaveState = in.readBoolean();
+        this.allowNativeHeapPointerTagging = in.readBoolean();
+        this.preserveLegacyExternalStorage = in.readBoolean();
+        this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
+    }
+
+    public static final Parcelable.Creator<ParsingPackageImpl> CREATOR =
+            new Parcelable.Creator<ParsingPackageImpl>() {
+                @Override
+                public ParsingPackageImpl createFromParcel(Parcel source) {
+                    return new ParsingPackageImpl(source);
+                }
+
+                @Override
+                public ParsingPackageImpl[] newArray(int size) {
+                    return new ParsingPackageImpl[size];
+                }
+            };
+
+    @Override
+    public int getVersionCode() {
+        return versionCode;
+    }
+
+    @Override
+    public int getVersionCodeMajor() {
+        return versionCodeMajor;
+    }
+
+    @Override
+    public int getBaseRevisionCode() {
+        return baseRevisionCode;
+    }
+
+    @Nullable
+    @Override
+    public String getVersionName() {
+        return versionName;
+    }
+
+    @Override
+    public int getCompileSdkVersion() {
+        return compileSdkVersion;
+    }
+
+    @Nullable
+    @Override
+    public String getCompileSdkVersionCodeName() {
+        return compileSdkVersionCodeName;
+    }
+
+    @NonNull
+    @Override
+    public String getPackageName() {
+        return packageName;
+    }
+
+    @Nullable
+    @Override
+    public String getRealPackage() {
+        return realPackage;
+    }
+
+    @NonNull
+    @Override
+    public String getBaseCodePath() {
+        return baseCodePath;
+    }
+
+    @Override
+    public boolean isRequiredForAllUsers() {
+        return requiredForAllUsers;
+    }
+
+    @Nullable
+    @Override
+    public String getRestrictedAccountType() {
+        return restrictedAccountType;
+    }
+
+    @Nullable
+    @Override
+    public String getRequiredAccountType() {
+        return requiredAccountType;
+    }
+
+    @Nullable
+    @Override
+    public String getOverlayTarget() {
+        return overlayTarget;
+    }
+
+    @Nullable
+    @Override
+    public String getOverlayTargetName() {
+        return overlayTargetName;
+    }
+
+    @Nullable
+    @Override
+    public String getOverlayCategory() {
+        return overlayCategory;
+    }
+
+    @Override
+    public int getOverlayPriority() {
+        return overlayPriority;
+    }
+
+    @Override
+    public boolean isOverlayIsStatic() {
+        return overlayIsStatic;
+    }
+
+    @NonNull
+    @Override
+    public Map<String,String> getOverlayables() {
+        return overlayables;
+    }
+
+    @Nullable
+    @Override
+    public String getStaticSharedLibName() {
+        return staticSharedLibName;
+    }
+
+    @Override
+    public long getStaticSharedLibVersion() {
+        return staticSharedLibVersion;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getLibraryNames() {
+        return libraryNames;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getUsesLibraries() {
+        return usesLibraries;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getUsesOptionalLibraries() {
+        return usesOptionalLibraries;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getUsesStaticLibraries() {
+        return usesStaticLibraries;
+    }
+
+    @Nullable
+    @Override
+    public long[] getUsesStaticLibrariesVersions() {
+        return usesStaticLibrariesVersions;
+    }
+
+    @Nullable
+    @Override
+    public String[][] getUsesStaticLibrariesCertDigests() {
+        return usesStaticLibrariesCertDigests;
+    }
+
+    @Nullable
+    @Override
+    public String getSharedUserId() {
+        return sharedUserId;
+    }
+
+    @Override
+    public int getSharedUserLabel() {
+        return sharedUserLabel;
+    }
+
+    @NonNull
+    @Override
+    public List<ConfigurationInfo> getConfigPreferences() {
+        return configPreferences;
+    }
+
+    @NonNull
+    @Override
+    public List<FeatureInfo> getReqFeatures() {
+        return reqFeatures;
+    }
+
+    @NonNull
+    @Override
+    public List<FeatureGroupInfo> getFeatureGroups() {
+        return featureGroups;
+    }
+
+    @Nullable
+    @Override
+    public byte[] getRestrictUpdateHash() {
+        return restrictUpdateHash;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getOriginalPackages() {
+        return originalPackages;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getAdoptPermissions() {
+        return adoptPermissions;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getRequestedPermissions() {
+        return requestedPermissions;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getImplicitPermissions() {
+        return implicitPermissions;
+    }
+
+    @NonNull
+    @Override
+    public Set<String> getUpgradeKeySets() {
+        return upgradeKeySets;
+    }
+
+    @NonNull
+    @Override
+    public Map<String,ArraySet<PublicKey>> getKeySetMapping() {
+        return keySetMapping;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getProtectedBroadcasts() {
+        return protectedBroadcasts;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedActivity> getActivities() {
+        return activities;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedActivity> getReceivers() {
+        return receivers;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedService> getServices() {
+        return services;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedProvider> getProviders() {
+        return providers;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedFeature> getFeatures() {
+        return features;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedPermission> getPermissions() {
+        return permissions;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedPermissionGroup> getPermissionGroups() {
+        return permissionGroups;
+    }
+
+    @NonNull
+    @Override
+    public List<ParsedInstrumentation> getInstrumentations() {
+        return instrumentations;
+    }
+
+    @NonNull
+    @Override
+    public List<Pair<String,ParsedIntentInfo>> getPreferredActivityFilters() {
+        return preferredActivityFilters;
+    }
+
+    @NonNull
+    @Override
+    public Map<String,ParsedProcess> getProcesses() {
+        return processes;
+    }
+
+    @Nullable
+    @Override
+    public Bundle getMetaData() {
+        return metaData;
+    }
+
+    private void addMimeGroupsFromComponent(ParsedComponent component) {
+        for (int i = component.getIntents().size() - 1; i >= 0; i--) {
+            IntentFilter filter = component.getIntents().get(i);
+            for (int groupIndex = filter.countMimeGroups() - 1; groupIndex >= 0; groupIndex--) {
+                mimeGroups = ArrayUtils.add(mimeGroups, filter.getMimeGroup(groupIndex));
+            }
+        }
+    }
+
+    @Override
+    @Nullable
+    public Set<String> getMimeGroups() {
+        return mimeGroups;
+    }
+
+    @Nullable
+    @Override
+    public String getVolumeUuid() {
+        return volumeUuid;
+    }
+
+    @Nullable
+    @Override
+    public PackageParser.SigningDetails getSigningDetails() {
+        return signingDetails;
+    }
+
+    @NonNull
+    @Override
+    public String getCodePath() {
+        return codePath;
+    }
+
+    @Override
+    public boolean isUse32BitAbi() {
+        return use32BitAbi;
+    }
+
+    @Override
+    public boolean isVisibleToInstantApps() {
+        return visibleToInstantApps;
+    }
+
+    @Override
+    public boolean isForceQueryable() {
+        return forceQueryable;
+    }
+
+    @NonNull
+    @Override
+    public List<Intent> getQueriesIntents() {
+        return queriesIntents;
+    }
+
+    @NonNull
+    @Override
+    public List<String> getQueriesPackages() {
+        return queriesPackages;
+    }
+
+    @NonNull
+    @Override
+    public Set<String> getQueriesProviders() {
+        return queriesProviders;
+    }
+
+    @Nullable
+    @Override
+    public String[] getSplitClassLoaderNames() {
+        return splitClassLoaderNames;
+    }
+
+    @Nullable
+    @Override
+    public String[] getSplitCodePaths() {
+        return splitCodePaths;
+    }
+
+    @Nullable
+    @Override
+    public SparseArray<int[]> getSplitDependencies() {
+        return splitDependencies;
+    }
+
+    @Nullable
+    @Override
+    public int[] getSplitFlags() {
+        return splitFlags;
+    }
+
+    @Nullable
+    @Override
+    public String[] getSplitNames() {
+        return splitNames;
+    }
+
+    @Nullable
+    @Override
+    public int[] getSplitRevisionCodes() {
+        return splitRevisionCodes;
+    }
+
+    @Nullable
+    @Override
+    public String getAppComponentFactory() {
+        return appComponentFactory;
+    }
+
+    @Nullable
+    @Override
+    public String getBackupAgentName() {
+        return backupAgentName;
+    }
+
+    @Override
+    public int getBanner() {
+        return banner;
+    }
+
+    @Override
+    public int getCategory() {
+        return category;
+    }
+
+    @Nullable
+    @Override
+    public String getClassLoaderName() {
+        return classLoaderName;
+    }
+
+    @Nullable
+    @Override
+    public String getClassName() {
+        return className;
+    }
+
+    @Override
+    public int getCompatibleWidthLimitDp() {
+        return compatibleWidthLimitDp;
+    }
+
+    @Override
+    public int getDescriptionRes() {
+        return descriptionRes;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    @Override
+    public boolean isCrossProfile() {
+        return crossProfile;
+    }
+
+    @Override
+    public int getFullBackupContent() {
+        return fullBackupContent;
+    }
+
+    @Override
+    public int getIconRes() {
+        return iconRes;
+    }
+
+    @Override
+    public int getInstallLocation() {
+        return installLocation;
+    }
+
+    @Override
+    public int getLabelRes() {
+        return labelRes;
+    }
+
+    @Override
+    public int getLargestWidthLimitDp() {
+        return largestWidthLimitDp;
+    }
+
+    @Override
+    public int getLogo() {
+        return logo;
+    }
+
+    @Nullable
+    @Override
+    public String getManageSpaceActivityName() {
+        return manageSpaceActivityName;
+    }
+
+    @Override
+    public float getMaxAspectRatio() {
+        return maxAspectRatio;
+    }
+
+    @Override
+    public float getMinAspectRatio() {
+        return minAspectRatio;
+    }
+
+    @Override
+    public int getMinSdkVersion() {
+        return minSdkVersion;
+    }
+
+    @Override
+    public int getNetworkSecurityConfigRes() {
+        return networkSecurityConfigRes;
+    }
+
+    @Nullable
+    @Override
+    public CharSequence getNonLocalizedLabel() {
+        return nonLocalizedLabel;
+    }
+
+    @Nullable
+    @Override
+    public String getPermission() {
+        return permission;
+    }
+
+    @Override
+    public int getRequiresSmallestWidthDp() {
+        return requiresSmallestWidthDp;
+    }
+
+    @Override
+    public int getRoundIconRes() {
+        return roundIconRes;
+    }
+
+    @Override
+    public int getTargetSandboxVersion() {
+        return targetSandboxVersion;
+    }
+
+    @Override
+    public int getTargetSdkVersion() {
+        return targetSdkVersion;
+    }
+
+    @Nullable
+    @Override
+    public String getTaskAffinity() {
+        return taskAffinity;
+    }
+
+    @Override
+    public int getTheme() {
+        return theme;
+    }
+
+    @Override
+    public int getUiOptions() {
+        return uiOptions;
+    }
+
+    @Nullable
+    @Override
+    public String getZygotePreloadName() {
+        return zygotePreloadName;
+    }
+
+    @Override
+    public boolean isExternalStorage() {
+        return externalStorage;
+    }
+
+    @Override
+    public boolean isBaseHardwareAccelerated() {
+        return baseHardwareAccelerated;
+    }
+
+    @Override
+    public boolean isAllowBackup() {
+        return allowBackup;
+    }
+
+    @Override
+    public boolean isKillAfterRestore() {
+        return killAfterRestore;
+    }
+
+    @Override
+    public boolean isRestoreAnyVersion() {
+        return restoreAnyVersion;
+    }
+
+    @Override
+    public boolean isFullBackupOnly() {
+        return fullBackupOnly;
+    }
+
+    @Override
+    public boolean isPersistent() {
+        return persistent;
+    }
+
+    @Override
+    public boolean isDebuggable() {
+        return debuggable;
+    }
+
+    @Override
+    public boolean isVmSafeMode() {
+        return vmSafeMode;
+    }
+
+    @Override
+    public boolean isHasCode() {
+        return hasCode;
+    }
+
+    @Override
+    public boolean isAllowTaskReparenting() {
+        return allowTaskReparenting;
+    }
+
+    @Override
+    public boolean isAllowClearUserData() {
+        return allowClearUserData;
+    }
+
+    @Override
+    public boolean isLargeHeap() {
+        return largeHeap;
+    }
+
+    @Override
+    public boolean isUsesCleartextTraffic() {
+        return usesCleartextTraffic;
+    }
+
+    @Override
+    public boolean isSupportsRtl() {
+        return supportsRtl;
+    }
+
+    @Override
+    public boolean isTestOnly() {
+        return testOnly;
+    }
+
+    @Override
+    public boolean isMultiArch() {
+        return multiArch;
+    }
+
+    @Override
+    public boolean isExtractNativeLibs() {
+        return extractNativeLibs;
+    }
+
+    @Override
+    public boolean isGame() {
+        return game;
+    }
+
+    /**
+     * @see ParsingPackageRead#getResizeableActivity()
+     */
+    @Nullable
+    @Override
+    public Boolean getResizeableActivity() {
+        return resizeableActivity;
+    }
+
+    @Override
+    public boolean isStaticSharedLibrary() {
+        return staticSharedLibrary;
+    }
+
+    @Override
+    public boolean isOverlay() {
+        return overlay;
+    }
+
+    @Override
+    public boolean isIsolatedSplitLoading() {
+        return isolatedSplitLoading;
+    }
+
+    @Override
+    public boolean isHasDomainUrls() {
+        return hasDomainUrls;
+    }
+
+    @Override
+    public boolean isProfileableByShell() {
+        return profileableByShell;
+    }
+
+    @Override
+    public boolean isBackupInForeground() {
+        return backupInForeground;
+    }
+
+    @Override
+    public boolean isUseEmbeddedDex() {
+        return useEmbeddedDex;
+    }
+
+    @Override
+    public boolean isDefaultToDeviceProtectedStorage() {
+        return defaultToDeviceProtectedStorage;
+    }
+
+    @Override
+    public boolean isDirectBootAware() {
+        return directBootAware;
+    }
+
+    @Override
+    public boolean isPartiallyDirectBootAware() {
+        return partiallyDirectBootAware;
+    }
+
+    @Override
+    public boolean isResizeableActivityViaSdkVersion() {
+        return resizeableActivityViaSdkVersion;
+    }
+
+    @Override
+    public boolean isAllowClearUserDataOnFailedRestore() {
+        return allowClearUserDataOnFailedRestore;
+    }
+
+    @Override
+    public boolean isAllowAudioPlaybackCapture() {
+        return allowAudioPlaybackCapture;
+    }
+
+    @Override
+    public boolean isRequestLegacyExternalStorage() {
+        return requestLegacyExternalStorage;
+    }
+
+    @Override
+    public boolean isUsesNonSdkApi() {
+        return usesNonSdkApi;
+    }
+
+    @Override
+    public boolean isHasFragileUserData() {
+        return hasFragileUserData;
+    }
+
+    @Override
+    public boolean isCantSaveState() {
+        return cantSaveState;
+    }
+
+    @Override
+    public boolean isAllowNativeHeapPointerTagging() {
+        return allowNativeHeapPointerTagging;
+    }
+
+    @Override
+    public boolean hasPreserveLegacyExternalStorage() {
+        return preserveLegacyExternalStorage;
+    }
+
+    @Override
+    public ParsingPackageImpl setBaseRevisionCode(int value) {
+        baseRevisionCode = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setCompileSdkVersion(int value) {
+        compileSdkVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRequiredForAllUsers(boolean value) {
+        requiredForAllUsers = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlayPriority(int value) {
+        overlayPriority = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlayIsStatic(boolean value) {
+        overlayIsStatic = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setStaticSharedLibVersion(long value) {
+        staticSharedLibVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSharedUserLabel(int value) {
+        sharedUserLabel = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRestrictUpdateHash(@Nullable byte... value) {
+        restrictUpdateHash = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUpgradeKeySets(@NonNull Set<String> value) {
+        upgradeKeySets = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setProcesses(@NonNull Map<String,ParsedProcess> value) {
+        processes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setMetaData(@Nullable Bundle value) {
+        metaData = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSigningDetails(@Nullable PackageParser.SigningDetails value) {
+        signingDetails = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUse32BitAbi(boolean value) {
+        use32BitAbi = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setVisibleToInstantApps(boolean value) {
+        visibleToInstantApps = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setForceQueryable(boolean value) {
+        forceQueryable = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setBanner(int value) {
+        banner = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setCategory(int value) {
+        category = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setCompatibleWidthLimitDp(int value) {
+        compatibleWidthLimitDp = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setDescriptionRes(int value) {
+        descriptionRes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setEnabled(boolean value) {
+        enabled = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setCrossProfile(boolean value) {
+        crossProfile = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setFullBackupContent(int value) {
+        fullBackupContent = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setIconRes(int value) {
+        iconRes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setInstallLocation(int value) {
+        installLocation = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setLabelRes(int value) {
+        labelRes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setLargestWidthLimitDp(int value) {
+        largestWidthLimitDp = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setLogo(int value) {
+        logo = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setMaxAspectRatio(float value) {
+        maxAspectRatio = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setMinAspectRatio(float value) {
+        minAspectRatio = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setMinSdkVersion(int value) {
+        minSdkVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setNetworkSecurityConfigRes(int value) {
+        networkSecurityConfigRes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setNonLocalizedLabel(@Nullable CharSequence value) {
+        nonLocalizedLabel = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRequiresSmallestWidthDp(int value) {
+        requiresSmallestWidthDp = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRoundIconRes(int value) {
+        roundIconRes = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setTargetSandboxVersion(int value) {
+        targetSandboxVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setTargetSdkVersion(int value) {
+        targetSdkVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setTheme(int value) {
+        theme = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUiOptions(int value) {
+        uiOptions = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setExternalStorage(boolean value) {
+        externalStorage = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setBaseHardwareAccelerated(boolean value) {
+        baseHardwareAccelerated = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowBackup(boolean value) {
+        allowBackup = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setKillAfterRestore(boolean value) {
+        killAfterRestore = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRestoreAnyVersion(boolean value) {
+        restoreAnyVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setFullBackupOnly(boolean value) {
+        fullBackupOnly = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setPersistent(boolean value) {
+        persistent = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setDebuggable(boolean value) {
+        debuggable = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setVmSafeMode(boolean value) {
+        vmSafeMode = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setHasCode(boolean value) {
+        hasCode = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowTaskReparenting(boolean value) {
+        allowTaskReparenting = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowClearUserData(boolean value) {
+        allowClearUserData = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setLargeHeap(boolean value) {
+        largeHeap = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUsesCleartextTraffic(boolean value) {
+        usesCleartextTraffic = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setSupportsRtl(boolean value) {
+        supportsRtl = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setTestOnly(boolean value) {
+        testOnly = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setMultiArch(boolean value) {
+        multiArch = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setExtractNativeLibs(boolean value) {
+        extractNativeLibs = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setGame(boolean value) {
+        game = value;
+        return this;
+    }
+
+    /**
+     * @see ParsingPackageRead#getResizeableActivity()
+     */
+    @Override
+    public ParsingPackageImpl setResizeableActivity(@Nullable Boolean value) {
+        resizeableActivity = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setStaticSharedLibrary(boolean value) {
+        staticSharedLibrary = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setOverlay(boolean value) {
+        overlay = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setIsolatedSplitLoading(boolean value) {
+        isolatedSplitLoading = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setHasDomainUrls(boolean value) {
+        hasDomainUrls = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setProfileableByShell(boolean value) {
+        profileableByShell = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setBackupInForeground(boolean value) {
+        backupInForeground = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUseEmbeddedDex(boolean value) {
+        useEmbeddedDex = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setDefaultToDeviceProtectedStorage(boolean value) {
+        defaultToDeviceProtectedStorage = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setDirectBootAware(boolean value) {
+        directBootAware = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setPartiallyDirectBootAware(boolean value) {
+        partiallyDirectBootAware = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setResizeableActivityViaSdkVersion(boolean value) {
+        resizeableActivityViaSdkVersion = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowClearUserDataOnFailedRestore(boolean value) {
+        allowClearUserDataOnFailedRestore = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowAudioPlaybackCapture(boolean value) {
+        allowAudioPlaybackCapture = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setRequestLegacyExternalStorage(boolean value) {
+        requestLegacyExternalStorage = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setUsesNonSdkApi(boolean value) {
+        usesNonSdkApi = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setHasFragileUserData(boolean value) {
+        hasFragileUserData = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setCantSaveState(boolean value) {
+        cantSaveState = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setAllowNativeHeapPointerTagging(boolean value) {
+        allowNativeHeapPointerTagging = value;
+        return this;
+    }
+
+    @Override
+    public ParsingPackageImpl setPreserveLegacyExternalStorage(boolean value) {
+        preserveLegacyExternalStorage = value;
+        return this;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageRead.java b/core/java/android/content/pm/parsing/ParsingPackageRead.java
new file mode 100644
index 0000000..048b924
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingPackageRead.java
@@ -0,0 +1,845 @@
+/*
+ * 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.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.ServiceInfo;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.util.Pair;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+
+import java.security.PublicKey;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Everything written by {@link ParsingPackage} and readable back.
+ *
+ * @hide
+ */
+@SuppressWarnings("UnusedReturnValue")
+public interface ParsingPackageRead extends Parcelable {
+
+    /**
+     * @see ActivityInfo
+     * @see PackageInfo#activities
+     */
+    @NonNull
+    List<ParsedActivity> getActivities();
+
+    /**
+     * The names of packages to adopt ownership of permissions from, parsed under
+     * {@link PackageParser#TAG_ADOPT_PERMISSIONS}.
+     * @see R.styleable#AndroidManifestOriginalPackage_name
+     */
+    @NonNull
+    List<String> getAdoptPermissions();
+
+    /**
+     * @see PackageInfo#configPreferences
+     * @see R.styleable#AndroidManifestUsesConfiguration
+     */
+    @NonNull
+    List<ConfigurationInfo> getConfigPreferences();
+
+    @NonNull
+    List<ParsedFeature> getFeatures();
+
+    /**
+     * @see PackageInfo#featureGroups
+     * @see R.styleable#AndroidManifestUsesFeature
+     */
+    @NonNull
+    List<FeatureGroupInfo> getFeatureGroups();
+
+    /**
+     * Permissions requested but not in the manifest. These may have been split or migrated from
+     * previous versions/definitions.
+     */
+    @NonNull
+    List<String> getImplicitPermissions();
+
+    /**
+     * @see android.content.pm.InstrumentationInfo
+     * @see PackageInfo#instrumentation
+     */
+    @NonNull
+    List<ParsedInstrumentation> getInstrumentations();
+
+    /**
+     * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
+     * {@link PackageParser#TAG_KEY_SETS}.
+     * @see R.styleable#AndroidManifestKeySet
+     * @see R.styleable#AndroidManifestPublicKey
+     */
+    @NonNull
+    Map<String, ArraySet<PublicKey>> getKeySetMapping();
+
+    /**
+     * Library names this package is declared as, for use by other packages with "uses-library".
+     * @see R.styleable#AndroidManifestLibrary
+     */
+    @NonNull
+    List<String> getLibraryNames();
+
+    /**
+     * For system use to migrate from an old package name to a new one, moving over data
+     * if available.
+     * @see R.styleable#AndroidManifestOriginalPackage}
+     */
+    @NonNull
+    List<String> getOriginalPackages();
+
+    /**
+     * Map of overlayable name to actor name.
+     */
+    @NonNull
+    Map<String, String> getOverlayables();
+
+    /**
+     * @see android.content.pm.PermissionInfo
+     * @see PackageInfo#permissions
+     */
+    @NonNull
+    List<ParsedPermission> getPermissions();
+
+    /**
+     * @see android.content.pm.PermissionGroupInfo
+     */
+    @NonNull
+    List<ParsedPermissionGroup> getPermissionGroups();
+
+    /**
+     * Used to determine the default preferred handler of an {@link Intent}.
+     *
+     * Map of component className to intent info inside that component.
+     * TODO(b/135203078): Is this actually used/working?
+     */
+    @NonNull
+    List<Pair<String, ParsedIntentInfo>> getPreferredActivityFilters();
+
+    /**
+     * System protected broadcasts.
+     * @see R.styleable#AndroidManifestProtectedBroadcast
+     */
+    @NonNull
+    List<String> getProtectedBroadcasts();
+
+    /**
+     * @see android.content.pm.ProviderInfo
+     * @see PackageInfo#providers
+     */
+    @NonNull
+    List<ParsedProvider> getProviders();
+
+    /**
+     * @see android.content.pm.ProcessInfo
+     */
+    @NonNull
+    Map<String, ParsedProcess> getProcesses();
+
+    /**
+     * Since they share several attributes, receivers are parsed as {@link ParsedActivity}, even
+     * though they represent different functionality.
+     * TODO(b/135203078): Reconsider this and maybe make ParsedReceiver so it's not so confusing
+     * @see ActivityInfo
+     * @see PackageInfo#receivers
+     */
+    @NonNull
+    List<ParsedActivity> getReceivers();
+
+    /**
+     * @see PackageInfo#reqFeatures
+     * @see R.styleable#AndroidManifestUsesFeature
+     */
+    @NonNull
+    List<FeatureInfo> getReqFeatures();
+
+    /**
+     * All the permissions declared. This is an effective set, and may include permissions
+     * transformed from split/migrated permissions from previous versions, so may not be exactly
+     * what the package declares in its manifest.
+     * @see PackageInfo#requestedPermissions
+     * @see R.styleable#AndroidManifestUsesPermission
+     */
+    @NonNull
+    List<String> getRequestedPermissions();
+
+    /**
+     * Whether or not the app requested explicitly resizeable Activities.
+     * A null value means nothing was explicitly requested.
+     */
+    @Nullable
+    Boolean getResizeableActivity();
+
+    /**
+     * @see ServiceInfo
+     * @see PackageInfo#services
+     */
+    @NonNull
+    List<ParsedService> getServices();
+
+    /** @see R.styleable#AndroidManifestUsesLibrary */
+    @NonNull
+    List<String> getUsesLibraries();
+
+    /**
+     * Like {@link #getUsesLibraries()}, but marked optional by setting
+     * {@link R.styleable#AndroidManifestUsesLibrary_required} to false . Application is expected
+     * to handle absence manually.
+     * @see R.styleable#AndroidManifestUsesLibrary
+     */
+    @NonNull
+    List<String> getUsesOptionalLibraries();
+
+    /**
+     * TODO(b/135203078): Move static library stuff to an inner data class
+     * @see R.styleable#AndroidManifestUsesStaticLibrary
+     */
+    @NonNull
+    List<String> getUsesStaticLibraries();
+
+    /** @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest */
+    @Nullable
+    String[][] getUsesStaticLibrariesCertDigests();
+
+    /** @see R.styleable#AndroidManifestUsesStaticLibrary_version */
+    @Nullable
+    long[] getUsesStaticLibrariesVersions();
+
+    /**
+     * Intents that this package may query or require and thus requires visibility into.
+     * @see R.styleable#AndroidManifestQueriesIntent
+     */
+    @NonNull
+    List<Intent> getQueriesIntents();
+
+    /**
+     * Other packages that this package may query or require and thus requires visibility into.
+     * @see R.styleable#AndroidManifestQueriesPackage
+     */
+    @NonNull
+    List<String> getQueriesPackages();
+
+    /**
+     * Authorities that this package may query or require and thus requires visibility into.
+     * @see R.styleable#AndroidManifestQueriesProvider
+     */
+    @NonNull
+    Set<String> getQueriesProviders();
+
+    /**
+     * We store the application meta-data independently to avoid multiple unwanted references
+     * TODO(b/135203078): What does this comment mean?
+     * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?)
+     */
+    @Nullable
+    Bundle getMetaData();
+
+    /** @see R.styleable#AndroidManifestApplication_forceQueryable */
+    boolean isForceQueryable();
+
+    /**
+     * @see ApplicationInfo#maxAspectRatio
+     * @see R.styleable#AndroidManifestApplication_maxAspectRatio
+     */
+    float getMaxAspectRatio();
+
+    /**
+     * @see ApplicationInfo#minAspectRatio
+     * @see R.styleable#AndroidManifestApplication_minAspectRatio
+     */
+    float getMinAspectRatio();
+
+    /**
+     * @see ApplicationInfo#permission
+     * @see R.styleable#AndroidManifestApplication_permission
+     */
+    @Nullable
+    String getPermission();
+
+    /**
+     * @see ApplicationInfo#processName
+     * @see R.styleable#AndroidManifestApplication_process
+     */
+    @NonNull
+    String getProcessName();
+
+    /**
+     * @see PackageInfo#sharedUserId
+     * @see R.styleable#AndroidManifest_sharedUserId
+     */
+    @Deprecated
+    @Nullable
+    String getSharedUserId();
+
+    /** @see R.styleable#AndroidManifestStaticLibrary_name */
+    @Nullable
+    String getStaticSharedLibName();
+
+    /**
+     * @see ApplicationInfo#taskAffinity
+     * @see R.styleable#AndroidManifestApplication_taskAffinity
+     */
+    @Nullable
+    String getTaskAffinity();
+
+    /**
+     * @see ApplicationInfo#targetSdkVersion
+     * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion
+     */
+    int getTargetSdkVersion();
+
+    /**
+     * @see ApplicationInfo#uiOptions
+     * @see R.styleable#AndroidManifestApplication_uiOptions
+     */
+    int getUiOptions();
+
+    boolean isCrossProfile();
+
+    boolean isResizeableActivityViaSdkVersion();
+
+    /** @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED */
+    boolean isBaseHardwareAccelerated();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_resizeable
+     * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS
+     */
+    boolean isResizeable();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE */
+    boolean isAllowAudioPlaybackCapture();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_BACKUP */
+    boolean isAllowBackup();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA */
+    boolean isAllowClearUserData();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE */
+    boolean isAllowClearUserDataOnFailedRestore();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING */
+    boolean isAllowTaskReparenting();
+
+    /**
+     * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY
+     * @see ApplicationInfo#isResourceOverlay()
+     */
+    boolean isOverlay();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND */
+    boolean isBackupInForeground();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE */
+    boolean isCantSaveState();
+
+    /** @see ApplicationInfo#FLAG_DEBUGGABLE */
+    boolean isDebuggable();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE */
+    boolean isDefaultToDeviceProtectedStorage();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE */
+    boolean isDirectBootAware();
+
+    /** @see ApplicationInfo#FLAG_EXTERNAL_STORAGE */
+    boolean isExternalStorage();
+
+    /** @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS */
+    boolean isExtractNativeLibs();
+
+    /** @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY */
+    boolean isFullBackupOnly();
+
+    /** @see ApplicationInfo#FLAG_HAS_CODE */
+    boolean isHasCode();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA */
+    boolean isHasFragileUserData();
+
+    /** @see ApplicationInfo#FLAG_IS_GAME */
+    @Deprecated
+    boolean isGame();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING */
+    boolean isIsolatedSplitLoading();
+
+    /** @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE */
+    boolean isKillAfterRestore();
+
+    /** @see ApplicationInfo#FLAG_LARGE_HEAP */
+    boolean isLargeHeap();
+
+    /** @see ApplicationInfo#FLAG_MULTIARCH */
+    boolean isMultiArch();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE */
+    boolean isPartiallyDirectBootAware();
+
+    /** @see ApplicationInfo#FLAG_PERSISTENT */
+    boolean isPersistent();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL */
+    boolean isProfileableByShell();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE */
+    boolean isRequestLegacyExternalStorage();
+
+    /** @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION */
+    boolean isRestoreAnyVersion();
+
+    // ParsingPackageRead setSplitHasCode(int splitIndex, boolean splitHasCode);
+
+    /** Flags of any split APKs; ordered by parsed splitName */
+    @Nullable
+    int[] getSplitFlags();
+
+    /** @see ApplicationInfo#splitSourceDirs */
+    @Nullable
+    String[] getSplitCodePaths();
+
+    /** @see ApplicationInfo#splitDependencies */
+    @Nullable
+    SparseArray<int[]> getSplitDependencies();
+
+    /**
+     * @see ApplicationInfo#splitNames
+     * @see PackageInfo#splitNames
+     */
+    @Nullable
+    String[] getSplitNames();
+
+    /** @see PackageInfo#splitRevisionCodes */
+    int[] getSplitRevisionCodes();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY */
+    boolean isStaticSharedLibrary();
+
+    /** @see ApplicationInfo#FLAG_SUPPORTS_RTL */
+    boolean isSupportsRtl();
+
+    /** @see ApplicationInfo#FLAG_TEST_ONLY */
+    boolean isTestOnly();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX */
+    boolean isUseEmbeddedDex();
+
+    /** @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC */
+    boolean isUsesCleartextTraffic();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API */
+    boolean isUsesNonSdkApi();
+
+    /**
+     * Set if the any of components are visible to instant applications.
+     * @see R.styleable#AndroidManifestActivity_visibleToInstantApps
+     * @see R.styleable#AndroidManifestProvider_visibleToInstantApps
+     * @see R.styleable#AndroidManifestService_visibleToInstantApps
+     */
+    boolean isVisibleToInstantApps();
+
+    /** @see ApplicationInfo#FLAG_VM_SAFE_MODE */
+    boolean isVmSafeMode();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_anyDensity
+     * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES
+     */
+    boolean isAnyDensity();
+
+    /**
+     * @see ApplicationInfo#appComponentFactory
+     * @see R.styleable#AndroidManifestApplication_appComponentFactory
+     */
+    @Nullable
+    String getAppComponentFactory();
+
+    /**
+     * @see ApplicationInfo#backupAgentName
+     * @see R.styleable#AndroidManifestApplication_backupAgent
+     */
+    @Nullable
+    String getBackupAgentName();
+
+    /**
+     * @see ApplicationInfo#banner
+     * @see R.styleable#AndroidManifestApplication_banner
+     */
+    int getBanner();
+
+    /**
+     * @see ApplicationInfo#category
+     * @see R.styleable#AndroidManifestApplication_appCategory
+     */
+    int getCategory();
+
+    /**
+     * @see ApplicationInfo#classLoaderName
+     * @see R.styleable#AndroidManifestApplication_classLoader
+     */
+    @Nullable
+    String getClassLoaderName();
+
+    /**
+     * @see ApplicationInfo#className
+     * @see R.styleable#AndroidManifestApplication_name
+     */
+    @Nullable
+    String getClassName();
+
+    String getPackageName();
+
+    /** Path of base APK */
+    String getBaseCodePath();
+
+    /**
+     * Path where this package was found on disk. For monolithic packages
+     * this is path to single base APK file; for cluster packages this is
+     * path to the cluster directory.
+     */
+    @NonNull
+    String getCodePath();
+
+    /**
+     * @see ApplicationInfo#compatibleWidthLimitDp
+     * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
+     */
+    int getCompatibleWidthLimitDp();
+
+    /**
+     * @see ApplicationInfo#descriptionRes
+     * @see R.styleable#AndroidManifestApplication_description
+     */
+    int getDescriptionRes();
+
+    /**
+     * @see ApplicationInfo#enabled
+     * @see R.styleable#AndroidManifestApplication_enabled
+     */
+    boolean isEnabled();
+
+    /**
+     * @see ApplicationInfo#fullBackupContent
+     * @see R.styleable#AndroidManifestApplication_fullBackupContent
+     */
+    int getFullBackupContent();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
+    boolean isHasDomainUrls();
+
+    /**
+     * @see ApplicationInfo#iconRes
+     * @see R.styleable#AndroidManifestApplication_icon
+     */
+    int getIconRes();
+
+    /**
+     * @see ApplicationInfo#installLocation
+     * @see R.styleable#AndroidManifest_installLocation
+     */
+    int getInstallLocation();
+
+    /**
+     * @see ApplicationInfo#labelRes
+     * @see R.styleable#AndroidManifestApplication_label
+     */
+    int getLabelRes();
+
+    /**
+     * @see ApplicationInfo#largestWidthLimitDp
+     * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
+     */
+    int getLargestWidthLimitDp();
+
+    /**
+     * @see ApplicationInfo#logo
+     * @see R.styleable#AndroidManifestApplication_logo
+     */
+    int getLogo();
+
+    /**
+     * @see ApplicationInfo#manageSpaceActivityName
+     * @see R.styleable#AndroidManifestApplication_manageSpaceActivity
+     */
+    @Nullable
+    String getManageSpaceActivityName();
+
+    /**
+     * @see ApplicationInfo#minSdkVersion
+     * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion
+     */
+    int getMinSdkVersion();
+
+    /**
+     * @see ApplicationInfo#networkSecurityConfigRes
+     * @see R.styleable#AndroidManifestApplication_networkSecurityConfig
+     */
+    int getNetworkSecurityConfigRes();
+
+    /**
+     * If {@link R.styleable#AndroidManifestApplication_label} is a string literal, this is it.
+     * Otherwise, it's stored as {@link #getLabelRes()}.
+     * @see ApplicationInfo#nonLocalizedLabel
+     * @see R.styleable#AndroidManifestApplication_label
+     */
+    @Nullable
+    CharSequence getNonLocalizedLabel();
+
+    /**
+     * @see PackageInfo#overlayCategory
+     * @see R.styleable#AndroidManifestResourceOverlay_category
+     */
+    @Nullable
+    String getOverlayCategory();
+
+    /** @see PackageInfo#mOverlayIsStatic */
+    boolean isOverlayIsStatic();
+
+    /**
+     * @see PackageInfo#overlayPriority
+     * @see R.styleable#AndroidManifestResourceOverlay_priority
+     */
+    int getOverlayPriority();
+
+    /**
+     * @see PackageInfo#overlayTarget
+     * @see R.styleable#AndroidManifestResourceOverlay_targetPackage
+     */
+    @Nullable
+    String getOverlayTarget();
+
+    /**
+     * @see PackageInfo#targetOverlayableName
+     * @see R.styleable#AndroidManifestResourceOverlay_targetName
+     */
+    @Nullable
+    String getOverlayTargetName();
+
+    /**
+     * If a system app declares {@link #getOriginalPackages()}, and the app was previously installed
+     * under one of those original package names, the {@link #getPackageName()} system identifier
+     * will be changed to that previously installed name. This will then be non-null, set to the
+     * manifest package name, for tracking the package under its true name.
+     *
+     * TODO(b/135203078): Remove this in favor of checking originalPackages.isEmpty and
+     *  getManifestPackageName
+     */
+    @Nullable
+    String getRealPackage();
+
+    /**
+     * The required account type without which this application will not function.
+     *
+     * @see PackageInfo#requiredAccountType
+     * @see R.styleable#AndroidManifestApplication_requiredAccountType
+     */
+    @Nullable
+    String getRequiredAccountType();
+
+    /**
+     * @see PackageInfo#requiredForAllUsers
+     * @see R.styleable#AndroidManifestApplication_requiredForAllUsers
+     */
+    boolean isRequiredForAllUsers();
+
+    /**
+     * @see ApplicationInfo#requiresSmallestWidthDp
+     * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
+     */
+    int getRequiresSmallestWidthDp();
+
+    /**
+     * SHA-512 hash of the only APK that can be used to update a system package.
+     * @see R.styleable#AndroidManifestRestrictUpdate
+     */
+    @Nullable
+    byte[] getRestrictUpdateHash();
+
+    /**
+     * The restricted account authenticator type that is used by this application
+     *
+     * @see PackageInfo#restrictedAccountType
+     * @see R.styleable#AndroidManifestApplication_restrictedAccountType
+     */
+    @Nullable
+    String getRestrictedAccountType();
+
+    /**
+     * @see ApplicationInfo#roundIconRes
+     * @see R.styleable#AndroidManifestApplication_roundIcon
+     */
+    int getRoundIconRes();
+
+    /**
+     * @see PackageInfo#sharedUserLabel
+     * @see R.styleable#AndroidManifest_sharedUserLabel
+     */
+    @Deprecated
+    int getSharedUserLabel();
+
+    /**
+     * The signature data of all APKs in this package, which must be exactly the same across the
+     * base and splits.
+     */
+    PackageParser.SigningDetails getSigningDetails();
+
+    /**
+     * @see ApplicationInfo#splitClassLoaderNames
+     * @see R.styleable#AndroidManifestApplication_classLoader
+     */
+    @Nullable
+    String[] getSplitClassLoaderNames();
+
+    /** @see R.styleable#AndroidManifestStaticLibrary_version */
+    long getStaticSharedLibVersion();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_largeScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS
+     */
+    boolean isSupportsLargeScreens();
+
+    /**
+     * If omitted from manifest, returns true.
+     * @see R.styleable#AndroidManifestSupportsScreens_normalScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS
+     */
+    boolean isSupportsNormalScreens();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_smallScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS
+     */
+    boolean isSupportsSmallScreens();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#GINGERBREAD}.
+     * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS
+     */
+    boolean isSupportsExtraLargeScreens();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING */
+    boolean isAllowNativeHeapPointerTagging();
+
+    boolean hasPreserveLegacyExternalStorage();
+
+    /**
+     * @see ApplicationInfo#targetSandboxVersion
+     * @see R.styleable#AndroidManifest_targetSandboxVersion
+     */
+    @Deprecated
+    int getTargetSandboxVersion();
+
+    /**
+     * @see ApplicationInfo#theme
+     * @see R.styleable#AndroidManifestApplication_theme
+     */
+    int getTheme();
+
+    /**
+     * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
+     * {@link PackageParser#TAG_KEY_SETS}.
+     * @see R.styleable#AndroidManifestUpgradeKeySet
+     */
+    @NonNull
+    Set<String> getUpgradeKeySets();
+
+    /**
+     * The install time abi override to choose 32bit abi's when multiple abi's
+     * are present. This is only meaningfull for multiarch applications.
+     * The use32bitAbi attribute is ignored if cpuAbiOverride is also set.
+     */
+    boolean isUse32BitAbi();
+
+    /** @see ApplicationInfo#volumeUuid */
+    @Nullable
+    String getVolumeUuid();
+
+    /** @see ApplicationInfo#zygotePreloadName */
+    @Nullable
+    String getZygotePreloadName();
+
+    /** Revision code of base APK */
+    int getBaseRevisionCode();
+
+    /** @see PackageInfo#versionName */
+    @Nullable
+    String getVersionName();
+
+    /** @see PackageInfo#versionCodeMajor */
+    @Nullable
+    int getVersionCode();
+
+    /** @see PackageInfo#versionCodeMajor */
+    @Nullable
+    int getVersionCodeMajor();
+
+    /**
+     * @see ApplicationInfo#compileSdkVersion
+     * @see R.styleable#AndroidManifest_compileSdkVersion
+     */
+    int getCompileSdkVersion();
+
+    /**
+     * @see ApplicationInfo#compileSdkVersionCodename
+     * @see R.styleable#AndroidManifest_compileSdkVersionCodename
+     */
+    @Nullable
+    String getCompileSdkVersionCodeName();
+
+    @Nullable
+    Set<String> getMimeGroups();
+
+    // TODO(b/135203078): Hide and enforce going through PackageInfoUtils
+    ApplicationInfo toAppInfoWithoutState();
+}
diff --git a/core/java/android/content/pm/parsing/ParsingPackageUtils.java b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
new file mode 100644
index 0000000..40754df
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingPackageUtils.java
@@ -0,0 +1,2673 @@
+/*
+ * 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.content.pm.parsing;
+
+import static android.content.pm.ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+import static android.content.pm.PackageManager.FEATURE_WATCH;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
+import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
+import static android.os.Build.VERSION_CODES.DONUT;
+import static android.os.Build.VERSION_CODES.O;
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+
+import android.annotation.AnyRes;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StyleableRes;
+import android.app.ActivityThread;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.PackageParser.SigningDetails;
+import android.content.pm.Signature;
+import android.content.pm.parsing.component.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedActivityUtils;
+import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedFeatureUtils;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedInstrumentationUtils;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedIntentInfoUtils;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedPermissionUtils;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProcessUtils;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedProviderUtils;
+import android.content.pm.parsing.component.ParsedService;
+import android.content.pm.parsing.component.ParsedServiceUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
+import android.content.pm.split.DefaultSplitAssetLoader;
+import android.content.pm.split.SplitAssetDependencyLoader;
+import android.content.pm.split.SplitAssetLoader;
+import android.content.res.ApkAssets;
+import android.content.res.AssetManager;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.os.FileUtils;
+import android.os.RemoteException;
+import android.os.SystemProperties;
+import android.os.Trace;
+import android.os.ext.SdkExtensions;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
+import android.util.Pair;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.TypedValue;
+import android.util.apk.ApkSignatureVerifier;
+
+import com.android.internal.R;
+import com.android.internal.os.ClassLoaderFactory;
+import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.XmlUtils;
+
+import libcore.io.IoUtils;
+import libcore.util.EmptyArray;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.IOException;
+import java.security.PublicKey;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * TODO(b/135203078): Differentiate between parse_ methods and some add_ method for whether it
+ * mutates the passed-in component or not. Or consolidate so all parse_ methods mutate.
+ *
+ * @hide
+ */
+public class ParsingPackageUtils {
+
+    public static final String TAG = ParsingUtils.TAG;
+
+    private boolean mOnlyCoreApps;
+    private String[] mSeparateProcesses;
+    private DisplayMetrics mDisplayMetrics;
+    private Callback mCallback;
+
+    public ParsingPackageUtils(boolean onlyCoreApps, String[] separateProcesses,
+            DisplayMetrics displayMetrics, @NonNull Callback callback) {
+        mOnlyCoreApps = onlyCoreApps;
+        mSeparateProcesses = separateProcesses;
+        mDisplayMetrics = displayMetrics;
+        mCallback = callback;
+    }
+
+    /**
+     * Parse the package at the given location. Automatically detects if the
+     * package is a monolithic style (single APK file) or cluster style
+     * (directory of APKs).
+     * <p>
+     * This performs sanity checking on cluster style packages, such as
+     * requiring identical package name and version codes, a single base APK,
+     * and unique split names.
+     * <p>
+     * Note that this <em>does not</em> perform signature verification; that
+     * must be done separately in {@link #collectCertificates(ParsingPackageRead, boolean)}.
+     *
+     * If {@code useCaches} is true, the package parser might return a cached
+     * result from a previous parse of the same {@code packageFile} with the same
+     * {@code flags}. Note that this method does not check whether {@code packageFile}
+     * has changed since the last parse, it's up to callers to do so.
+     *
+     * @see PackageParser#parsePackageLite(File, int)
+     */
+    public ParseResult<ParsingPackage> parsePackage(ParseInput input, File packageFile,
+            int flags)
+            throws PackageParserException {
+        if (packageFile.isDirectory()) {
+            return parseClusterPackage(input, packageFile, flags);
+        } else {
+            return parseMonolithicPackage(input, packageFile, flags);
+        }
+    }
+
+    /**
+     * Parse all APKs contained in the given directory, treating them as a
+     * single package. This also performs sanity checking, such as requiring
+     * identical package name and version codes, a single base APK, and unique
+     * split names.
+     * <p>
+     * Note that this <em>does not</em> perform signature verification; that
+     * must be done separately in {@link #collectCertificates(ParsingPackageRead, boolean)}.
+     */
+    private ParseResult<ParsingPackage> parseClusterPackage(ParseInput input, File packageDir,
+            int flags) throws PackageParserException {
+        final PackageParser.PackageLite lite = ApkLiteParseUtils.parseClusterPackageLite(packageDir,
+                0);
+        if (mOnlyCoreApps && !lite.coreApp) {
+            return input.error("Not a coreApp: " + packageDir);
+        }
+
+        // Build the split dependency tree.
+        SparseArray<int[]> splitDependencies = null;
+        final SplitAssetLoader assetLoader;
+        if (lite.isolatedSplits && !ArrayUtils.isEmpty(lite.splitNames)) {
+            try {
+                splitDependencies = SplitAssetDependencyLoader.createDependenciesFromPackage(lite);
+                assetLoader = new SplitAssetDependencyLoader(lite, splitDependencies, flags);
+            } catch (SplitAssetDependencyLoader.IllegalDependencyException e) {
+                return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST, e.getMessage());
+            }
+        } else {
+            assetLoader = new DefaultSplitAssetLoader(lite, flags);
+        }
+
+        try {
+            final AssetManager assets = assetLoader.getBaseAssetManager();
+            final File baseApk = new File(lite.baseCodePath);
+            ParseResult<ParsingPackage> result = parseBaseApk(input, baseApk,
+                    lite.codePath, assets, flags);
+            // TODO(b/135203078): Pass original error up?
+            if (result.isError()) {
+                return input.error(INSTALL_PARSE_FAILED_NOT_APK,
+                        "Failed to parse base APK: " + baseApk);
+            }
+
+            ParsingPackage pkg = result.getResult();
+            if (!ArrayUtils.isEmpty(lite.splitNames)) {
+                pkg.asSplit(
+                        lite.splitNames,
+                        lite.splitCodePaths,
+                        lite.splitRevisionCodes,
+                        splitDependencies
+                );
+                final int num = lite.splitNames.length;
+
+                for (int i = 0; i < num; i++) {
+                    final AssetManager splitAssets = assetLoader.getSplitAssetManager(i);
+                    parseSplitApk(input, pkg, i, splitAssets, flags);
+                }
+            }
+
+            pkg.setUse32BitAbi(lite.use32bitAbi);
+            return input.success(pkg);
+        } finally {
+            IoUtils.closeQuietly(assetLoader);
+        }
+    }
+
+    /**
+     * Parse the given APK file, treating it as as a single monolithic package.
+     * <p>
+     * Note that this <em>does not</em> perform signature verification; that
+     * must be done separately in {@link #collectCertificates(ParsingPackageRead, boolean)}.
+     */
+    private ParseResult<ParsingPackage> parseMonolithicPackage(ParseInput input, File apkFile,
+            int flags) throws PackageParserException {
+        final PackageParser.PackageLite lite = ApkLiteParseUtils.parseMonolithicPackageLite(apkFile,
+                flags);
+        if (mOnlyCoreApps && !lite.coreApp) {
+            return input.error("Not a coreApp: " + apkFile);
+        }
+
+        final SplitAssetLoader assetLoader = new DefaultSplitAssetLoader(lite, flags);
+        try {
+            ParseResult<ParsingPackage> result = parseBaseApk(input,
+                    apkFile,
+                    apkFile.getCanonicalPath(),
+                    assetLoader.getBaseAssetManager(), flags);
+            if (result.isError()) {
+                return input.error(result);
+            }
+
+            return input.success(result.getResult()
+                    .setUse32BitAbi(lite.use32bitAbi));
+        } catch (IOException e) {
+            return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+                    "Failed to get path: " + apkFile, e);
+        } finally {
+            IoUtils.closeQuietly(assetLoader);
+        }
+    }
+
+    private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
+            String codePath, AssetManager assets, int flags) {
+        final String apkPath = apkFile.getAbsolutePath();
+
+        String volumeUuid = null;
+        if (apkPath.startsWith(PackageParser.MNT_EXPAND)) {
+            final int end = apkPath.indexOf('/', PackageParser.MNT_EXPAND.length());
+            volumeUuid = apkPath.substring(PackageParser.MNT_EXPAND.length(), end);
+        }
+
+        if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);
+
+        final int cookie = assets.findCookieForPath(apkPath);
+        if (cookie == 0) {
+            return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                    "Failed adding asset path: " + apkPath);
+        }
+
+        try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
+                PackageParser.ANDROID_MANIFEST_FILENAME)) {
+            final Resources res = new Resources(assets, mDisplayMetrics, null);
+
+            ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,
+                    parser, flags);
+            if (result.isError()) {
+                return input.error(result.getErrorCode(),
+                        apkPath + " (at " + parser.getPositionDescription() + "): "
+                                + result.getErrorMessage());
+            }
+
+            ParsingPackage pkg = result.getResult();
+            ApkAssets apkAssets = assets.getApkAssets()[0];
+            if (apkAssets.definesOverlayable()) {
+                SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
+                int size = packageNames.size();
+                for (int index = 0; index < size; index++) {
+                    String packageName = packageNames.get(index);
+                    Map<String, String> overlayableToActor = assets.getOverlayableMap(packageName);
+                    if (overlayableToActor != null && !overlayableToActor.isEmpty()) {
+                        for (String overlayable : overlayableToActor.keySet()) {
+                            pkg.addOverlayable(overlayable, overlayableToActor.get(overlayable));
+                        }
+                    }
+                }
+            }
+
+            pkg.setVolumeUuid(volumeUuid)
+                    .setSigningDetails(SigningDetails.UNKNOWN);
+
+            return input.success(pkg);
+        } catch (Exception e) {
+            return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+                    "Failed to read manifest from " + apkPath, e);
+        }
+    }
+
+    private ParseResult<ParsingPackage> parseSplitApk(ParseInput input,
+            ParsingPackage pkg, int splitIndex, AssetManager assets, int flags) {
+        final String apkPath = pkg.getSplitCodePaths()[splitIndex];
+
+        if (PackageParser.DEBUG_JAR) Slog.d(TAG, "Scanning split APK: " + apkPath);
+
+        // This must always succeed, as the path has been added to the AssetManager before.
+        final int cookie = assets.findCookieForPath(apkPath);
+        if (cookie == 0) {
+            return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                    "Failed adding asset path: " + apkPath);
+        }
+        try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
+                PackageParser.ANDROID_MANIFEST_FILENAME)) {
+            Resources res = new Resources(assets, mDisplayMetrics, null);
+            ParseResult<ParsingPackage> parseResult = parseSplitApk(input, pkg, res,
+                    parser, flags, splitIndex);
+            if (parseResult.isError()) {
+                return input.error(parseResult.getErrorCode(),
+                        apkPath + " (at " + parser.getPositionDescription() + "): "
+                                + parseResult.getErrorMessage());
+            }
+
+            return parseResult;
+        } catch (Exception e) {
+            return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
+                    "Failed to read manifest from " + apkPath, e);
+        }
+    }
+
+    /**
+     * Parse the manifest of a <em>base APK</em>. When adding new features you
+     * need to consider whether they should be supported by split APKs and child
+     * packages.
+     *
+     * @param apkPath The package apk file path
+     * @param res     The resources from which to resolve values
+     * @param parser  The manifest parser
+     * @param flags   Flags how to parse
+     * @return Parsed package or null on error.
+     */
+    private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, String apkPath,
+            String codePath, Resources res, XmlResourceParser parser, int flags)
+            throws XmlPullParserException, IOException {
+        final String splitName;
+        final String pkgName;
+
+        try {
+            Pair<String, String> packageSplit = PackageParser.parsePackageSplitNames(parser,
+                    parser);
+            pkgName = packageSplit.first;
+            splitName = packageSplit.second;
+
+            if (!TextUtils.isEmpty(splitName)) {
+                return input.error(
+                        PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
+                        "Expected base APK, but found split " + splitName
+                );
+            }
+        } catch (PackageParserException e) {
+            return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME);
+        }
+
+        TypedArray manifestArray = res.obtainAttributes(parser, R.styleable.AndroidManifest);
+        try {
+            boolean isCoreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
+
+            ParsingPackage pkg = mCallback.startParsingPackage(pkgName, apkPath, codePath,
+                    manifestArray, isCoreApp);
+
+            ParseResult<ParsingPackage> result = parseBaseApkTags(input, pkg, manifestArray,
+                    res, parser, flags);
+            if (result.isError()) {
+                return result;
+            }
+
+            return input.success(pkg);
+        } finally {
+            manifestArray.recycle();
+        }
+    }
+
+    /**
+     * Parse the manifest of a <em>split APK</em>.
+     * <p>
+     * Note that split APKs have many more restrictions on what they're capable
+     * of doing, so many valid features of a base APK have been carefully
+     * omitted here.
+     *
+     * @param pkg builder to fill
+     * @return false on failure
+     */
+    private ParseResult<ParsingPackage> parseSplitApk(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser, int flags, int splitIndex)
+            throws XmlPullParserException, IOException, PackageParserException {
+        AttributeSet attrs = parser;
+
+        // We parsed manifest tag earlier; just skip past it
+        PackageParser.parsePackageSplitNames(parser, attrs);
+
+        int type;
+
+        boolean foundApp = false;
+
+        int outerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            if (outerDepth + 1 < parser.getDepth() || type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult result;
+            String tagName = parser.getName();
+            if (PackageParser.TAG_APPLICATION.equals(tagName)) {
+                if (foundApp) {
+                    if (PackageParser.RIGID_PARSER) {
+                        result = input.error("<manifest> has more than one <application>");
+                    } else {
+                        Slog.w(TAG, "<manifest> has more than one <application>");
+                        result = input.success(null);
+                    }
+                } else {
+                    foundApp = true;
+                    result = parseSplitApplication(input, pkg, res, parser, flags, splitIndex);
+                }
+            } else {
+                result = ParsingUtils.unknownTag("<manifest>", pkg, parser, input);
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        if (!foundApp) {
+            return input.error(
+                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY,
+                    "<manifest> does not contain an <application>"
+            );
+        }
+
+        return input.success(pkg);
+    }
+
+    /**
+     * Parse the {@code application} XML tree at the current parse location in a
+     * <em>split APK</em> manifest.
+     * <p>
+     * Note that split APKs have many more restrictions on what they're capable
+     * of doing, so many valid features of a base APK have been carefully
+     * omitted here.
+     */
+    private ParseResult<ParsingPackage> parseSplitApplication(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags, int splitIndex)
+            throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestApplication);
+        try {
+            pkg.setSplitHasCode(splitIndex, sa.getBoolean(
+                    R.styleable.AndroidManifestApplication_hasCode, true));
+
+            final String classLoaderName = sa.getString(
+                    R.styleable.AndroidManifestApplication_classLoader);
+            if (classLoaderName == null || ClassLoaderFactory.isValidClassLoaderName(
+                    classLoaderName)) {
+                pkg.setSplitClassLoaderName(splitIndex, classLoaderName);
+            } else {
+                return input.error("Invalid class loader name: " + classLoaderName);
+            }
+        } finally {
+            sa.recycle();
+        }
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            ParsedMainComponent mainComponent = null;
+
+            final ParseResult result;
+            String tagName = parser.getName();
+            boolean isActivity = false;
+            switch (tagName) {
+                case "activity":
+                    isActivity = true;
+                    // fall-through
+                case "receiver":
+                    ParseResult<ParsedActivity> activityResult =
+                            ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
+                                    res,
+                                    parser, flags, PackageParser.sUseRoundIcon, input);
+                    if (activityResult.isSuccess()) {
+                        ParsedActivity activity = activityResult.getResult();
+                        if (isActivity) {
+                            pkg.addActivity(activity);
+                        } else {
+                            pkg.addReceiver(activity);
+                        }
+                        mainComponent = activity;
+                    }
+                    result = activityResult;
+                    break;
+                case "service":
+                    ParseResult<ParsedService> serviceResult = ParsedServiceUtils.parseService(
+                            mSeparateProcesses, pkg, res, parser, flags,
+                            PackageParser.sUseRoundIcon, input);
+                    if (serviceResult.isSuccess()) {
+                        ParsedService service = serviceResult.getResult();
+                        pkg.addService(service);
+                        mainComponent = service;
+                    }
+                    result = serviceResult;
+                    break;
+                case "provider":
+                    ParseResult<ParsedProvider> providerResult =
+                            ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
+                                    flags, PackageParser.sUseRoundIcon, input);
+                    if (providerResult.isSuccess()) {
+                        ParsedProvider provider = providerResult.getResult();
+                        pkg.addProvider(provider);
+                        mainComponent = provider;
+                    }
+                    result = providerResult;
+                    break;
+                case "activity-alias":
+                    activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res, parser,
+                            PackageParser.sUseRoundIcon, input);
+                    if (activityResult.isSuccess()) {
+                        ParsedActivity activity = activityResult.getResult();
+                        pkg.addActivity(activity);
+                        mainComponent = activity;
+                    }
+
+                    result = activityResult;
+                    break;
+                default:
+                    result = parseSplitBaseAppChildTags(input, tagName, pkg, res, parser);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+
+            if (mainComponent != null && mainComponent.getSplitName() == null) {
+                // If the loaded component did not specify a split, inherit the split name
+                // based on the split it is defined in.
+                // This is used to later load the correct split when starting this
+                // component.
+                mainComponent.setSplitName(pkg.getSplitNames()[splitIndex]);
+            }
+        }
+
+        return input.success(pkg);
+    }
+
+    /**
+     * For parsing non-MainComponents. Main ones have an order and some special handling which is
+     * done directly in {@link #parseSplitApplication(ParseInput, ParsingPackage, Resources,
+     * XmlResourceParser, int, int)}.
+     */
+    private ParseResult parseSplitBaseAppChildTags(ParseInput input, String tag, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
+        switch (tag) {
+            case "meta-data":
+                // note: application meta-data is stored off to the side, so it can
+                // remain null in the primary copy (we like to avoid extra copies because
+                // it can be large)
+                ParseResult<Bundle> metaDataResult = parseMetaData(pkg, res, parser,
+                        pkg.getMetaData(), input);
+                if (metaDataResult.isSuccess()) {
+                    pkg.setMetaData(metaDataResult.getResult());
+                }
+                return metaDataResult;
+            case "uses-static-library":
+                return parseUsesStaticLibrary(input, pkg, res, parser);
+            case "uses-library":
+                return parseUsesLibrary(input, pkg, res, parser);
+            case "uses-package":
+                // Dependencies for app installers; we don't currently try to
+                // enforce this.
+                return input.success(null);
+            default:
+                return ParsingUtils.unknownTag("<application>", pkg, parser, input);
+        }
+    }
+
+    private ParseResult<ParsingPackage> parseBaseApkTags(ParseInput input, ParsingPackage pkg,
+            TypedArray sa, Resources res, XmlResourceParser parser, int flags)
+            throws XmlPullParserException, IOException {
+        ParseResult<ParsingPackage> sharedUserResult = parseSharedUser(input, pkg, sa);
+        if (sharedUserResult.isError()) {
+            return sharedUserResult;
+        }
+
+        pkg.setInstallLocation(anInt(PackageParser.PARSE_DEFAULT_INSTALL_LOCATION,
+                R.styleable.AndroidManifest_installLocation, sa))
+                .setTargetSandboxVersion(anInt(PackageParser.PARSE_DEFAULT_TARGET_SANDBOX,
+                        R.styleable.AndroidManifest_targetSandboxVersion, sa))
+                /* Set the global "on SD card" flag */
+                .setExternalStorage((flags & PackageParser.PARSE_EXTERNAL_STORAGE) != 0)
+                .setIsolatedSplitLoading(
+                        bool(false, R.styleable.AndroidManifest_isolatedSplits, sa));
+
+        boolean foundApp = false;
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            final ParseResult result;
+
+            // TODO(b/135203078): Convert to instance methods to share variables
+            // <application> has special logic, so it's handled outside the general method
+            if (PackageParser.TAG_APPLICATION.equals(tagName)) {
+                if (foundApp) {
+                    if (PackageParser.RIGID_PARSER) {
+                        result = input.error("<manifest> has more than one <application>");
+                    } else {
+                        Slog.w(TAG, "<manifest> has more than one <application>");
+                        result = input.success(null);
+                    }
+                } else {
+                    foundApp = true;
+                    result = parseBaseApplication(input, pkg, res, parser, flags);
+                }
+            } else {
+                result = parseBaseApkTag(tagName, input, pkg, res, parser, flags);
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        if (!foundApp && ArrayUtils.size(pkg.getInstrumentations()) == 0) {
+            return input.error(
+                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY,
+                    "<manifest> does not contain an <application> or <instrumentation>"
+            );
+        }
+
+        if (!ParsedFeature.isCombinationValid(pkg.getFeatures())) {
+            return input.error(
+                    INSTALL_PARSE_FAILED_BAD_MANIFEST,
+                    "Combination <feature> tags are not valid"
+            );
+        }
+
+        convertNewPermissions(pkg);
+
+        convertSplitPermissions(pkg);
+
+        // At this point we can check if an application is not supporting densities and hence
+        // cannot be windowed / resized. Note that an SDK version of 0 is common for
+        // pre-Doughnut applications.
+        if (pkg.getTargetSdkVersion() < DONUT
+                || (!pkg.isSupportsSmallScreens()
+                && !pkg.isSupportsNormalScreens()
+                && !pkg.isSupportsLargeScreens()
+                && !pkg.isSupportsExtraLargeScreens()
+                && !pkg.isResizeable()
+                && !pkg.isAnyDensity())) {
+            adjustPackageToBeUnresizeableAndUnpipable(pkg);
+        }
+
+        return input.success(pkg);
+    }
+
+    private ParseResult parseBaseApkTag(String tag, ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)
+            throws IOException, XmlPullParserException {
+        switch (tag) {
+            case PackageParser.TAG_OVERLAY:
+                return parseOverlay(input, pkg, res, parser);
+            case PackageParser.TAG_KEY_SETS:
+                return parseKeySets(input, pkg, res, parser);
+            case PackageParser.TAG_FEATURE:
+                return parseFeature(input, pkg, res, parser);
+            case PackageParser.TAG_PERMISSION_GROUP:
+                return parsePermissionGroup(input, pkg, res, parser);
+            case PackageParser.TAG_PERMISSION:
+                return parsePermission(input, pkg, res, parser);
+            case PackageParser.TAG_PERMISSION_TREE:
+                return parsePermissionTree(input, pkg, res, parser);
+            case PackageParser.TAG_USES_PERMISSION:
+            case PackageParser.TAG_USES_PERMISSION_SDK_M:
+            case PackageParser.TAG_USES_PERMISSION_SDK_23:
+                return parseUsesPermission(input, pkg, res, parser);
+            case PackageParser.TAG_USES_CONFIGURATION:
+                return parseUsesConfiguration(input, pkg, res, parser);
+            case PackageParser.TAG_USES_FEATURE:
+                return parseUsesFeature(input, pkg, res, parser);
+            case PackageParser.TAG_FEATURE_GROUP:
+                return parseFeatureGroup(input, pkg, res, parser);
+            case PackageParser.TAG_USES_SDK:
+                return parseUsesSdk(input, pkg, res, parser);
+            case PackageParser.TAG_SUPPORT_SCREENS:
+                return parseSupportScreens(input, pkg, res, parser);
+            case PackageParser.TAG_PROTECTED_BROADCAST:
+                return parseProtectedBroadcast(input, pkg, res, parser);
+            case PackageParser.TAG_INSTRUMENTATION:
+                return parseInstrumentation(input, pkg, res, parser);
+            case PackageParser.TAG_ORIGINAL_PACKAGE:
+                return parseOriginalPackage(input, pkg, res, parser);
+            case PackageParser.TAG_ADOPT_PERMISSIONS:
+                return parseAdoptPermissions(input, pkg, res, parser);
+            case PackageParser.TAG_USES_GL_TEXTURE:
+            case PackageParser.TAG_COMPATIBLE_SCREENS:
+            case PackageParser.TAG_SUPPORTS_INPUT:
+            case PackageParser.TAG_EAT_COMMENT:
+                // Just skip this tag
+                XmlUtils.skipCurrentTag(parser);
+                return input.success(pkg);
+            case PackageParser.TAG_RESTRICT_UPDATE:
+                return parseRestrictUpdateHash(flags, input, pkg, res, parser);
+            case PackageParser.TAG_QUERIES:
+                return parseQueries(input, pkg, res, parser);
+            default:
+                return ParsingUtils.unknownTag("<manifest>", pkg, parser, input);
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseSharedUser(ParseInput input,
+            ParsingPackage pkg, TypedArray sa) {
+        String str = nonConfigString(0, R.styleable.AndroidManifest_sharedUserId, sa);
+        if (TextUtils.isEmpty(str)) {
+            return input.success(pkg);
+        }
+
+        ParseResult nameResult = validateName(input, str, true, true);
+        if (nameResult.isError()) {
+            if ("android".equals(pkg.getPackageName())) {
+                nameResult.ignoreError();
+            } else {
+                return input.error(PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID,
+                        "<manifest> specifies bad sharedUserId name \"" + str + "\": "
+                                + nameResult.getErrorMessage());
+            }
+        }
+
+        return input.success(pkg
+                .setSharedUserId(str.intern())
+                .setSharedUserLabel(resId(R.styleable.AndroidManifest_sharedUserLabel, sa)));
+    }
+
+    private static ParseResult<ParsingPackage> parseKeySets(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        // we've encountered the 'key-sets' tag
+        // all the keys and keysets that we want must be defined here
+        // so we're going to iterate over the parser and pull out the things we want
+        int outerDepth = parser.getDepth();
+        int currentKeySetDepth = -1;
+        int type;
+        String currentKeySet = null;
+        ArrayMap<String, PublicKey> publicKeys = new ArrayMap<>();
+        ArraySet<String> upgradeKeySets = new ArraySet<>();
+        ArrayMap<String, ArraySet<String>> definedKeySets = new ArrayMap<>();
+        ArraySet<String> improperKeySets = new ArraySet<>();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG) {
+                if (parser.getDepth() == currentKeySetDepth) {
+                    currentKeySet = null;
+                    currentKeySetDepth = -1;
+                }
+                continue;
+            }
+            String tagName = parser.getName();
+            switch (tagName) {
+                case "key-set": {
+                    if (currentKeySet != null) {
+                        return input.error("Improperly nested 'key-set' tag at "
+                                + parser.getPositionDescription());
+                    }
+                    TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestKeySet);
+                    try {
+                        final String keysetName = sa.getNonResourceString(
+                                R.styleable.AndroidManifestKeySet_name);
+                        definedKeySets.put(keysetName, new ArraySet<>());
+                        currentKeySet = keysetName;
+                        currentKeySetDepth = parser.getDepth();
+                    } finally {
+                        sa.recycle();
+                    }
+                } break;
+                case "public-key": {
+                    if (currentKeySet == null) {
+                        return input.error("Improperly nested 'key-set' tag at "
+                                + parser.getPositionDescription());
+                    }
+                    TypedArray sa = res.obtainAttributes(parser,
+                            R.styleable.AndroidManifestPublicKey);
+                    try {
+                        final String publicKeyName = nonResString(
+                                R.styleable.AndroidManifestPublicKey_name, sa);
+                        final String encodedKey = nonResString(
+                                R.styleable.AndroidManifestPublicKey_value, sa);
+                        if (encodedKey == null && publicKeys.get(publicKeyName) == null) {
+                            return input.error("'public-key' " + publicKeyName
+                                    + " must define a public-key value on first use at "
+                                    + parser.getPositionDescription());
+                        } else if (encodedKey != null) {
+                            PublicKey currentKey = PackageParser.parsePublicKey(encodedKey);
+                            if (currentKey == null) {
+                                Slog.w(TAG, "No recognized valid key in 'public-key' tag at "
+                                        + parser.getPositionDescription() + " key-set "
+                                        + currentKeySet
+                                        + " will not be added to the package's defined key-sets.");
+                                improperKeySets.add(currentKeySet);
+                                XmlUtils.skipCurrentTag(parser);
+                                continue;
+                            }
+                            if (publicKeys.get(publicKeyName) == null
+                                    || publicKeys.get(publicKeyName).equals(currentKey)) {
+
+                                /* public-key first definition, or matches old definition */
+                                publicKeys.put(publicKeyName, currentKey);
+                            } else {
+                                return input.error("Value of 'public-key' " + publicKeyName
+                                        + " conflicts with previously defined value at "
+                                        + parser.getPositionDescription());
+                            }
+                        }
+                        definedKeySets.get(currentKeySet).add(publicKeyName);
+                        XmlUtils.skipCurrentTag(parser);
+                    } finally {
+                        sa.recycle();
+                    }
+                } break;
+                case "upgrade-key-set": {
+                    TypedArray sa = res.obtainAttributes(parser,
+                            R.styleable.AndroidManifestUpgradeKeySet);
+                    try {
+                        String name = sa.getNonResourceString(
+                                R.styleable.AndroidManifestUpgradeKeySet_name);
+                        upgradeKeySets.add(name);
+                        XmlUtils.skipCurrentTag(parser);
+                    } finally {
+                        sa.recycle();
+                    }
+                } break;
+                default:
+                    ParseResult result = ParsingUtils.unknownTag("<key-sets>", pkg, parser,
+                            input);
+                    if (result.isError()) {
+                        return input.error(result);
+                    }
+                    break;
+            }
+        }
+        String packageName = pkg.getPackageName();
+        Set<String> publicKeyNames = publicKeys.keySet();
+        if (publicKeyNames.removeAll(definedKeySets.keySet())) {
+            return input.error("Package" + packageName
+                    + " AndroidManifest.xml 'key-set' and 'public-key' names must be distinct.");
+        }
+
+        for (ArrayMap.Entry<String, ArraySet<String>> e : definedKeySets.entrySet()) {
+            final String keySetName = e.getKey();
+            if (e.getValue().size() == 0) {
+                Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml "
+                        + "'key-set' " + keySetName + " has no valid associated 'public-key'."
+                        + " Not including in package's defined key-sets.");
+                continue;
+            } else if (improperKeySets.contains(keySetName)) {
+                Slog.w(TAG, "Package" + packageName + " AndroidManifest.xml "
+                        + "'key-set' " + keySetName + " contained improper 'public-key'"
+                        + " tags. Not including in package's defined key-sets.");
+                continue;
+            }
+
+            for (String s : e.getValue()) {
+                pkg.addKeySet(keySetName, publicKeys.get(s));
+            }
+        }
+        if (pkg.getKeySetMapping().keySet().containsAll(upgradeKeySets)) {
+            pkg.setUpgradeKeySets(upgradeKeySets);
+        } else {
+            return input.error("Package" + packageName
+                    + " AndroidManifest.xml does not define all 'upgrade-key-set's .");
+        }
+
+        return input.success(pkg);
+    }
+
+    private static ParseResult<ParsingPackage> parseFeature(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
+        ParseResult<ParsedFeature> result = ParsedFeatureUtils.parseFeature(res, parser, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        return input.success(pkg.addFeature(result.getResult()));
+    }
+
+    private static ParseResult<ParsingPackage> parsePermissionGroup(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        ParseResult<ParsedPermissionGroup> result = ParsedPermissionUtils.parsePermissionGroup(
+                pkg, res, parser, PackageParser.sUseRoundIcon, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        return input.success(pkg.addPermissionGroup(result.getResult()));
+    }
+
+    private static ParseResult<ParsingPackage> parsePermission(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        ParseResult<ParsedPermission> result = ParsedPermissionUtils.parsePermission(
+                pkg, res, parser, PackageParser.sUseRoundIcon, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        return input.success(pkg.addPermission(result.getResult()));
+    }
+
+    private static ParseResult<ParsingPackage> parsePermissionTree(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        ParseResult<ParsedPermission> result = ParsedPermissionUtils.parsePermissionTree(
+                pkg, res, parser, PackageParser.sUseRoundIcon, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        return input.success(pkg.addPermission(result.getResult()));
+    }
+
+    private ParseResult<ParsingPackage> parseUsesPermission(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesPermission);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            String name = sa.getNonResourceString(
+                    R.styleable.AndroidManifestUsesPermission_name);
+
+            int maxSdkVersion = 0;
+            TypedValue val = sa.peekValue(
+                    R.styleable.AndroidManifestUsesPermission_maxSdkVersion);
+            if (val != null) {
+                if (val.type >= TypedValue.TYPE_FIRST_INT && val.type <= TypedValue.TYPE_LAST_INT) {
+                    maxSdkVersion = val.data;
+                }
+            }
+
+            final String requiredFeature = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestUsesPermission_requiredFeature, 0);
+
+            final String requiredNotfeature = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestUsesPermission_requiredNotFeature,
+                    0);
+
+            XmlUtils.skipCurrentTag(parser);
+
+            // Can only succeed from here on out
+            ParseResult<ParsingPackage> success = input.success(pkg);
+
+            if (name == null) {
+                return success;
+            }
+
+            if ((maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT)) {
+                return success;
+            }
+
+            // Only allow requesting this permission if the platform supports the given feature.
+            if (requiredFeature != null && mCallback != null && !mCallback.hasFeature(
+                    requiredFeature)) {
+                return success;
+            }
+
+            // Only allow requesting this permission if the platform doesn't support the given
+            // feature.
+            if (requiredNotfeature != null && mCallback != null
+                    && mCallback.hasFeature(requiredNotfeature)) {
+                return success;
+            }
+
+            if (!pkg.getRequestedPermissions().contains(name)) {
+                pkg.addRequestedPermission(name.intern());
+            } else {
+                Slog.w(TAG, "Ignoring duplicate uses-permissions/uses-permissions-sdk-m: "
+                        + name + " in package: " + pkg.getPackageName() + " at: "
+                        + parser.getPositionDescription());
+            }
+
+            return success;
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseUsesConfiguration(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        ConfigurationInfo cPref = new ConfigurationInfo();
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesConfiguration);
+        try {
+            cPref.reqTouchScreen = sa.getInt(
+                    R.styleable.AndroidManifestUsesConfiguration_reqTouchScreen,
+                    Configuration.TOUCHSCREEN_UNDEFINED);
+            cPref.reqKeyboardType = sa.getInt(
+                    R.styleable.AndroidManifestUsesConfiguration_reqKeyboardType,
+                    Configuration.KEYBOARD_UNDEFINED);
+            if (sa.getBoolean(
+                    R.styleable.AndroidManifestUsesConfiguration_reqHardKeyboard,
+                    false)) {
+                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_HARD_KEYBOARD;
+            }
+            cPref.reqNavigation = sa.getInt(
+                    R.styleable.AndroidManifestUsesConfiguration_reqNavigation,
+                    Configuration.NAVIGATION_UNDEFINED);
+            if (sa.getBoolean(
+                    R.styleable.AndroidManifestUsesConfiguration_reqFiveWayNav,
+                    false)) {
+                cPref.reqInputFeatures |= ConfigurationInfo.INPUT_FEATURE_FIVE_WAY_NAV;
+            }
+            pkg.addConfigPreference(cPref);
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseUsesFeature(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        FeatureInfo fi = parseFeatureInfo(res, parser);
+        pkg.addReqFeature(fi);
+
+        if (fi.name == null) {
+            ConfigurationInfo cPref = new ConfigurationInfo();
+            cPref.reqGlEsVersion = fi.reqGlEsVersion;
+            pkg.addConfigPreference(cPref);
+        }
+
+        return input.success(pkg);
+    }
+
+    private static FeatureInfo parseFeatureInfo(Resources res, AttributeSet attrs) {
+        FeatureInfo fi = new FeatureInfo();
+        TypedArray sa = res.obtainAttributes(attrs, R.styleable.AndroidManifestUsesFeature);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            fi.name = sa.getNonResourceString(R.styleable.AndroidManifestUsesFeature_name);
+            fi.version = sa.getInt(R.styleable.AndroidManifestUsesFeature_version, 0);
+            if (fi.name == null) {
+                fi.reqGlEsVersion = sa.getInt(R.styleable.AndroidManifestUsesFeature_glEsVersion,
+                        FeatureInfo.GL_ES_VERSION_UNDEFINED);
+            }
+            if (sa.getBoolean(R.styleable.AndroidManifestUsesFeature_required, true)) {
+                fi.flags |= FeatureInfo.FLAG_REQUIRED;
+            }
+            return fi;
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseFeatureGroup(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        FeatureGroupInfo group = new FeatureGroupInfo();
+        ArrayList<FeatureInfo> features = null;
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final String innerTagName = parser.getName();
+            if (innerTagName.equals("uses-feature")) {
+                FeatureInfo featureInfo = parseFeatureInfo(res, parser);
+                // FeatureGroups are stricter and mandate that
+                // any <uses-feature> declared are mandatory.
+                featureInfo.flags |= FeatureInfo.FLAG_REQUIRED;
+                features = ArrayUtils.add(features, featureInfo);
+            } else {
+                Slog.w(TAG,
+                        "Unknown element under <feature-group>: " + innerTagName +
+                                " at " + pkg.getBaseCodePath() + " " +
+                                parser.getPositionDescription());
+            }
+        }
+
+        if (features != null) {
+            group.features = new FeatureInfo[features.size()];
+            group.features = features.toArray(group.features);
+        }
+
+        pkg.addFeatureGroup(group);
+        return input.success(pkg);
+    }
+
+    private static ParseResult<ParsingPackage> parseUsesSdk(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws IOException, XmlPullParserException {
+        if (PackageParser.SDK_VERSION > 0) {
+            TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesSdk);
+            try {
+                int minVers = 1;
+                String minCode = null;
+                int targetVers = 0;
+                String targetCode = null;
+
+                TypedValue val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_minSdkVersion);
+                if (val != null) {
+                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+                        minCode = val.string.toString();
+                    } else {
+                        // If it's not a string, it's an integer.
+                        minVers = val.data;
+                    }
+                }
+
+                val = sa.peekValue(R.styleable.AndroidManifestUsesSdk_targetSdkVersion);
+                if (val != null) {
+                    if (val.type == TypedValue.TYPE_STRING && val.string != null) {
+                        targetCode = val.string.toString();
+                        if (minCode == null) {
+                            minCode = targetCode;
+                        }
+                    } else {
+                        // If it's not a string, it's an integer.
+                        targetVers = val.data;
+                    }
+                } else {
+                    targetVers = minVers;
+                    targetCode = minCode;
+                }
+
+                ParseResult<Integer> minSdkVersionResult = computeMinSdkVersion(minVers, minCode,
+                        PackageParser.SDK_VERSION, PackageParser.SDK_CODENAMES, input);
+                if (minSdkVersionResult.isError()) {
+                    return input.error(minSdkVersionResult);
+                }
+
+                int minSdkVersion = minSdkVersionResult.getResult();
+
+                ParseResult<Integer> targetSdkVersionResult = computeTargetSdkVersion(
+                        targetVers, targetCode, PackageParser.SDK_CODENAMES, input);
+                if (targetSdkVersionResult.isError()) {
+                    return input.error(targetSdkVersionResult);
+                }
+
+                int targetSdkVersion = minSdkVersionResult.getResult();
+
+                pkg.setMinSdkVersion(minSdkVersion)
+                        .setTargetSdkVersion(targetSdkVersion);
+
+                int type;
+                final int innerDepth = parser.getDepth();
+                while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                        && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+                    if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                        continue;
+                    }
+
+                    final ParseResult result;
+                    if (parser.getName().equals("extension-sdk")) {
+                        result = parseExtensionSdk(input, pkg, res, parser);
+                        XmlUtils.skipCurrentTag(parser);
+                    } else {
+                        result = ParsingUtils.unknownTag("<uses-sdk>", pkg, parser, input);
+                    }
+
+                    if (result.isError()) {
+                        return input.error(result);
+                    }
+                }
+            } finally {
+                sa.recycle();
+            }
+        }
+        return input.success(pkg);
+    }
+
+    private static ParseResult parseExtensionSdk(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser) {
+        int sdkVersion;
+        int minVersion;
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestExtensionSdk);
+        try {
+            sdkVersion = sa.getInt(R.styleable.AndroidManifestExtensionSdk_sdkVersion, -1);
+            minVersion = sa.getInt(R.styleable.AndroidManifestExtensionSdk_minExtensionVersion, -1);
+        } finally {
+            sa.recycle();
+        }
+
+        if (sdkVersion < 0) {
+            return input.error(
+                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                    "<extension-sdk> must specify an sdkVersion >= 0");
+        }
+        if (minVersion < 0) {
+            return input.error(
+                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                    "<extension-sdk> must specify minExtensionVersion >= 0");
+        }
+
+        try {
+            int version = SdkExtensions.getExtensionVersion(sdkVersion);
+            if (version < minVersion) {
+                return input.error(
+                        PackageManager.INSTALL_FAILED_OLDER_SDK,
+                        "Package requires " + sdkVersion + " extension version " + minVersion
+                                + " which exceeds device version " + version);
+            }
+        } catch (RuntimeException e) {
+            return input.error(
+                    PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                    "Specified sdkVersion " + sdkVersion + " is not valid");
+        }
+        return input.success(pkg);
+    }
+
+    /**
+     * {@link ParseResult} version of
+     * {@link PackageParser#computeMinSdkVersion(int, String, int, String[], String[])}
+     */
+    public static ParseResult<Integer> computeMinSdkVersion(@IntRange(from = 1) int minVers,
+            @Nullable String minCode, @IntRange(from = 1) int platformSdkVersion,
+            @NonNull String[] platformSdkCodenames, @NonNull ParseInput input) {
+        // If it's a release SDK, make sure we meet the minimum SDK requirement.
+        if (minCode == null) {
+            if (minVers <= platformSdkVersion) {
+                return input.success(minVers);
+            }
+
+            // We don't meet the minimum SDK requirement.
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+                    "Requires newer sdk version #" + minVers
+                            + " (current version is #" + platformSdkVersion + ")");
+        }
+
+        // If it's a pre-release SDK and the codename matches this platform, we
+        // definitely meet the minimum SDK requirement.
+        if (matchTargetCode(platformSdkCodenames, minCode)) {
+            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        }
+
+        // Otherwise, we're looking at an incompatible pre-release SDK.
+        if (platformSdkCodenames.length > 0) {
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+                    "Requires development platform " + minCode
+                            + " (current platform is any of "
+                            + Arrays.toString(platformSdkCodenames) + ")");
+        } else {
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+                    "Requires development platform " + minCode
+                            + " but this is a release platform.");
+        }
+    }
+
+    /**
+     * {@link ParseResult} version of
+     * {@link PackageParser#computeTargetSdkVersion(int, String, String[], String[])}
+     */
+    public static ParseResult<Integer> computeTargetSdkVersion(@IntRange(from = 0) int targetVers,
+            @Nullable String targetCode, @NonNull String[] platformSdkCodenames,
+            @NonNull ParseInput input) {
+        // If it's a release SDK, return the version number unmodified.
+        if (targetCode == null) {
+            return input.success(targetVers);
+        }
+
+        // If it's a pre-release SDK and the codename matches this platform, it
+        // definitely targets this SDK.
+        if (matchTargetCode(platformSdkCodenames, targetCode)) {
+            return input.success(Build.VERSION_CODES.CUR_DEVELOPMENT);
+        }
+
+        // Otherwise, we're looking at an incompatible pre-release SDK.
+        if (platformSdkCodenames.length > 0) {
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+                    "Requires development platform " + targetCode
+                            + " (current platform is any of "
+                            + Arrays.toString(platformSdkCodenames) + ")");
+        } else {
+            return input.error(PackageManager.INSTALL_FAILED_OLDER_SDK,
+                    "Requires development platform " + targetCode
+                            + " but this is a release platform.");
+        }
+    }
+
+    /**
+     * Matches a given {@code targetCode} against a set of release codeNames. Target codes can
+     * either be of the form {@code [codename]}" (e.g {@code "Q"}) or of the form
+     * {@code [codename].[fingerprint]} (e.g {@code "Q.cafebc561"}).
+     */
+    private static boolean matchTargetCode(@NonNull String[] codeNames,
+            @NonNull String targetCode) {
+        final String targetCodeName;
+        final int targetCodeIdx = targetCode.indexOf('.');
+        if (targetCodeIdx == -1) {
+            targetCodeName = targetCode;
+        } else {
+            targetCodeName = targetCode.substring(0, targetCodeIdx);
+        }
+        return ArrayUtils.contains(codeNames, targetCodeName);
+    }
+
+    private static ParseResult<ParsingPackage> parseRestrictUpdateHash(int flags, ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        if ((flags & PackageParser.PARSE_IS_SYSTEM_DIR) != 0) {
+            TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestRestrictUpdate);
+            try {
+                final String hash = sa.getNonConfigurationString(
+                        R.styleable.AndroidManifestRestrictUpdate_hash,
+                        0);
+
+                if (hash != null) {
+                    final int hashLength = hash.length();
+                    final byte[] hashBytes = new byte[hashLength / 2];
+                    for (int i = 0; i < hashLength; i += 2) {
+                        hashBytes[i / 2] = (byte) ((Character.digit(hash.charAt(i), 16)
+                                << 4)
+                                + Character.digit(hash.charAt(i + 1), 16));
+                    }
+                    pkg.setRestrictUpdateHash(hashBytes);
+                } else {
+                    pkg.setRestrictUpdateHash(null);
+                }
+            } finally {
+                sa.recycle();
+            }
+        }
+        return input.success(pkg);
+    }
+
+    private static ParseResult<ParsingPackage> parseQueries(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser) throws IOException, XmlPullParserException {
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            if (parser.getName().equals("intent")) {
+                ParseResult<ParsedIntentInfo> result = ParsedIntentInfoUtils.parseIntentInfo(null,
+                        pkg, res, parser, true /*allowGlobs*/, true /*allowAutoVerify*/, input);
+                if (result.isError()) {
+                    return input.error(result);
+                }
+
+                ParsedIntentInfo intentInfo = result.getResult();
+
+                Uri data = null;
+                String dataType = null;
+                String host = "";
+                final int numActions = intentInfo.countActions();
+                final int numSchemes = intentInfo.countDataSchemes();
+                final int numTypes = intentInfo.countDataTypes();
+                final int numHosts = intentInfo.getHosts().length;
+                if ((numSchemes == 0 && numTypes == 0 && numActions == 0)) {
+                    return input.error("intent tags must contain either an action or data.");
+                }
+                if (numActions > 1) {
+                    return input.error("intent tag may have at most one action.");
+                }
+                if (numTypes > 1) {
+                    return input.error("intent tag may have at most one data type.");
+                }
+                if (numSchemes > 1) {
+                    return input.error("intent tag may have at most one data scheme.");
+                }
+                if (numHosts > 1) {
+                    return input.error("intent tag may have at most one data host.");
+                }
+                Intent intent = new Intent();
+                for (int i = 0, max = intentInfo.countCategories(); i < max; i++) {
+                    intent.addCategory(intentInfo.getCategory(i));
+                }
+                if (numHosts == 1) {
+                    host = intentInfo.getHosts()[0];
+                }
+                if (numSchemes == 1) {
+                    data = new Uri.Builder()
+                            .scheme(intentInfo.getDataScheme(0))
+                            .authority(host)
+                            .build();
+                }
+                if (numTypes == 1) {
+                    dataType = intentInfo.getDataType(0);
+                }
+                intent.setDataAndType(data, dataType);
+                if (numActions == 1) {
+                    intent.setAction(intentInfo.getAction(0));
+                }
+                pkg.addQueriesIntent(intent);
+            } else if (parser.getName().equals("package")) {
+                final TypedArray sa = res.obtainAttributes(parser,
+                        R.styleable.AndroidManifestQueriesPackage);
+                final String packageName = sa.getString(
+                        R.styleable.AndroidManifestQueriesPackage_name);
+                if (TextUtils.isEmpty(packageName)) {
+                    return input.error("Package name is missing from package tag.");
+                }
+                pkg.addQueriesPackage(packageName.intern());
+            } else if (parser.getName().equals("provider")) {
+                final TypedArray sa = res.obtainAttributes(parser,
+                        R.styleable.AndroidManifestQueriesProvider);
+                try {
+                    final String authorities =
+                            sa.getString(R.styleable.AndroidManifestQueriesProvider_authorities);
+                    if (TextUtils.isEmpty(authorities)) {
+                        return input.error(
+                                PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED,
+                                "Authority missing from provider tag."
+                        );
+                    }
+                    StringTokenizer authoritiesTokenizer = new StringTokenizer(authorities, ";");
+                    while (authoritiesTokenizer.hasMoreElements()) {
+                        pkg.addQueriesProvider(authoritiesTokenizer.nextToken());
+                    }
+                } finally {
+                    sa.recycle();
+                }
+            }
+        }
+        return input.success(pkg);
+    }
+
+    /**
+     * Parse the {@code application} XML tree at the current parse location in a
+     * <em>base APK</em> manifest.
+     * <p>
+     * When adding new features, carefully consider if they should also be
+     * supported by split APKs.
+     *
+     * This method should avoid using a getter for fields set by this method. Prefer assigning
+     * a local variable and using it. Otherwise there's an ordering problem which can be broken
+     * if any code moves around.
+     */
+    private ParseResult<ParsingPackage> parseBaseApplication(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags)
+            throws XmlPullParserException, IOException {
+        final String pkgName = pkg.getPackageName();
+        int targetSdk = pkg.getTargetSdkVersion();
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestApplication);
+        try {
+            // TODO(b/135203078): Remove this and force unit tests to mock an empty manifest
+            // This case can only happen in unit tests where we sometimes need to create fakes
+            // of various package parser data structures.
+            if (sa == null) {
+                return input.error("<application> does not contain any attributes");
+            }
+
+            String name = sa.getNonConfigurationString(R.styleable.AndroidManifestApplication_name,
+                    0);
+            if (name != null) {
+                String packageName = pkg.getPackageName();
+                String outInfoName = ParsingUtils.buildClassName(packageName, name);
+                if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(outInfoName)) {
+                    return input.error("<application> invalid android:name");
+                } else if (outInfoName == null) {
+                    return input.error("Empty class name in package " + packageName);
+                }
+
+                pkg.setClassName(outInfoName);
+            }
+
+            TypedValue labelValue = sa.peekValue(R.styleable.AndroidManifestApplication_label);
+            if (labelValue != null) {
+                pkg.setLabelRes(labelValue.resourceId);
+                if (labelValue.resourceId == 0) {
+                    pkg.setNonLocalizedLabel(labelValue.coerceToString());
+                }
+            }
+
+            parseBaseAppBasicFlags(pkg, sa);
+
+            String manageSpaceActivity = nonConfigString(Configuration.NATIVE_CONFIG_VERSION,
+                    R.styleable.AndroidManifestApplication_manageSpaceActivity, sa);
+            if (manageSpaceActivity != null) {
+                String manageSpaceActivityName = ParsingUtils.buildClassName(pkgName,
+                        manageSpaceActivity);
+
+                if (manageSpaceActivityName == null) {
+                    return input.error("Empty class name in package " + pkgName);
+                }
+
+                pkg.setManageSpaceActivityName(manageSpaceActivityName);
+            }
+
+            if (pkg.isAllowBackup()) {
+                // backupAgent, killAfterRestore, fullBackupContent, backupInForeground,
+                // and restoreAnyVersion are only relevant if backup is possible for the
+                // given application.
+                String backupAgent = nonConfigString(Configuration.NATIVE_CONFIG_VERSION,
+                        R.styleable.AndroidManifestApplication_backupAgent, sa);
+                if (backupAgent != null) {
+                    String backupAgentName = ParsingUtils.buildClassName(pkgName, backupAgent);
+                    if (backupAgentName == null) {
+                        return input.error("Empty class name in package " + pkgName);
+                    }
+
+                    if (PackageParser.DEBUG_BACKUP) {
+                        Slog.v(TAG, "android:backupAgent = " + backupAgentName
+                                + " from " + pkgName + "+" + backupAgent);
+                    }
+
+                    pkg.setBackupAgentName(backupAgentName)
+                            .setKillAfterRestore(bool(true,
+                                    R.styleable.AndroidManifestApplication_killAfterRestore, sa))
+                            .setRestoreAnyVersion(bool(false,
+                                    R.styleable.AndroidManifestApplication_restoreAnyVersion, sa))
+                            .setFullBackupOnly(bool(false,
+                                    R.styleable.AndroidManifestApplication_fullBackupOnly, sa))
+                            .setBackupInForeground(bool(false,
+                                    R.styleable.AndroidManifestApplication_backupInForeground, sa));
+                }
+
+                TypedValue v = sa.peekValue(
+                        R.styleable.AndroidManifestApplication_fullBackupContent);
+                int fullBackupContent = 0;
+
+                if (v != null) {
+                    fullBackupContent = v.resourceId;
+
+                    if (v.resourceId == 0) {
+                        if (PackageParser.DEBUG_BACKUP) {
+                            Slog.v(TAG, "fullBackupContent specified as boolean=" +
+                                    (v.data == 0 ? "false" : "true"));
+                        }
+                        // "false" => -1, "true" => 0
+                        fullBackupContent = v.data == 0 ? -1 : 0;
+                    }
+
+                    pkg.setFullBackupContent(fullBackupContent);
+                }
+                if (PackageParser.DEBUG_BACKUP) {
+                    Slog.v(TAG, "fullBackupContent=" + fullBackupContent + " for " + pkgName);
+                }
+            }
+
+            if (sa.getBoolean(R.styleable.AndroidManifestApplication_persistent, false)) {
+                // Check if persistence is based on a feature being present
+                final String requiredFeature = sa.getNonResourceString(R.styleable
+                        .AndroidManifestApplication_persistentWhenFeatureAvailable);
+                pkg.setPersistent(requiredFeature == null || mCallback.hasFeature(requiredFeature));
+            }
+
+            // TODO(b/135203078): Should parsing code be responsible for this? Maybe move to a
+            //  util or just have PackageImpl return true if either flag is set
+            // Debuggable implies profileable
+            pkg.setProfileableByShell(pkg.isProfileableByShell() || pkg.isDebuggable());
+
+            if (sa.hasValueOrEmpty(R.styleable.AndroidManifestApplication_resizeableActivity)) {
+                pkg.setResizeableActivity(sa.getBoolean(
+                        R.styleable.AndroidManifestApplication_resizeableActivity, true));
+            } else {
+                pkg.setResizeableActivityViaSdkVersion(
+                        targetSdk >= Build.VERSION_CODES.N);
+            }
+
+            String taskAffinity;
+            if (targetSdk >= Build.VERSION_CODES.FROYO) {
+                taskAffinity = sa.getNonConfigurationString(
+                        R.styleable.AndroidManifestApplication_taskAffinity,
+                        Configuration.NATIVE_CONFIG_VERSION);
+            } else {
+                // Some older apps have been seen to use a resource reference
+                // here that on older builds was ignored (with a warning).  We
+                // need to continue to do this for them so they don't break.
+                taskAffinity = sa.getNonResourceString(
+                        R.styleable.AndroidManifestApplication_taskAffinity);
+            }
+
+            ParseResult<String> taskAffinityResult = ComponentParseUtils.buildTaskAffinityName(
+                    pkgName, pkgName, taskAffinity, input);
+            if (taskAffinityResult.isError()) {
+                return input.error(taskAffinityResult);
+            }
+
+            pkg.setTaskAffinity(taskAffinityResult.getResult());
+            String factory = sa.getNonResourceString(
+                    R.styleable.AndroidManifestApplication_appComponentFactory);
+            if (factory != null) {
+                String appComponentFactory = ParsingUtils.buildClassName(pkgName, factory);
+                if (appComponentFactory == null) {
+                    return input.error("Empty class name in package " + pkgName);
+                }
+
+                pkg.setAppComponentFactory(appComponentFactory);
+            }
+
+            CharSequence pname;
+            if (targetSdk >= Build.VERSION_CODES.FROYO) {
+                pname = sa.getNonConfigurationString(
+                        R.styleable.AndroidManifestApplication_process,
+                        Configuration.NATIVE_CONFIG_VERSION);
+            } else {
+                // Some older apps have been seen to use a resource reference
+                // here that on older builds was ignored (with a warning).  We
+                // need to continue to do this for them so they don't break.
+                pname = sa.getNonResourceString(
+                        R.styleable.AndroidManifestApplication_process);
+            }
+            ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName(
+                    pkgName, null, pname, flags, mSeparateProcesses, input);
+            if (processNameResult.isError()) {
+                return input.error(processNameResult);
+            }
+
+            String processName = processNameResult.getResult();
+            pkg.setProcessName(processName);
+
+            if (pkg.isCantSaveState()) {
+                // A heavy-weight application can not be in a custom process.
+                // We can do direct compare because we intern all strings.
+                if (processName != null && !processName.equals(pkgName)) {
+                    return input.error(
+                            "cantSaveState applications can not use custom processes");
+                }
+            }
+
+            String classLoaderName = pkg.getClassLoaderName();
+            if (classLoaderName != null
+                    && !ClassLoaderFactory.isValidClassLoaderName(classLoaderName)) {
+                return input.error("Invalid class loader name: " + classLoaderName);
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        boolean hasActivityOrder = false;
+        boolean hasReceiverOrder = false;
+        boolean hasServiceOrder = false;
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult result;
+            String tagName = parser.getName();
+            boolean isActivity = false;
+            switch (tagName) {
+                case "activity":
+                    isActivity = true;
+                    // fall-through
+                case "receiver":
+                    ParseResult<ParsedActivity> activityResult =
+                            ParsedActivityUtils.parseActivityOrReceiver(mSeparateProcesses, pkg,
+                                    res, parser, flags, PackageParser.sUseRoundIcon, input);
+
+                    if (activityResult.isSuccess()) {
+                        ParsedActivity activity = activityResult.getResult();
+                        if (isActivity) {
+                            hasActivityOrder |= (activity.getOrder() != 0);
+                            pkg.addActivity(activity);
+                        } else {
+                            hasReceiverOrder |= (activity.getOrder() != 0);
+                            pkg.addReceiver(activity);
+                        }
+                    }
+
+                    result = activityResult;
+                    break;
+                case "service":
+                    ParseResult<ParsedService> serviceResult =
+                            ParsedServiceUtils.parseService(mSeparateProcesses, pkg, res, parser,
+                                    flags, PackageParser.sUseRoundIcon, input);
+                    if (serviceResult.isSuccess()) {
+                        ParsedService service = serviceResult.getResult();
+                        hasServiceOrder |= (service.getOrder() != 0);
+                        pkg.addService(service);
+                    }
+
+                    result = serviceResult;
+                    break;
+                case "provider":
+                    ParseResult<ParsedProvider> providerResult =
+                            ParsedProviderUtils.parseProvider(mSeparateProcesses, pkg, res, parser,
+                                    flags, PackageParser.sUseRoundIcon, input);
+                    if (providerResult.isSuccess()) {
+                        pkg.addProvider(providerResult.getResult());
+                    }
+
+                    result = providerResult;
+                    break;
+                case "activity-alias":
+                    activityResult = ParsedActivityUtils.parseActivityAlias(pkg, res,
+                            parser, PackageParser.sUseRoundIcon, input);
+                    if (activityResult.isSuccess()) {
+                        ParsedActivity activity = activityResult.getResult();
+                        hasActivityOrder |= (activity.getOrder() != 0);
+                        pkg.addActivity(activity);
+                    }
+
+                    result = activityResult;
+                    break;
+                default:
+                    result = parseBaseAppChildTag(input, tagName, pkg, res, parser, flags);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        if (TextUtils.isEmpty(pkg.getStaticSharedLibName())) {
+            // Add a hidden app detail activity to normal apps which forwards user to App Details
+            // page.
+            ParseResult<ParsedActivity> a = generateAppDetailsHiddenActivity(input, pkg);
+            // Backwards-compat, assume success
+            pkg.addActivity(a.getResult());
+            a.ignoreError();
+        }
+
+        if (hasActivityOrder) {
+            pkg.sortActivities();
+        }
+        if (hasReceiverOrder) {
+            pkg.sortReceivers();
+        }
+        if (hasServiceOrder) {
+            pkg.sortServices();
+        }
+
+        // Must be run after the entire {@link ApplicationInfo} has been fully processed and after
+        // every activity info has had a chance to set it from its attributes.
+        setMaxAspectRatio(pkg);
+        setMinAspectRatio(pkg);
+
+        pkg.setHasDomainUrls(hasDomainURLs(pkg));
+
+        return input.success(pkg);
+    }
+
+    /**
+     * Collection of single-line, no (or little) logic assignments. Separated for readability.
+     *
+     * Flags are separated by type and by default value. They are sorted alphabetically within each
+     * section.
+     */
+    private void parseBaseAppBasicFlags(ParsingPackage pkg, TypedArray sa) {
+        int targetSdk = pkg.getTargetSdkVersion();
+        //@formatter:off
+        // CHECKSTYLE:off
+        pkg
+                // Default true
+                .setAllowBackup(bool(true, R.styleable.AndroidManifestApplication_allowBackup, sa))
+                .setAllowClearUserData(bool(true, R.styleable.AndroidManifestApplication_allowClearUserData, sa))
+                .setAllowClearUserDataOnFailedRestore(bool(true, R.styleable.AndroidManifestApplication_allowClearUserDataOnFailedRestore, sa))
+                .setAllowNativeHeapPointerTagging(bool(true, R.styleable.AndroidManifestApplication_allowNativeHeapPointerTagging, sa))
+                .setEnabled(bool(true, R.styleable.AndroidManifestApplication_enabled, sa))
+                .setExtractNativeLibs(bool(true, R.styleable.AndroidManifestApplication_extractNativeLibs, sa))
+                .setHasCode(bool(true, R.styleable.AndroidManifestApplication_hasCode, sa))
+                // Default false
+                .setAllowTaskReparenting(bool(false, R.styleable.AndroidManifestApplication_allowTaskReparenting, sa))
+                .setCantSaveState(bool(false, R.styleable.AndroidManifestApplication_cantSaveState, sa))
+                .setDebuggable(bool(false, R.styleable.AndroidManifestApplication_debuggable, sa))
+                .setDefaultToDeviceProtectedStorage(bool(false, R.styleable.AndroidManifestApplication_defaultToDeviceProtectedStorage, sa))
+                .setDirectBootAware(bool(false, R.styleable.AndroidManifestApplication_directBootAware, sa))
+                .setForceQueryable(bool(false, R.styleable.AndroidManifestApplication_forceQueryable, sa))
+                .setGame(bool(false, R.styleable.AndroidManifestApplication_isGame, sa))
+                .setHasFragileUserData(bool(false, R.styleable.AndroidManifestApplication_hasFragileUserData, sa))
+                .setLargeHeap(bool(false, R.styleable.AndroidManifestApplication_largeHeap, sa))
+                .setMultiArch(bool(false, R.styleable.AndroidManifestApplication_multiArch, sa))
+                .setPreserveLegacyExternalStorage(bool(false, R.styleable.AndroidManifestApplication_preserveLegacyExternalStorage, sa))
+                .setRequiredForAllUsers(bool(false, R.styleable.AndroidManifestApplication_requiredForAllUsers, sa))
+                .setSupportsRtl(bool(false, R.styleable.AndroidManifestApplication_supportsRtl, sa))
+                .setTestOnly(bool(false, R.styleable.AndroidManifestApplication_testOnly, sa))
+                .setUseEmbeddedDex(bool(false, R.styleable.AndroidManifestApplication_useEmbeddedDex, sa))
+                .setUsesNonSdkApi(bool(false, R.styleable.AndroidManifestApplication_usesNonSdkApi, sa))
+                .setVmSafeMode(bool(false, R.styleable.AndroidManifestApplication_vmSafeMode, sa))
+                // targetSdkVersion gated
+                .setAllowAudioPlaybackCapture(bool(targetSdk >= Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_allowAudioPlaybackCapture, sa))
+                .setBaseHardwareAccelerated(bool(targetSdk >= Build.VERSION_CODES.ICE_CREAM_SANDWICH, R.styleable.AndroidManifestApplication_hardwareAccelerated, sa))
+                .setRequestLegacyExternalStorage(bool(targetSdk < Build.VERSION_CODES.Q, R.styleable.AndroidManifestApplication_requestLegacyExternalStorage, sa))
+                .setUsesCleartextTraffic(bool(targetSdk < Build.VERSION_CODES.P, R.styleable.AndroidManifestApplication_usesCleartextTraffic, sa))
+                // Ints Default 0
+                .setUiOptions(anInt(R.styleable.AndroidManifestApplication_uiOptions, sa))
+                // Ints
+                .setCategory(anInt(ApplicationInfo.CATEGORY_UNDEFINED, R.styleable.AndroidManifestApplication_appCategory, sa))
+                // Floats Default 0f
+                .setMaxAspectRatio(aFloat(R.styleable.AndroidManifestApplication_maxAspectRatio, sa))
+                .setMinAspectRatio(aFloat(R.styleable.AndroidManifestApplication_minAspectRatio, sa))
+                // Resource ID
+                .setBanner(resId(R.styleable.AndroidManifestApplication_banner, sa))
+                .setDescriptionRes(resId(R.styleable.AndroidManifestApplication_description, sa))
+                .setIconRes(resId(R.styleable.AndroidManifestApplication_icon, sa))
+                .setLogo(resId(R.styleable.AndroidManifestApplication_logo, sa))
+                .setNetworkSecurityConfigRes(resId(R.styleable.AndroidManifestApplication_networkSecurityConfig, sa))
+                .setRoundIconRes(resId(R.styleable.AndroidManifestApplication_roundIcon, sa))
+                .setTheme(resId(R.styleable.AndroidManifestApplication_theme, sa))
+                // Strings
+                .setClassLoaderName(string(R.styleable.AndroidManifestApplication_classLoader, sa))
+                .setRequiredAccountType(string(R.styleable.AndroidManifestApplication_requiredAccountType, sa))
+                .setRestrictedAccountType(string(R.styleable.AndroidManifestApplication_restrictedAccountType, sa))
+                .setZygotePreloadName(string(R.styleable.AndroidManifestApplication_zygotePreloadName, sa))
+                // Non-Config String
+                .setPermission(nonConfigString(0, R.styleable.AndroidManifestApplication_permission, sa));
+        // CHECKSTYLE:on
+        //@formatter:on
+    }
+
+    /**
+     * For parsing non-MainComponents. Main ones have an order and some special handling which is
+     * done directly in {@link #parseBaseApplication(ParseInput, ParsingPackage, Resources,
+     * XmlResourceParser, int)}.
+     */
+    private ParseResult parseBaseAppChildTag(ParseInput input, String tag, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser, int flags)
+            throws IOException, XmlPullParserException {
+        switch (tag) {
+            case "meta-data":
+                // TODO(b/135203078): I have no idea what this comment means
+                // note: application meta-data is stored off to the side, so it can
+                // remain null in the primary copy (we like to avoid extra copies because
+                // it can be large)
+                ParseResult<Bundle> metaDataResult = parseMetaData(pkg, res, parser,
+                        pkg.getMetaData(), input);
+                if (metaDataResult.isSuccess()) {
+                    pkg.setMetaData(metaDataResult.getResult());
+                }
+
+                return metaDataResult;
+            case "static-library":
+                return parseStaticLibrary(pkg, res, parser, input);
+            case "library":
+                return parseLibrary(pkg, res, parser, input);
+            case "uses-static-library":
+                return parseUsesStaticLibrary(input, pkg, res, parser);
+            case "uses-library":
+                return parseUsesLibrary(input, pkg, res, parser);
+            case "processes":
+                return parseProcesses(input, pkg, res, parser, mSeparateProcesses, flags);
+            case "uses-package":
+                // Dependencies for app installers; we don't currently try to
+                // enforce this.
+                return input.success(null);
+            case "profileable":
+                return parseProfileable(input, pkg, res, parser);
+            default:
+                return ParsingUtils.unknownTag("<application>", pkg, parser, input);
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseStaticLibrary(
+            ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, ParseInput input) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestStaticLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            String lname = sa.getNonResourceString(
+                    R.styleable.AndroidManifestStaticLibrary_name);
+            final int version = sa.getInt(
+                    R.styleable.AndroidManifestStaticLibrary_version, -1);
+            final int versionMajor = sa.getInt(
+                    R.styleable.AndroidManifestStaticLibrary_versionMajor,
+                    0);
+
+            // Since the app canot run without a static lib - fail if malformed
+            if (lname == null || version < 0) {
+                return input.error("Bad static-library declaration name: " + lname
+                        + " version: " + version);
+            } else if (pkg.getSharedUserId() != null) {
+                return input.error(
+                        PackageManager.INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID,
+                        "sharedUserId not allowed in static shared library"
+                );
+            } else if (pkg.getStaticSharedLibName() != null) {
+                return input.error("Multiple static-shared libs for package "
+                        + pkg.getPackageName());
+            }
+
+            return input.success(pkg.setStaticSharedLibName(lname.intern())
+                    .setStaticSharedLibVersion(
+                            PackageInfo.composeLongVersionCode(versionMajor, version))
+                    .setStaticSharedLibrary(true));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseLibrary(
+            ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, ParseInput input) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            String lname = sa.getNonResourceString(R.styleable.AndroidManifestLibrary_name);
+
+            if (lname != null) {
+                lname = lname.intern();
+                if (!ArrayUtils.contains(pkg.getLibraryNames(), lname)) {
+                    pkg.addLibraryName(lname);
+                }
+            }
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseUsesStaticLibrary(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesStaticLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource that may change.
+            String lname = sa.getNonResourceString(
+                    R.styleable.AndroidManifestUsesLibrary_name);
+            final int version = sa.getInt(
+                    R.styleable.AndroidManifestUsesStaticLibrary_version, -1);
+            String certSha256Digest = sa.getNonResourceString(R.styleable
+                    .AndroidManifestUsesStaticLibrary_certDigest);
+
+            // Since an APK providing a static shared lib can only provide the lib - fail if
+            // malformed
+            if (lname == null || version < 0 || certSha256Digest == null) {
+                return input.error("Bad uses-static-library declaration name: " + lname
+                        + " version: " + version + " certDigest" + certSha256Digest);
+            }
+
+            // Can depend only on one version of the same library
+            List<String> usesStaticLibraries = pkg.getUsesStaticLibraries();
+            if (usesStaticLibraries.contains(lname)) {
+                return input.error(
+                        "Depending on multiple versions of static library " + lname);
+            }
+
+            lname = lname.intern();
+            // We allow ":" delimiters in the SHA declaration as this is the format
+            // emitted by the certtool making it easy for developers to copy/paste.
+            certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
+
+            // Fot apps targeting O-MR1 we require explicit enumeration of all certs.
+            String[] additionalCertSha256Digests = EmptyArray.STRING;
+            if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.O_MR1) {
+                ParseResult<String[]> certResult = parseAdditionalCertificates(input, res, parser);
+                if (certResult.isError()) {
+                    return input.error(certResult);
+                }
+                additionalCertSha256Digests = certResult.getResult();
+            }
+
+            final String[] certSha256Digests = new String[additionalCertSha256Digests.length + 1];
+            certSha256Digests[0] = certSha256Digest;
+            System.arraycopy(additionalCertSha256Digests, 0, certSha256Digests,
+                    1, additionalCertSha256Digests.length);
+
+            return input.success(pkg.addUsesStaticLibrary(lname)
+                    .addUsesStaticLibraryVersion(version)
+                    .addUsesStaticLibraryCertDigests(certSha256Digests));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseUsesLibrary(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestUsesLibrary);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            String lname = sa.getNonResourceString(R.styleable.AndroidManifestUsesLibrary_name);
+            boolean req = sa.getBoolean(R.styleable.AndroidManifestUsesLibrary_required, true);
+
+            if (lname != null) {
+                lname = lname.intern();
+                if (req) {
+                    // Upgrade to treat as stronger constraint
+                    pkg.addUsesLibrary(lname)
+                            .removeUsesOptionalLibrary(lname);
+                } else {
+                    // Ignore if someone already defined as required
+                    if (!ArrayUtils.contains(pkg.getUsesLibraries(), lname)) {
+                        pkg.addUsesOptionalLibrary(lname);
+                    }
+                }
+            }
+
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseProcesses(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser, String[] separateProcesses, int flags)
+            throws IOException, XmlPullParserException {
+        ParseResult<ArrayMap<String, ParsedProcess>> result =
+                ParsedProcessUtils.parseProcesses(separateProcesses, pkg, res, parser, flags,
+                        input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+
+        return input.success(pkg.setProcesses(result.getResult()));
+    }
+
+    @NonNull
+    private static ParseResult<ParsingPackage> parseProfileable(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProfileable);
+        try {
+            return input.success(pkg.setProfileableByShell(pkg.isProfileableByShell()
+                    || bool(false, R.styleable.AndroidManifestProfileable_shell, sa)));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<String[]> parseAdditionalCertificates(ParseInput input,
+            Resources resources, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        String[] certSha256Digests = EmptyArray.STRING;
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final String nodeName = parser.getName();
+            if (nodeName.equals("additional-certificate")) {
+                TypedArray sa = resources.obtainAttributes(parser,
+                        R.styleable.AndroidManifestAdditionalCertificate);
+                try {
+                    String certSha256Digest = sa.getNonResourceString(
+                            R.styleable.AndroidManifestAdditionalCertificate_certDigest);
+
+                    if (TextUtils.isEmpty(certSha256Digest)) {
+                        return input.error("Bad additional-certificate declaration with empty"
+                                + " certDigest:" + certSha256Digest);
+                    }
+
+
+                    // We allow ":" delimiters in the SHA declaration as this is the format
+                    // emitted by the certtool making it easy for developers to copy/paste.
+                    certSha256Digest = certSha256Digest.replace(":", "").toLowerCase();
+                    certSha256Digests = ArrayUtils.appendElement(String.class,
+                            certSha256Digests, certSha256Digest);
+                } finally {
+                    sa.recycle();
+                }
+            }
+        }
+
+        return input.success(certSha256Digests);
+    }
+
+    /**
+     * Generate activity object that forwards user to App Details page automatically.
+     * This activity should be invisible to user and user should not know or see it.
+     */
+    @NonNull
+    private static ParseResult<ParsedActivity> generateAppDetailsHiddenActivity(ParseInput input,
+            ParsingPackage pkg) {
+        String packageName = pkg.getPackageName();
+        ParseResult<String> taskAffinityResult = ComponentParseUtils.buildTaskAffinityName(
+                packageName, packageName, ":app_details", input);
+
+        String taskAffinity;
+        if (taskAffinityResult.isSuccess()) {
+            taskAffinity = taskAffinityResult.getResult();
+        } else {
+            // Backwards-compat, do not fail
+            taskAffinity = null;
+            taskAffinityResult.ignoreError();
+        }
+
+        // Build custom App Details activity info instead of parsing it from xml
+        return input.success(ParsedActivity.makeAppDetailsActivity(packageName,
+                pkg.getProcessName(), pkg.getUiOptions(), taskAffinity,
+                pkg.isBaseHardwareAccelerated()));
+    }
+
+    /**
+     * Check if one of the IntentFilter as both actions DEFAULT / VIEW and a HTTP/HTTPS data URI
+     */
+    private static boolean hasDomainURLs(ParsingPackage pkg) {
+        final List<ParsedActivity> activities = pkg.getActivities();
+        final int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            ParsedActivity activity = activities.get(index);
+            List<ParsedIntentInfo> filters = activity.getIntents();
+            final int filtersSize = filters.size();
+            for (int filtersIndex = 0; filtersIndex < filtersSize; filtersIndex++) {
+                ParsedIntentInfo aii = filters.get(filtersIndex);
+                if (!aii.hasAction(Intent.ACTION_VIEW)) continue;
+                if (!aii.hasAction(Intent.ACTION_DEFAULT)) continue;
+                if (aii.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
+                        aii.hasDataScheme(IntentFilter.SCHEME_HTTPS)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Sets the max aspect ratio of every child activity that doesn't already have an aspect
+     * ratio set.
+     */
+    private static void setMaxAspectRatio(ParsingPackage pkg) {
+        // Default to (1.86) 16.7:9 aspect ratio for pre-O apps and unset for O and greater.
+        // NOTE: 16.7:9 was the max aspect ratio Android devices can support pre-O per the CDD.
+        float maxAspectRatio = pkg.getTargetSdkVersion() < O
+                ? PackageParser.DEFAULT_PRE_O_MAX_ASPECT_RATIO : 0;
+
+        float packageMaxAspectRatio = pkg.getMaxAspectRatio();
+        if (packageMaxAspectRatio != 0) {
+            // Use the application max aspect ration as default if set.
+            maxAspectRatio = packageMaxAspectRatio;
+        } else {
+            Bundle appMetaData = pkg.getMetaData();
+            if (appMetaData != null && appMetaData.containsKey(
+                    PackageParser.METADATA_MAX_ASPECT_RATIO)) {
+                maxAspectRatio = appMetaData.getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
+                        maxAspectRatio);
+            }
+        }
+
+        List<ParsedActivity> activities = pkg.getActivities();
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            ParsedActivity activity = activities.get(index);
+            // If the max aspect ratio for the activity has already been set, skip.
+            if (activity.getMaxAspectRatio() != null) {
+                continue;
+            }
+
+            // By default we prefer to use a values defined on the activity directly than values
+            // defined on the application. We do not check the styled attributes on the activity
+            // as it would have already been set when we processed the activity. We wait to
+            // process the meta data here since this method is called at the end of processing
+            // the application and all meta data is guaranteed.
+            final float activityAspectRatio = activity.getMetaData() != null
+                    ? activity.getMetaData().getFloat(PackageParser.METADATA_MAX_ASPECT_RATIO,
+                    maxAspectRatio)
+                    : maxAspectRatio;
+
+            activity.setMaxAspectRatio(activity.getResizeMode(), activityAspectRatio);
+        }
+    }
+
+    /**
+     * Sets the min aspect ratio of every child activity that doesn't already have an aspect
+     * ratio set.
+     */
+    private void setMinAspectRatio(ParsingPackage pkg) {
+        final float minAspectRatio;
+        float packageMinAspectRatio = pkg.getMinAspectRatio();
+        if (packageMinAspectRatio != 0) {
+            // Use the application max aspect ration as default if set.
+            minAspectRatio = packageMinAspectRatio;
+        } else {
+            // Default to (1.33) 4:3 aspect ratio for pre-Q apps and unset for Q and greater.
+            // NOTE: 4:3 was the min aspect ratio Android devices can support pre-Q per the CDD,
+            // except for watches which always supported 1:1.
+            minAspectRatio = pkg.getTargetSdkVersion() >= Build.VERSION_CODES.Q
+                    ? 0
+                    : (mCallback != null && mCallback.hasFeature(FEATURE_WATCH))
+                            ? PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO_WATCH
+                            : PackageParser.DEFAULT_PRE_Q_MIN_ASPECT_RATIO;
+        }
+
+        List<ParsedActivity> activities = pkg.getActivities();
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            ParsedActivity activity = activities.get(index);
+            if (activity.getMinAspectRatio() == null) {
+                activity.setMinAspectRatio(activity.getResizeMode(), minAspectRatio);
+            }
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseOverlay(ParseInput input, ParsingPackage pkg,
+            Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestResourceOverlay);
+        try {
+            String target = sa.getString(R.styleable.AndroidManifestResourceOverlay_targetPackage);
+            int priority = anInt(0, R.styleable.AndroidManifestResourceOverlay_priority, sa);
+
+            if (target == null) {
+                return input.error("<overlay> does not specify a target package");
+            } else if (priority < 0 || priority > 9999) {
+                return input.error("<overlay> priority must be between 0 and 9999");
+            }
+
+            // check to see if overlay should be excluded based on system property condition
+            String propName = sa.getString(
+                    R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyName);
+            String propValue = sa.getString(
+                    R.styleable.AndroidManifestResourceOverlay_requiredSystemPropertyValue);
+            if (!checkOverlayRequiredSystemProperty(propName, propValue)) {
+                Slog.i(TAG, "Skipping target and overlay pair " + target + " and "
+                        + pkg.getBaseCodePath()
+                        + ": overlay ignored due to required system property: "
+                        + propName + " with value: " + propValue);
+                return input.error("Skipping target and overlay pair " + target + " and "
+                        + pkg.getBaseCodePath()
+                        + ": overlay ignored due to required system property: "
+                        + propName + " with value: " + propValue);
+            }
+
+            return input.success(pkg.setOverlay(true)
+                    .setOverlayTarget(target)
+                    .setOverlayPriority(priority)
+                    .setOverlayTargetName(
+                            sa.getString(R.styleable.AndroidManifestResourceOverlay_targetName))
+                    .setOverlayCategory(
+                            sa.getString(R.styleable.AndroidManifestResourceOverlay_category))
+                    .setOverlayIsStatic(
+                            bool(false, R.styleable.AndroidManifestResourceOverlay_isStatic, sa)));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseProtectedBroadcast(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProtectedBroadcast);
+        try {
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            String name = nonResString(R.styleable.AndroidManifestProtectedBroadcast_name, sa);
+            if (name != null) {
+                pkg.addProtectedBroadcast(name);
+            }
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseSupportScreens(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestSupportsScreens);
+        try {
+            int requiresSmallestWidthDp = anInt(0,
+                    R.styleable.AndroidManifestSupportsScreens_requiresSmallestWidthDp, sa);
+            int compatibleWidthLimitDp = anInt(0,
+                    R.styleable.AndroidManifestSupportsScreens_compatibleWidthLimitDp, sa);
+            int largestWidthLimitDp = anInt(0,
+                    R.styleable.AndroidManifestSupportsScreens_largestWidthLimitDp, sa);
+
+            // This is a trick to get a boolean and still able to detect
+            // if a value was actually set.
+            return input.success(pkg
+                    .setSupportsSmallScreens(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_smallScreens, sa))
+                    .setSupportsNormalScreens(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_normalScreens, sa))
+                    .setSupportsLargeScreens(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_largeScreens, sa))
+                    .setSupportsExtraLargeScreens(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_xlargeScreens, sa))
+                    .setResizeable(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_resizeable, sa))
+                    .setAnyDensity(
+                            anInt(1, R.styleable.AndroidManifestSupportsScreens_anyDensity, sa))
+                    .setRequiresSmallestWidthDp(requiresSmallestWidthDp)
+                    .setCompatibleWidthLimitDp(compatibleWidthLimitDp)
+                    .setLargestWidthLimitDp(largestWidthLimitDp));
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseInstrumentation(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser)
+            throws XmlPullParserException, IOException {
+        ParseResult<ParsedInstrumentation> result = ParsedInstrumentationUtils.parseInstrumentation(
+                pkg, res, parser, PackageParser.sUseRoundIcon, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        return input.success(pkg.addInstrumentation(result.getResult()));
+    }
+
+    private static ParseResult<ParsingPackage> parseOriginalPackage(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestOriginalPackage);
+        try {
+            String orig = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestOriginalPackage_name,
+                    0);
+            if (!pkg.getPackageName().equals(orig)) {
+                if (pkg.getOriginalPackages().isEmpty()) {
+                    pkg.setRealPackage(pkg.getPackageName());
+                }
+                pkg.addOriginalPackage(orig);
+            }
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static ParseResult<ParsingPackage> parseAdoptPermissions(ParseInput input,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestOriginalPackage);
+        try {
+            String name = nonConfigString(0, R.styleable.AndroidManifestOriginalPackage_name, sa);
+            if (name != null) {
+                pkg.addAdoptPermission(name);
+            }
+            return input.success(pkg);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    private static void convertNewPermissions(ParsingPackage pkg) {
+        final int NP = PackageParser.NEW_PERMISSIONS.length;
+        StringBuilder newPermsMsg = null;
+        for (int ip = 0; ip < NP; ip++) {
+            final PackageParser.NewPermissionInfo npi
+                    = PackageParser.NEW_PERMISSIONS[ip];
+            if (pkg.getTargetSdkVersion() >= npi.sdkVersion) {
+                break;
+            }
+            if (!pkg.getRequestedPermissions().contains(npi.name)) {
+                if (newPermsMsg == null) {
+                    newPermsMsg = new StringBuilder(128);
+                    newPermsMsg.append(pkg.getPackageName());
+                    newPermsMsg.append(": compat added ");
+                } else {
+                    newPermsMsg.append(' ');
+                }
+                newPermsMsg.append(npi.name);
+                pkg.addRequestedPermission(npi.name)
+                        .addImplicitPermission(npi.name);
+            }
+        }
+        if (newPermsMsg != null) {
+            Slog.i(TAG, newPermsMsg.toString());
+        }
+    }
+
+    private static void convertSplitPermissions(ParsingPackage pkg) {
+        List<SplitPermissionInfoParcelable> splitPermissions;
+
+        try {
+            splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        final int listSize = splitPermissions.size();
+        for (int is = 0; is < listSize; is++) {
+            final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
+            List<String> requestedPermissions = pkg.getRequestedPermissions();
+            if (pkg.getTargetSdkVersion() >= spi.getTargetSdk()
+                    || !requestedPermissions.contains(spi.getSplitPermission())) {
+                continue;
+            }
+            final List<String> newPerms = spi.getNewPermissions();
+            for (int in = 0; in < newPerms.size(); in++) {
+                final String perm = newPerms.get(in);
+                if (!requestedPermissions.contains(perm)) {
+                    pkg.addRequestedPermission(perm)
+                            .addImplicitPermission(perm);
+                }
+            }
+        }
+    }
+
+    private static boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
+        if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
+            if (!TextUtils.isEmpty(propName) || !TextUtils.isEmpty(propValue)) {
+                // malformed condition - incomplete
+                Slog.w(TAG, "Disabling overlay - incomplete property :'" + propName
+                        + "=" + propValue + "' - require both requiredSystemPropertyName"
+                        + " AND requiredSystemPropertyValue to be specified.");
+                return false;
+            }
+            // no valid condition set - so no exclusion criteria, overlay will be included.
+            return true;
+        }
+
+        // check property value - make sure it is both set and equal to expected value
+        final String currValue = SystemProperties.get(propName);
+        return (currValue != null && currValue.equals(propValue));
+    }
+
+    /**
+     * This is a pre-density application which will get scaled - instead of being pixel perfect.
+     * This type of application is not resizable.
+     *
+     * @param pkg The package which needs to be marked as unresizable.
+     */
+    private static void adjustPackageToBeUnresizeableAndUnpipable(ParsingPackage pkg) {
+        List<ParsedActivity> activities = pkg.getActivities();
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            ParsedActivity activity = activities.get(index);
+            activity.setResizeMode(RESIZE_MODE_UNRESIZEABLE)
+                    .setFlags(activity.getFlags() & ~FLAG_SUPPORTS_PICTURE_IN_PICTURE);
+        }
+    }
+
+    private static ParseResult validateName(ParseInput input, String name, boolean requireSeparator,
+            boolean requireFilename) {
+        final int N = name.length();
+        boolean hasSep = false;
+        boolean front = true;
+        for (int i = 0; i < N; i++) {
+            final char c = name.charAt(i);
+            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
+                front = false;
+                continue;
+            }
+            if (!front) {
+                if ((c >= '0' && c <= '9') || c == '_') {
+                    continue;
+                }
+            }
+            if (c == '.') {
+                hasSep = true;
+                front = true;
+                continue;
+            }
+            return input.error("bad character '" + c + "'");
+        }
+        if (requireFilename && !FileUtils.isValidExtFilename(name)) {
+            return input.error("Invalid filename");
+        }
+        return hasSep || !requireSeparator
+                ? input.success(null)
+                : input.error("must have at least one '.' separator");
+    }
+
+    public static ParseResult<Bundle> parseMetaData(ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, Bundle data, ParseInput input) {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestMetaData);
+        try {
+            if (data == null) {
+                data = new Bundle();
+            }
+
+            String name = TextUtils.safeIntern(
+                    nonConfigString(0, R.styleable.AndroidManifestMetaData_name, sa));
+            if (name == null) {
+                return input.error("<meta-data> requires an android:name attribute");
+            }
+
+            TypedValue v = sa.peekValue(R.styleable.AndroidManifestMetaData_resource);
+            if (v != null && v.resourceId != 0) {
+                //Slog.i(TAG, "Meta data ref " + name + ": " + v);
+                data.putInt(name, v.resourceId);
+            } else {
+                v = sa.peekValue(R.styleable.AndroidManifestMetaData_value);
+                //Slog.i(TAG, "Meta data " + name + ": " + v);
+                if (v != null) {
+                    if (v.type == TypedValue.TYPE_STRING) {
+                        CharSequence cs = v.coerceToString();
+                        data.putString(name, cs != null ? cs.toString() : null);
+                    } else if (v.type == TypedValue.TYPE_INT_BOOLEAN) {
+                        data.putBoolean(name, v.data != 0);
+                    } else if (v.type >= TypedValue.TYPE_FIRST_INT
+                            && v.type <= TypedValue.TYPE_LAST_INT) {
+                        data.putInt(name, v.data);
+                    } else if (v.type == TypedValue.TYPE_FLOAT) {
+                        data.putFloat(name, v.getFloat());
+                    } else {
+                        if (!PackageParser.RIGID_PARSER) {
+                            Slog.w(TAG,
+                                    "<meta-data> only supports string, integer, float, color, "
+                                            + "boolean, and resource reference types: "
+                                            + parser.getName() + " at "
+                                            + pkg.getBaseCodePath() + " "
+                                            + parser.getPositionDescription());
+                        } else {
+                            return input.error("<meta-data> only supports string, integer, float, "
+                                    + "color, boolean, and resource reference types");
+                        }
+                    }
+                } else {
+                    return input.error("<meta-data> requires an android:value "
+                            + "or android:resource attribute");
+                }
+            }
+            return input.success(data);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    /**
+     * Collect certificates from all the APKs described in the given package. Also asserts that
+     * all APK contents are signed correctly and consistently.
+     */
+    public static SigningDetails collectCertificates(ParsingPackageRead pkg, boolean skipVerify)
+            throws PackageParserException {
+        SigningDetails signingDetails = SigningDetails.UNKNOWN;
+
+        Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
+        try {
+            signingDetails = collectCertificates(
+                    pkg.getBaseCodePath(),
+                    skipVerify,
+                    pkg.isStaticSharedLibrary(),
+                    signingDetails,
+                    pkg.getTargetSdkVersion()
+            );
+
+            String[] splitCodePaths = pkg.getSplitCodePaths();
+            if (!ArrayUtils.isEmpty(splitCodePaths)) {
+                for (int i = 0; i < splitCodePaths.length; i++) {
+                    signingDetails = collectCertificates(
+                            splitCodePaths[i],
+                            skipVerify,
+                            pkg.isStaticSharedLibrary(),
+                            signingDetails,
+                            pkg.getTargetSdkVersion()
+                    );
+                }
+            }
+            return signingDetails;
+        } finally {
+            Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
+        }
+    }
+
+    public static SigningDetails collectCertificates(String baseCodePath, boolean skipVerify,
+            boolean isStaticSharedLibrary, @NonNull SigningDetails existingSigningDetails,
+            int targetSdk) throws PackageParserException {
+        int minSignatureScheme = ApkSignatureVerifier.getMinimumSignatureSchemeVersionForTargetSdk(
+                targetSdk);
+        if (isStaticSharedLibrary) {
+            // must use v2 signing scheme
+            minSignatureScheme = SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V2;
+        }
+        SigningDetails verified;
+        if (skipVerify) {
+            // systemDir APKs are already trusted, save time by not verifying
+            verified = ApkSignatureVerifier.unsafeGetCertsWithoutVerification(
+                    baseCodePath, minSignatureScheme);
+        } else {
+            verified = ApkSignatureVerifier.verify(baseCodePath, minSignatureScheme);
+        }
+
+        // Verify that entries are signed consistently with the first pkg
+        // we encountered. Note that for splits, certificates may have
+        // already been populated during an earlier parse of a base APK.
+        if (existingSigningDetails == SigningDetails.UNKNOWN) {
+            return verified;
+        } else {
+            if (!Signature.areExactMatch(existingSigningDetails.signatures, verified.signatures)) {
+                throw new PackageParserException(
+                        INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
+                        baseCodePath + " has mismatched certificates");
+            }
+
+            return existingSigningDetails;
+        }
+    }
+
+    /*
+     The following set of methods makes code easier to read by re-ordering the TypedArray methods.
+
+     The first parameter is the default, which is the most important to understand for someone
+     reading through the parsing code.
+
+     That's followed by the attribute name, which is usually irrelevant during reading because
+     it'll look like setSomeValue(true, R.styleable.ReallyLongParentName_SomeValueAttr... and
+     the "setSomeValue" part is enough to communicate what the line does.
+
+     Last comes the TypedArray, which is by far the least important since each try-with-resources
+     should only have 1.
+    */
+
+    // Note there is no variant of bool without a defaultValue parameter, since explicit true/false
+    // is important to specify when adding an attribute.
+    private static boolean bool(boolean defaultValue, @StyleableRes int attribute, TypedArray sa) {
+        return sa.getBoolean(attribute, defaultValue);
+    }
+
+    private static float aFloat(float defaultValue, @StyleableRes int attribute, TypedArray sa) {
+        return sa.getFloat(attribute, defaultValue);
+    }
+
+    private static float aFloat(@StyleableRes int attribute, TypedArray sa) {
+        return sa.getFloat(attribute, 0f);
+    }
+
+    private static int anInt(int defaultValue, @StyleableRes int attribute, TypedArray sa) {
+        return sa.getInt(attribute, defaultValue);
+    }
+
+    private static int anInt(@StyleableRes int attribute, TypedArray sa) {
+        return sa.getInt(attribute, 0);
+    }
+
+    @AnyRes
+    private static int resId(@StyleableRes int attribute, TypedArray sa) {
+        return sa.getResourceId(attribute, 0);
+    }
+
+    private static String string(@StyleableRes int attribute, TypedArray sa) {
+        return sa.getString(attribute);
+    }
+
+    private static String nonConfigString(int allowedChangingConfigs, @StyleableRes int attribute,
+            TypedArray sa) {
+        return sa.getNonConfigurationString(attribute, allowedChangingConfigs);
+    }
+
+    private static String nonResString(@StyleableRes int index, TypedArray sa) {
+        return sa.getNonResourceString(index);
+    }
+
+    /**
+     * Callback interface for retrieving information that may be needed while parsing
+     * a package.
+     */
+    public interface Callback {
+        boolean hasFeature(String feature);
+
+        ParsingPackage startParsingPackage(String packageName, String baseCodePath, String codePath,
+                TypedArray manifestArray, boolean isCoreApp);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/ParsingUtils.java b/core/java/android/content/pm/parsing/ParsingUtils.java
new file mode 100644
index 0000000..ba61de1
--- /dev/null
+++ b/core/java/android/content/pm/parsing/ParsingUtils.java
@@ -0,0 +1,70 @@
+/*
+ * 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.content.pm.parsing;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageParser;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.XmlResourceParser;
+import android.util.Slog;
+
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide **/
+public class ParsingUtils {
+
+    // TODO(b/135203078): Consolidate log tags
+    public static final String TAG = "PackageParsing";
+
+    @Nullable
+    public static String buildClassName(String pkg, CharSequence clsSeq) {
+        if (clsSeq == null || clsSeq.length() <= 0) {
+            return null;
+        }
+        String cls = clsSeq.toString();
+        char c = cls.charAt(0);
+        if (c == '.') {
+            return pkg + cls;
+        }
+        if (cls.indexOf('.') < 0) {
+            StringBuilder b = new StringBuilder(pkg);
+            b.append('.');
+            b.append(cls);
+            return b.toString();
+        }
+        return cls;
+    }
+
+    @NonNull
+    public static ParseResult unknownTag(String parentTag, ParsingPackage pkg,
+            XmlResourceParser parser, ParseInput input) throws IOException, XmlPullParserException {
+        if (PackageParser.RIGID_PARSER) {
+            return input.error("Bad element under " + parentTag + ": " + parser.getName());
+        }
+        Slog.w(TAG, "Unknown element under " + parentTag + ": "
+                + parser.getName() + " at " + pkg.getBaseCodePath() + " "
+                + parser.getPositionDescription());
+        XmlUtils.skipCurrentTag(parser);
+        return input.success(null); // Type doesn't matter
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ComponentParseUtils.java b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
new file mode 100644
index 0000000..c4caedc
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ComponentParseUtils.java
@@ -0,0 +1,178 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.AttrRes;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageUserState;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.text.TextUtils;
+
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+public class ComponentParseUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    public static boolean isImplicitlyExposedIntent(ParsedIntentInfo intentInfo) {
+        return intentInfo.hasCategory(Intent.CATEGORY_BROWSABLE)
+                || intentInfo.hasAction(Intent.ACTION_SEND)
+                || intentInfo.hasAction(Intent.ACTION_SENDTO)
+                || intentInfo.hasAction(Intent.ACTION_SEND_MULTIPLE);
+    }
+
+    static <Component extends ParsedComponent> ParseResult<Component> parseAllMetaData(
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, String tag,
+            Component component, ParseInput input) throws XmlPullParserException, IOException {
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult result;
+            if ("meta-data".equals(parser.getName())) {
+                result = ParsedComponentUtils.addMetaData(component, pkg, res, parser, input);
+            } else {
+                result = ParsingUtils.unknownTag(tag, pkg, parser, input);
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        return input.success(component);
+    }
+
+    @NonNull
+    public static ParseResult<String> buildProcessName(@NonNull String pkg, String defProc,
+            CharSequence procSeq, int flags, String[] separateProcesses, ParseInput input) {
+        if ((flags & PackageParser.PARSE_IGNORE_PROCESSES) != 0 && !"system".contentEquals(
+                procSeq)) {
+            return input.success(defProc != null ? defProc : pkg);
+        }
+        if (separateProcesses != null) {
+            for (int i = separateProcesses.length - 1; i >= 0; i--) {
+                String sp = separateProcesses[i];
+                if (sp.equals(pkg) || sp.equals(defProc) || sp.contentEquals(procSeq)) {
+                    return input.success(pkg);
+                }
+            }
+        }
+        if (procSeq == null || procSeq.length() <= 0) {
+            return input.success(defProc);
+        }
+
+        ParseResult<String> nameResult = ComponentParseUtils.buildCompoundName(pkg, procSeq,
+                "process", input);
+        return input.success(TextUtils.safeIntern(nameResult.getResult()));
+    }
+
+    @NonNull
+    public static ParseResult<String> buildTaskAffinityName(String pkg, String defProc,
+            CharSequence procSeq, ParseInput input) {
+        if (procSeq == null) {
+            return input.success(defProc);
+        }
+        if (procSeq.length() <= 0) {
+            return input.success(null);
+        }
+        return buildCompoundName(pkg, procSeq, "taskAffinity", input);
+    }
+
+    public static ParseResult<String> buildCompoundName(String pkg, CharSequence procSeq,
+            String type, ParseInput input) {
+        String proc = procSeq.toString();
+        char c = proc.charAt(0);
+        if (pkg != null && c == ':') {
+            if (proc.length() < 2) {
+                return input.error("Bad " + type + " name " + proc + " in package " + pkg
+                        + ": must be at least two characters");
+            }
+            String subName = proc.substring(1);
+            String nameError = PackageParser.validateName(subName, false, false);
+            if (nameError != null) {
+                return input.error("Invalid " + type + " name " + proc + " in package " + pkg
+                        + ": " + nameError);
+            }
+            return input.success(pkg + proc);
+        }
+        String nameError = PackageParser.validateName(proc, true, false);
+        if (nameError != null && !"system".equals(proc)) {
+            return input.error("Invalid " + type + " name " + proc + " in package " + pkg
+                    + ": " + nameError);
+        }
+        return input.success(proc);
+    }
+
+    public static int flag(int flag, @AttrRes int attribute, TypedArray typedArray) {
+        return typedArray.getBoolean(attribute, false) ? flag : 0;
+    }
+
+    public static int flag(int flag, @AttrRes int attribute, boolean defaultValue,
+            TypedArray typedArray) {
+        return typedArray.getBoolean(attribute, defaultValue) ? flag : 0;
+    }
+
+    /**
+     * This is not state aware. Avoid and access through PackageInfoUtils in the system server.
+     */
+    @Nullable
+    public static CharSequence getNonLocalizedLabel(
+            ParsedComponent component) {
+        return component.nonLocalizedLabel;
+    }
+
+    /**
+     * This is not state aware. Avoid and access through PackageInfoUtils in the system server.
+     *
+     * This is a method of the utility class to discourage use.
+     */
+    public static int getIcon(ParsedComponent component) {
+        return component.icon;
+    }
+
+    public static boolean isMatch(PackageUserState state, boolean isSystem,
+            boolean isPackageEnabled, ParsedMainComponent component, int flags) {
+        return state.isMatch(isSystem, isPackageEnabled, component.isEnabled(),
+                component.isDirectBootAware(), component.getName(), flags);
+    }
+
+    public static boolean isEnabled(PackageUserState state, boolean isPackageEnabled,
+            ParsedMainComponent parsedComponent, int flags) {
+        return state.isEnabled(isPackageEnabled, parsedComponent.isEnabled(),
+                parsedComponent.getName(), flags);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivity.java b/core/java/android/content/pm/parsing/component/ParsedActivity.java
new file mode 100644
index 0000000..5495c22
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedActivity.java
@@ -0,0 +1,451 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE;
+import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
+
+import android.annotation.Nullable;
+import android.app.ActivityTaskManager;
+import android.content.ComponentName;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.parsing.ParsingPackageImpl;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide **/
+public class ParsedActivity extends ParsedMainComponent {
+
+    int theme;
+    int uiOptions;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String targetActivity;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String parentActivityName;
+    @Nullable
+    String taskAffinity;
+    int privateFlags;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String permission;
+
+    int launchMode;
+    int documentLaunchMode;
+    int maxRecents;
+    int configChanges;
+    int softInputMode;
+    int persistableMode;
+    int lockTaskLaunchMode;
+
+    int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+    int resizeMode = ActivityInfo.RESIZE_MODE_RESIZEABLE;
+
+    @Nullable
+    private Float maxAspectRatio;
+
+    @Nullable
+    private Float minAspectRatio;
+
+    @Nullable
+    String requestedVrComponent;
+    int rotationAnimation = -1;
+    int colorMode;
+
+    boolean preferMinimalPostProcessing;
+
+    @Nullable
+    ActivityInfo.WindowLayout windowLayout;
+
+    public ParsedActivity(ParsedActivity other) {
+        super(other);
+        this.theme = other.theme;
+        this.uiOptions = other.uiOptions;
+        this.targetActivity = other.targetActivity;
+        this.parentActivityName = other.parentActivityName;
+        this.taskAffinity = other.taskAffinity;
+        this.privateFlags = other.privateFlags;
+        this.permission = other.permission;
+        this.launchMode = other.launchMode;
+        this.documentLaunchMode = other.documentLaunchMode;
+        this.maxRecents = other.maxRecents;
+        this.configChanges = other.configChanges;
+        this.softInputMode = other.softInputMode;
+        this.persistableMode = other.persistableMode;
+        this.lockTaskLaunchMode = other.lockTaskLaunchMode;
+        this.screenOrientation = other.screenOrientation;
+        this.resizeMode = other.resizeMode;
+        this.maxAspectRatio = other.maxAspectRatio;
+        this.minAspectRatio = other.minAspectRatio;
+        this.requestedVrComponent = other.requestedVrComponent;
+        this.rotationAnimation = other.rotationAnimation;
+        this.colorMode = other.colorMode;
+        this.windowLayout = other.windowLayout;
+    }
+
+    /**
+     * Generate activity object that forwards user to App Details page automatically.
+     * This activity should be invisible to user and user should not know or see it.
+     */
+    public static ParsedActivity makeAppDetailsActivity(String packageName, String processName,
+            int uiOptions, String taskAffinity, boolean hardwareAccelerated) {
+        ParsedActivity activity = new ParsedActivity();
+        activity.setPackageName(packageName);
+        activity.theme = android.R.style.Theme_NoDisplay;
+        activity.exported = true;
+        activity.setName(PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME);
+        activity.setProcessName(processName);
+        activity.uiOptions = uiOptions;
+        activity.taskAffinity = taskAffinity;
+        activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+        activity.documentLaunchMode = ActivityInfo.DOCUMENT_LAUNCH_NONE;
+        activity.maxRecents = ActivityTaskManager.getDefaultAppRecentsLimitStatic();
+        activity.configChanges = PackageParser.getActivityConfigChanges(0, 0);
+        activity.softInputMode = 0;
+        activity.persistableMode = ActivityInfo.PERSIST_NEVER;
+        activity.screenOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+        activity.resizeMode = RESIZE_MODE_FORCE_RESIZEABLE;
+        activity.lockTaskLaunchMode = 0;
+        activity.setDirectBootAware(false);
+        activity.rotationAnimation = ROTATION_ANIMATION_UNSPECIFIED;
+        activity.colorMode = ActivityInfo.COLOR_MODE_DEFAULT;
+        activity.preferMinimalPostProcessing = ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT;
+        if (hardwareAccelerated) {
+            activity.setFlags(activity.getFlags() | ActivityInfo.FLAG_HARDWARE_ACCELERATED);
+        }
+        return activity;
+    }
+
+    static ParsedActivity makeAlias(String targetActivityName, ParsedActivity target) {
+        ParsedActivity alias = new ParsedActivity();
+        alias.setPackageName(target.getPackageName());
+        alias.setTargetActivity(targetActivityName);
+        alias.configChanges = target.configChanges;
+        alias.flags = target.flags;
+        alias.privateFlags = target.privateFlags;
+        alias.icon = target.icon;
+        alias.logo = target.logo;
+        alias.banner = target.banner;
+        alias.labelRes = target.labelRes;
+        alias.nonLocalizedLabel = target.nonLocalizedLabel;
+        alias.launchMode = target.launchMode;
+        alias.lockTaskLaunchMode = target.lockTaskLaunchMode;
+        alias.descriptionRes = target.descriptionRes;
+        alias.screenOrientation = target.screenOrientation;
+        alias.taskAffinity = target.taskAffinity;
+        alias.theme = target.theme;
+        alias.softInputMode = target.softInputMode;
+        alias.uiOptions = target.uiOptions;
+        alias.parentActivityName = target.parentActivityName;
+        alias.maxRecents = target.maxRecents;
+        alias.windowLayout = target.windowLayout;
+        alias.resizeMode = target.resizeMode;
+        alias.maxAspectRatio = target.maxAspectRatio;
+        alias.minAspectRatio = target.minAspectRatio;
+        alias.requestedVrComponent = target.requestedVrComponent;
+        alias.directBootAware = target.directBootAware;
+        alias.setProcessName(target.getProcessName());
+        return alias;
+
+        // Not all attributes from the target ParsedActivity are copied to the alias.
+        // Careful when adding an attribute and determine whether or not it should be copied.
+//        alias.enabled = target.enabled;
+//        alias.exported = target.exported;
+//        alias.permission = target.permission;
+//        alias.splitName = target.splitName;
+//        alias.documentLaunchMode = target.documentLaunchMode;
+//        alias.persistableMode = target.persistableMode;
+//        alias.rotationAnimation = target.rotationAnimation;
+//        alias.colorMode = target.colorMode;
+//        alias.intents.addAll(target.intents);
+//        alias.order = target.order;
+//        alias.metaData = target.metaData;
+    }
+
+    public ParsedActivity setMaxAspectRatio(int resizeMode, float maxAspectRatio) {
+        if (resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE
+                || resizeMode == ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
+            // Resizeable activities can be put in any aspect ratio.
+            return this;
+        }
+
+        if (maxAspectRatio < 1.0f && maxAspectRatio != 0) {
+            // Ignore any value lesser than 1.0.
+            return this;
+        }
+
+        this.maxAspectRatio = maxAspectRatio;
+        return this;
+    }
+
+    public ParsedActivity setMinAspectRatio(int resizeMode, float minAspectRatio) {
+        if (resizeMode == RESIZE_MODE_RESIZEABLE
+                || resizeMode == RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION) {
+            // Resizeable activities can be put in any aspect ratio.
+            return this;
+        }
+
+        if (minAspectRatio < 1.0f && minAspectRatio != 0) {
+            // Ignore any value lesser than 1.0.
+            return this;
+        }
+
+        this.minAspectRatio = minAspectRatio;
+        return this;
+    }
+
+    public ParsedActivity setFlags(int flags) {
+        this.flags = flags;
+        return this;
+    }
+
+    public ParsedActivity setResizeMode(int resizeMode) {
+        this.resizeMode = resizeMode;
+        return this;
+    }
+
+    public ParsedActivity setTargetActivity(String targetActivity) {
+        this.targetActivity = TextUtils.safeIntern(targetActivity);
+        return this;
+    }
+
+    public ParsedActivity setParentActivity(String parentActivity) {
+        this.parentActivityName = TextUtils.safeIntern(parentActivity);
+        return this;
+    }
+
+    public ParsedActivity setPermission(String permission) {
+        // Empty string must be converted to null
+        this.permission = TextUtils.isEmpty(permission) ? null : permission.intern();
+        return this;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("Activity{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        ComponentName.appendShortString(sb, getPackageName(), getName());
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(this.theme);
+        dest.writeInt(this.uiOptions);
+        sForString.parcel(this.targetActivity, dest, flags);
+        sForString.parcel(this.parentActivityName, dest, flags);
+        dest.writeString(this.taskAffinity);
+        dest.writeInt(this.privateFlags);
+        sForString.parcel(this.permission, dest, flags);
+        dest.writeInt(this.launchMode);
+        dest.writeInt(this.documentLaunchMode);
+        dest.writeInt(this.maxRecents);
+        dest.writeInt(this.configChanges);
+        dest.writeInt(this.softInputMode);
+        dest.writeInt(this.persistableMode);
+        dest.writeInt(this.lockTaskLaunchMode);
+        dest.writeInt(this.screenOrientation);
+        dest.writeInt(this.resizeMode);
+        dest.writeValue(this.maxAspectRatio);
+        dest.writeValue(this.minAspectRatio);
+        dest.writeString(this.requestedVrComponent);
+        dest.writeInt(this.rotationAnimation);
+        dest.writeInt(this.colorMode);
+        dest.writeBoolean(this.preferMinimalPostProcessing);
+        dest.writeBundle(this.metaData);
+
+        if (windowLayout != null) {
+            dest.writeBoolean(true);
+            dest.writeInt(windowLayout.width);
+            dest.writeFloat(windowLayout.widthFraction);
+            dest.writeInt(windowLayout.height);
+            dest.writeFloat(windowLayout.heightFraction);
+            dest.writeInt(windowLayout.gravity);
+            dest.writeInt(windowLayout.minWidth);
+            dest.writeInt(windowLayout.minHeight);
+        } else {
+            dest.writeBoolean(false);
+        }
+    }
+
+    public ParsedActivity() {
+    }
+
+    protected ParsedActivity(Parcel in) {
+        super(in);
+        this.theme = in.readInt();
+        this.uiOptions = in.readInt();
+        this.targetActivity = sForString.unparcel(in);
+        this.parentActivityName = sForString.unparcel(in);
+        this.taskAffinity = in.readString();
+        this.privateFlags = in.readInt();
+        this.permission = sForString.unparcel(in);
+        this.launchMode = in.readInt();
+        this.documentLaunchMode = in.readInt();
+        this.maxRecents = in.readInt();
+        this.configChanges = in.readInt();
+        this.softInputMode = in.readInt();
+        this.persistableMode = in.readInt();
+        this.lockTaskLaunchMode = in.readInt();
+        this.screenOrientation = in.readInt();
+        this.resizeMode = in.readInt();
+        this.maxAspectRatio = (Float) in.readValue(Float.class.getClassLoader());
+        this.minAspectRatio = (Float) in.readValue(Float.class.getClassLoader());
+        this.requestedVrComponent = in.readString();
+        this.rotationAnimation = in.readInt();
+        this.colorMode = in.readInt();
+        this.preferMinimalPostProcessing = in.readBoolean();
+        this.metaData = in.readBundle();
+        if (in.readBoolean()) {
+            windowLayout = new ActivityInfo.WindowLayout(in);
+        }
+    }
+
+    public static final Parcelable.Creator<ParsedActivity> CREATOR = new Creator<ParsedActivity>() {
+        @Override
+        public ParsedActivity createFromParcel(Parcel source) {
+            return new ParsedActivity(source);
+        }
+
+        @Override
+        public ParsedActivity[] newArray(int size) {
+            return new ParsedActivity[size];
+        }
+    };
+
+    public int getTheme() {
+        return theme;
+    }
+
+    public int getUiOptions() {
+        return uiOptions;
+    }
+
+    @Nullable
+    public String getTargetActivity() {
+        return targetActivity;
+    }
+
+    @Nullable
+    public String getParentActivityName() {
+        return parentActivityName;
+    }
+
+    @Nullable
+    public String getTaskAffinity() {
+        return taskAffinity;
+    }
+
+    public int getPrivateFlags() {
+        return privateFlags;
+    }
+
+    @Nullable
+    public String getPermission() {
+        return permission;
+    }
+
+    public int getLaunchMode() {
+        return launchMode;
+    }
+
+    public int getDocumentLaunchMode() {
+        return documentLaunchMode;
+    }
+
+    public int getMaxRecents() {
+        return maxRecents;
+    }
+
+    public int getConfigChanges() {
+        return configChanges;
+    }
+
+    public int getSoftInputMode() {
+        return softInputMode;
+    }
+
+    public int getPersistableMode() {
+        return persistableMode;
+    }
+
+    public int getLockTaskLaunchMode() {
+        return lockTaskLaunchMode;
+    }
+
+    public int getScreenOrientation() {
+        return screenOrientation;
+    }
+
+    public int getResizeMode() {
+        return resizeMode;
+    }
+
+    @Nullable
+    public Float getMaxAspectRatio() {
+        return maxAspectRatio;
+    }
+
+    @Nullable
+    public Float getMinAspectRatio() {
+        return minAspectRatio;
+    }
+
+    @Nullable
+    public String getRequestedVrComponent() {
+        return requestedVrComponent;
+    }
+
+    public int getRotationAnimation() {
+        return rotationAnimation;
+    }
+
+    public int getColorMode() {
+        return colorMode;
+    }
+
+    public boolean isPreferMinimalPostProcessing() {
+        return preferMinimalPostProcessing;
+    }
+
+    @Nullable
+    public ActivityInfo.WindowLayout getWindowLayout() {
+        return windowLayout;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
new file mode 100644
index 0000000..555cdd0
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedActivityUtils.java
@@ -0,0 +1,484 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+
+import static android.content.pm.parsing.component.ComponentParseUtils.flag;
+
+import android.annotation.NonNull;
+import android.app.ActivityTaskManager;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageParser;
+
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Slog;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.WindowManager;
+
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.ArrayUtils;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Objects;
+
+/** @hide */
+public class ParsedActivityUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public static ParseResult<ParsedActivity> parseActivityOrReceiver(String[] separateProcesses,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags,
+            boolean useRoundIcon, ParseInput input)
+            throws XmlPullParserException, IOException {
+        final String packageName = pkg.getPackageName();
+        final ParsedActivity
+                activity = new ParsedActivity();
+
+        boolean receiver = "receiver".equals(parser.getName());
+        String tag = "<" + parser.getName() + ">";
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivity);
+        try {
+            ParseResult<ParsedActivity> result =
+                    ParsedMainComponentUtils.parseMainComponent(
+                    activity, tag, separateProcesses,
+                    pkg, sa, flags, useRoundIcon, input,
+                    R.styleable.AndroidManifestActivity_banner,
+                    R.styleable.AndroidManifestActivity_description,
+                    R.styleable.AndroidManifestActivity_directBootAware,
+                    R.styleable.AndroidManifestActivity_enabled,
+                    R.styleable.AndroidManifestActivity_icon,
+                    R.styleable.AndroidManifestActivity_label,
+                    R.styleable.AndroidManifestActivity_logo,
+                    R.styleable.AndroidManifestActivity_name,
+                    R.styleable.AndroidManifestActivity_process,
+                    R.styleable.AndroidManifestActivity_roundIcon,
+                    R.styleable.AndroidManifestActivity_splitName);
+            if (result.isError()) {
+                return result;
+            }
+
+            if (receiver && pkg.isCantSaveState()) {
+                // A heavy-weight application can not have receivers in its main process
+                if (Objects.equals(activity.getProcessName(), packageName)) {
+                    return input.error("Heavy-weight applications can not have receivers "
+                            + "in main process");
+                }
+            }
+
+            // The following section has formatting off to make it easier to read the flags.
+            // Multi-lining them to fit within the column restriction makes it hard to tell what
+            // field is assigned where.
+            // @formatter:off
+            activity.theme = sa.getResourceId(R.styleable.AndroidManifestActivity_theme, 0);
+            activity.uiOptions = sa.getInt(R.styleable.AndroidManifestActivity_uiOptions, pkg.getUiOptions());
+
+            activity.flags |= flag(ActivityInfo.FLAG_ALLOW_TASK_REPARENTING, R.styleable.AndroidManifestActivity_allowTaskReparenting, pkg.isAllowTaskReparenting(), sa)
+                    | flag(ActivityInfo.FLAG_ALWAYS_RETAIN_TASK_STATE, R.styleable.AndroidManifestActivity_alwaysRetainTaskState, sa)
+                    | flag(ActivityInfo.FLAG_CLEAR_TASK_ON_LAUNCH, R.styleable.AndroidManifestActivity_clearTaskOnLaunch, sa)
+                    | flag(ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS, R.styleable.AndroidManifestActivity_excludeFromRecents, sa)
+                    | flag(ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS, R.styleable.AndroidManifestActivity_finishOnCloseSystemDialogs, sa)
+                    | flag(ActivityInfo.FLAG_FINISH_ON_TASK_LAUNCH, R.styleable.AndroidManifestActivity_finishOnTaskLaunch, sa)
+                    | flag(ActivityInfo.FLAG_IMMERSIVE, R.styleable.AndroidManifestActivity_immersive, sa)
+                    | flag(ActivityInfo.FLAG_MULTIPROCESS, R.styleable.AndroidManifestActivity_multiprocess, sa)
+                    | flag(ActivityInfo.FLAG_NO_HISTORY, R.styleable.AndroidManifestActivity_noHistory, sa)
+                    | flag(ActivityInfo.FLAG_SHOW_FOR_ALL_USERS, R.styleable.AndroidManifestActivity_showForAllUsers, sa)
+                    | flag(ActivityInfo.FLAG_SHOW_FOR_ALL_USERS, R.styleable.AndroidManifestActivity_showOnLockScreen, sa)
+                    | flag(ActivityInfo.FLAG_STATE_NOT_NEEDED, R.styleable.AndroidManifestActivity_stateNotNeeded, sa)
+                    | flag(ActivityInfo.FLAG_SYSTEM_USER_ONLY, R.styleable.AndroidManifestActivity_systemUserOnly, sa);
+
+            if (!receiver) {
+                activity.flags |= flag(ActivityInfo.FLAG_HARDWARE_ACCELERATED, R.styleable.AndroidManifestActivity_hardwareAccelerated, pkg.isBaseHardwareAccelerated(), sa)
+                        | flag(ActivityInfo.FLAG_ALLOW_EMBEDDED, R.styleable.AndroidManifestActivity_allowEmbedded, sa)
+                        | flag(ActivityInfo.FLAG_ALWAYS_FOCUSABLE, R.styleable.AndroidManifestActivity_alwaysFocusable, sa)
+                        | flag(ActivityInfo.FLAG_AUTO_REMOVE_FROM_RECENTS, R.styleable.AndroidManifestActivity_autoRemoveFromRecents, sa)
+                        | flag(ActivityInfo.FLAG_RELINQUISH_TASK_IDENTITY, R.styleable.AndroidManifestActivity_relinquishTaskIdentity, sa)
+                        | flag(ActivityInfo.FLAG_RESUME_WHILE_PAUSING, R.styleable.AndroidManifestActivity_resumeWhilePausing, sa)
+                        | flag(ActivityInfo.FLAG_SHOW_WHEN_LOCKED, R.styleable.AndroidManifestActivity_showWhenLocked, sa)
+                        | flag(ActivityInfo.FLAG_SUPPORTS_PICTURE_IN_PICTURE, R.styleable.AndroidManifestActivity_supportsPictureInPicture, sa)
+                        | flag(ActivityInfo.FLAG_TURN_SCREEN_ON, R.styleable.AndroidManifestActivity_turnScreenOn, sa);
+
+                activity.privateFlags |= flag(ActivityInfo.FLAG_INHERIT_SHOW_WHEN_LOCKED, R.styleable.AndroidManifestActivity_inheritShowWhenLocked, sa);
+
+                activity.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode, ActivityInfo.COLOR_MODE_DEFAULT);
+                activity.preferMinimalPostProcessing = sa.getBoolean(R.styleable.AndroidManifestActivity_preferMinimalPostProcessing, ActivityInfo.MINIMAL_POST_PROCESSING_DEFAULT);
+                activity.documentLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_documentLaunchMode, ActivityInfo.DOCUMENT_LAUNCH_NONE);
+                activity.launchMode = sa.getInt(R.styleable.AndroidManifestActivity_launchMode, ActivityInfo.LAUNCH_MULTIPLE);
+                activity.lockTaskLaunchMode = sa.getInt(R.styleable.AndroidManifestActivity_lockTaskMode, 0);
+                activity.maxRecents = sa.getInt(R.styleable.AndroidManifestActivity_maxRecents, ActivityTaskManager.getDefaultAppRecentsLimitStatic());
+                activity.persistableMode = sa.getInteger(R.styleable.AndroidManifestActivity_persistableMode, ActivityInfo.PERSIST_ROOT_ONLY);
+                activity.requestedVrComponent = sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
+                activity.rotationAnimation = sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED);
+                activity.softInputMode = sa.getInt(R.styleable.AndroidManifestActivity_windowSoftInputMode, 0);
+
+                activity.configChanges = PackageParser.getActivityConfigChanges(
+                        sa.getInt(R.styleable.AndroidManifestActivity_configChanges, 0),
+                        sa.getInt(R.styleable.AndroidManifestActivity_recreateOnConfigChanges, 0));
+
+                int screenOrientation = sa.getInt(R.styleable.AndroidManifestActivity_screenOrientation, SCREEN_ORIENTATION_UNSPECIFIED);
+                int resizeMode = getActivityResizeMode(pkg, sa, screenOrientation);
+                activity.screenOrientation = screenOrientation;
+                activity.resizeMode = resizeMode;
+
+                if (sa.hasValue(R.styleable.AndroidManifestActivity_maxAspectRatio)
+                        && sa.getType(R.styleable.AndroidManifestActivity_maxAspectRatio)
+                        == TypedValue.TYPE_FLOAT) {
+                    activity.setMaxAspectRatio(resizeMode,
+                            sa.getFloat(R.styleable.AndroidManifestActivity_maxAspectRatio,
+                                    0 /*default*/));
+                }
+
+                if (sa.hasValue(R.styleable.AndroidManifestActivity_minAspectRatio)
+                        && sa.getType(R.styleable.AndroidManifestActivity_minAspectRatio)
+                        == TypedValue.TYPE_FLOAT) {
+                    activity.setMinAspectRatio(resizeMode,
+                            sa.getFloat(R.styleable.AndroidManifestActivity_minAspectRatio,
+                                    0 /*default*/));
+                }
+            } else {
+                activity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
+                activity.configChanges = 0;
+                activity.flags |= flag(ActivityInfo.FLAG_SINGLE_USER, R.styleable.AndroidManifestActivity_singleUser, sa);
+            }
+            // @formatter:on
+
+            String taskAffinity = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestActivity_taskAffinity,
+                    Configuration.NATIVE_CONFIG_VERSION);
+
+            ParseResult<String> affinityNameResult = ComponentParseUtils.buildTaskAffinityName(
+                    packageName, pkg.getTaskAffinity(), taskAffinity, input);
+            if (affinityNameResult.isSuccess()) {
+                activity.taskAffinity = affinityNameResult.getResult();
+            } else {
+                // Backwards-compat, ignore error
+                affinityNameResult.ignoreError();
+            }
+
+            boolean visibleToEphemeral = sa.getBoolean(R.styleable.AndroidManifestActivity_visibleToInstantApps, false);
+            if (visibleToEphemeral) {
+                activity.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                pkg.setVisibleToInstantApps(true);
+            }
+
+            return parseActivityOrAlias(activity, pkg, tag, parser, res, sa, receiver,
+                    false /*isAlias*/, visibleToEphemeral, input,
+                    R.styleable.AndroidManifestActivity_parentActivityName,
+                    R.styleable.AndroidManifestActivity_permission,
+                    R.styleable.AndroidManifestActivity_exported
+            );
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    public static ParseResult<ParsedActivity> parseActivityAlias(ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
+            throws XmlPullParserException, IOException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestActivityAlias);
+        try {
+            String targetActivity = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestActivityAlias_targetActivity,
+                    Configuration.NATIVE_CONFIG_VERSION);
+            if (targetActivity == null) {
+                return input.error("<activity-alias> does not specify android:targetActivity");
+            }
+
+            String packageName = pkg.getPackageName();
+            targetActivity = ParsingUtils.buildClassName(packageName, targetActivity);
+            if (targetActivity == null) {
+                return input.error("Empty class name in package " + packageName);
+            }
+
+            ParsedActivity target = null;
+
+            List<ParsedActivity> activities = pkg.getActivities();
+            final int activitiesSize = ArrayUtils.size(activities);
+            for (int i = 0; i < activitiesSize; i++) {
+                ParsedActivity t = activities.get(i);
+                if (targetActivity.equals(t.getName())) {
+                    target = t;
+                    break;
+                }
+            }
+
+            if (target == null) {
+                return input.error("<activity-alias> target activity " + targetActivity
+                        + " not found in manifest with activities = "
+                        + pkg.getActivities()
+                        + ", parsedActivities = " + activities);
+            }
+
+            ParsedActivity activity = ParsedActivity.makeAlias(targetActivity, target);
+            String tag = "<" + parser.getName() + ">";
+
+            ParseResult<ParsedActivity> result = ParsedMainComponentUtils.parseMainComponent(
+                    activity, tag, null, pkg, sa, 0, useRoundIcon, input,
+                    R.styleable.AndroidManifestActivityAlias_banner,
+                    R.styleable.AndroidManifestActivityAlias_description,
+                    null /*directBootAwareAttr*/,
+                    R.styleable.AndroidManifestActivityAlias_enabled,
+                    R.styleable.AndroidManifestActivityAlias_icon,
+                    R.styleable.AndroidManifestActivityAlias_label,
+                    R.styleable.AndroidManifestActivityAlias_logo,
+                    R.styleable.AndroidManifestActivityAlias_name,
+                    null /*processAttr*/,
+                    R.styleable.AndroidManifestActivityAlias_roundIcon,
+                    null /*splitNameAttr*/);
+            if (result.isError()) {
+                return result;
+            }
+
+            // TODO add visibleToInstantApps attribute to activity alias
+            final boolean visibleToEphemeral =
+                    ((activity.getFlags() & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0);
+
+            return parseActivityOrAlias(activity, pkg, tag, parser, res, sa, false /*isReceiver*/, true /*isAlias*/,
+                    visibleToEphemeral, input,
+                    R.styleable.AndroidManifestActivityAlias_parentActivityName,
+                    R.styleable.AndroidManifestActivityAlias_permission,
+                    R.styleable.AndroidManifestActivityAlias_exported);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    /**
+     * This method shares parsing logic between Activity/Receiver/alias instances, but requires
+     * passing in booleans for isReceiver/isAlias, since there's no indicator in the other
+     * parameters.
+     *
+     * They're used to filter the parsed tags and their behavior. This makes the method rather
+     * messy, but it's more maintainable than writing 3 separate methods for essentially the same
+     * type of logic.
+     */
+    @NonNull
+    private static ParseResult<ParsedActivity> parseActivityOrAlias(ParsedActivity activity,
+            ParsingPackage pkg, String tag, XmlResourceParser parser, Resources resources,
+            TypedArray array, boolean isReceiver, boolean isAlias, boolean visibleToEphemeral,
+            ParseInput input, int parentActivityNameAttr, int permissionAttr,
+            int exportedAttr) throws IOException, XmlPullParserException {
+        String parentActivityName = array.getNonConfigurationString(parentActivityNameAttr, Configuration.NATIVE_CONFIG_VERSION);
+        if (parentActivityName != null) {
+            String packageName = pkg.getPackageName();
+            String parentClassName = ParsingUtils.buildClassName(packageName, parentActivityName);
+            if (parentClassName == null) {
+                Log.e(TAG, "Activity " + activity.getName()
+                        + " specified invalid parentActivityName " + parentActivityName);
+            } else {
+                activity.setParentActivity(parentClassName);
+            }
+        }
+
+        String permission = array.getNonConfigurationString(permissionAttr, 0);
+        activity.setPermission(permission != null ? permission : pkg.getPermission());
+
+        final boolean setExported = array.hasValue(exportedAttr);
+        if (setExported) {
+            activity.exported = array.getBoolean(exportedAttr, false);
+        }
+
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult result;
+            if (parser.getName().equals("intent-filter")) {
+                ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
+                        !isReceiver, visibleToEphemeral, resources, parser, input);
+                if (intentResult.isSuccess()) {
+                    ParsedIntentInfo intent = intentResult.getResult();
+                    if (intent != null) {
+                        activity.order = Math.max(intent.getOrder(), activity.order);
+                        activity.addIntent(intent);
+                        if (PackageParser.LOG_UNSAFE_BROADCASTS && isReceiver
+                                && pkg.getTargetSdkVersion() >= Build.VERSION_CODES.O) {
+                            int actionCount = intent.countActions();
+                            for (int i = 0; i < actionCount; i++) {
+                                final String action = intent.getAction(i);
+                                if (action == null || !action.startsWith("android.")) {
+                                    continue;
+                                }
+
+                                if (!PackageParser.SAFE_BROADCASTS.contains(action)) {
+                                    Slog.w(TAG,
+                                            "Broadcast " + action + " may never be delivered to "
+                                                    + pkg.getPackageName() + " as requested at: "
+                                                    + parser.getPositionDescription());
+                                }
+                            }
+                        }
+                    }
+                }
+                result = intentResult;
+            } else if (parser.getName().equals("meta-data")) {
+                result = ParsedComponentUtils.addMetaData(activity, pkg, resources, parser, input);
+            } else if (!isReceiver && !isAlias && parser.getName().equals("preferred")) {
+                ParseResult<ParsedIntentInfo> intentResult = parseIntentFilter(pkg, activity,
+                        true /*allowImplicitEphemeralVisibility*/, visibleToEphemeral,
+                        resources, parser, input);
+                if (intentResult.isSuccess()) {
+                    ParsedIntentInfo intent = intentResult.getResult();
+                    if (intent != null) {
+                        pkg.addPreferredActivityFilter(activity.getClassName(), intent);
+                    }
+                }
+                result = intentResult;
+            } else if (!isReceiver && !isAlias && parser.getName().equals("layout")) {
+                ParseResult<ActivityInfo.WindowLayout> layoutResult = parseLayout(resources, parser,
+                        input);
+                if (layoutResult.isSuccess()) {
+                    activity.windowLayout = layoutResult.getResult();
+                }
+                result = layoutResult;
+            } else {
+                result = ParsingUtils.unknownTag(tag, pkg, parser, input);
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        if (!setExported) {
+            activity.exported = activity.getIntents().size() > 0;
+        }
+
+        return input.success(activity);
+    }
+
+    @NonNull
+    private static ParseResult<ParsedIntentInfo> parseIntentFilter(ParsingPackage pkg,
+            ParsedActivity activity, boolean allowImplicitEphemeralVisibility,
+            boolean visibleToEphemeral, Resources resources, XmlResourceParser parser,
+            ParseInput input) throws IOException, XmlPullParserException {
+        ParseResult<ParsedIntentInfo> result = ParsedMainComponentUtils.parseIntentFilter(activity,
+                pkg, resources, parser, visibleToEphemeral, true /*allowGlobs*/,
+                true /*allowAutoVerify*/, allowImplicitEphemeralVisibility,
+                true /*failOnNoActions*/, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+
+        ParsedIntentInfo intent = result.getResult();
+        if (intent != null) {
+            if (intent.isVisibleToInstantApp()) {
+                activity.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+            }
+            if (intent.isImplicitlyVisibleToInstantApp()) {
+                activity.flags |= ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP;
+            }
+        }
+
+        return input.success(intent);
+    }
+
+    private static int getActivityResizeMode(ParsingPackage pkg, TypedArray sa,
+            int screenOrientation) {
+        Boolean resizeableActivity = pkg.getResizeableActivity();
+
+        if (sa.hasValue(R.styleable.AndroidManifestActivity_resizeableActivity)
+                || resizeableActivity != null) {
+            // Activity or app explicitly set if it is resizeable or not;
+            if (sa.getBoolean(R.styleable.AndroidManifestActivity_resizeableActivity,
+                    resizeableActivity != null && resizeableActivity)) {
+                return ActivityInfo.RESIZE_MODE_RESIZEABLE;
+            } else {
+                return ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
+            }
+        }
+
+        if (pkg.isResizeableActivityViaSdkVersion()) {
+            // The activity or app didn't explicitly set the resizing option, however we want to
+            // make it resize due to the sdk version it is targeting.
+            return ActivityInfo.RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION;
+        }
+
+        // resize preference isn't set and target sdk version doesn't support resizing apps by
+        // default. For the app to be resizeable if it isn't fixed orientation or immersive.
+        if (ActivityInfo.isFixedOrientationPortrait(screenOrientation)) {
+            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY;
+        } else if (ActivityInfo.isFixedOrientationLandscape(screenOrientation)) {
+            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY;
+        } else if (screenOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
+            return ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION;
+        } else {
+            return ActivityInfo.RESIZE_MODE_FORCE_RESIZEABLE;
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ActivityInfo.WindowLayout> parseLayout(Resources res,
+            AttributeSet attrs, ParseInput input) {
+        TypedArray sw = res.obtainAttributes(attrs, R.styleable.AndroidManifestLayout);
+        try {
+            int width = -1;
+            float widthFraction = -1f;
+            int height = -1;
+            float heightFraction = -1f;
+            final int widthType = sw.getType(R.styleable.AndroidManifestLayout_defaultWidth);
+            if (widthType == TypedValue.TYPE_FRACTION) {
+                widthFraction = sw.getFraction(R.styleable.AndroidManifestLayout_defaultWidth, 1, 1,
+                        -1);
+            } else if (widthType == TypedValue.TYPE_DIMENSION) {
+                width = sw.getDimensionPixelSize(R.styleable.AndroidManifestLayout_defaultWidth,
+                        -1);
+            }
+            final int heightType = sw.getType(R.styleable.AndroidManifestLayout_defaultHeight);
+            if (heightType == TypedValue.TYPE_FRACTION) {
+                heightFraction = sw.getFraction(R.styleable.AndroidManifestLayout_defaultHeight, 1,
+                        1, -1);
+            } else if (heightType == TypedValue.TYPE_DIMENSION) {
+                height = sw.getDimensionPixelSize(R.styleable.AndroidManifestLayout_defaultHeight,
+                        -1);
+            }
+            int gravity = sw.getInt(R.styleable.AndroidManifestLayout_gravity, Gravity.CENTER);
+            int minWidth = sw.getDimensionPixelSize(R.styleable.AndroidManifestLayout_minWidth, -1);
+            int minHeight = sw.getDimensionPixelSize(R.styleable.AndroidManifestLayout_minHeight,
+                    -1);
+            return input.success(new ActivityInfo.WindowLayout(width, widthFraction, height,
+                    heightFraction, gravity, minWidth, minHeight));
+        } finally {
+            sw.recycle();
+        }
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponent.java b/core/java/android/content/pm/parsing/component/ParsedComponent.java
new file mode 100644
index 0000000..098d620
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedComponent.java
@@ -0,0 +1,208 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.CallSuper;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** @hide */
+public abstract class ParsedComponent implements Parcelable {
+
+    private static ParsedIntentInfo.ListParceler sForIntentInfos = Parcelling.Cache.getOrCreate(
+            ParsedIntentInfo.ListParceler.class);
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String name;
+    int icon;
+    int labelRes;
+    @Nullable
+    CharSequence nonLocalizedLabel;
+    int logo;
+    int banner;
+    int descriptionRes;
+
+    // TODO(b/135203078): Replace flags with individual booleans, scoped by subclass
+    int flags;
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String packageName;
+
+    @Nullable
+    @DataClass.PluralOf("intent")
+    @DataClass.ParcelWith(ParsedIntentInfo.ListParceler.class)
+    private List<ParsedIntentInfo> intents;
+
+    private ComponentName componentName;
+
+    @Nullable
+    protected Bundle metaData;
+
+    ParsedComponent() {
+
+    }
+
+    @SuppressWarnings("IncompleteCopyConstructor")
+    public ParsedComponent(ParsedComponent other) {
+        this.metaData = other.metaData;
+        this.name = other.name;
+        this.icon = other.getIcon();
+        this.labelRes = other.getLabelRes();
+        this.nonLocalizedLabel = other.getNonLocalizedLabel();
+        this.logo = other.getLogo();
+        this.banner = other.getBanner();
+
+        this.descriptionRes = other.getDescriptionRes();
+
+        this.flags = other.getFlags();
+
+        this.setPackageName(other.packageName);
+        this.intents = new ArrayList<>(other.getIntents());
+    }
+
+    public void addIntent(ParsedIntentInfo intent) {
+        this.intents = CollectionUtils.add(this.intents, intent);
+    }
+
+    @NonNull
+    public List<ParsedIntentInfo> getIntents() {
+        return intents != null ? intents : Collections.emptyList();
+    }
+
+    public ParsedComponent setName(String name) {
+        this.name = TextUtils.safeIntern(name);
+        return this;
+    }
+
+    @CallSuper
+    public void setPackageName(@NonNull String packageName) {
+        this.packageName = TextUtils.safeIntern(packageName);
+        //noinspection ConstantConditions
+        this.componentName = null;
+
+        // Note: this method does not edit name (which can point to a class), because this package
+        // name change is not changing the package in code, but the identifier used by the system.
+    }
+
+    @NonNull
+    public ComponentName getComponentName() {
+        if (componentName == null) {
+            componentName = new ComponentName(getPackageName(), getName());
+        }
+        return componentName;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        sForString.parcel(this.name, dest, flags);
+        dest.writeInt(this.getIcon());
+        dest.writeInt(this.getLabelRes());
+        dest.writeCharSequence(this.getNonLocalizedLabel());
+        dest.writeInt(this.getLogo());
+        dest.writeInt(this.getBanner());
+        dest.writeInt(this.getDescriptionRes());
+        dest.writeInt(this.getFlags());
+        sForString.parcel(this.packageName, dest, flags);
+        sForIntentInfos.parcel(this.getIntents(), dest, flags);
+        dest.writeBundle(this.metaData);
+    }
+
+    protected ParsedComponent(Parcel in) {
+        // We use the boot classloader for all classes that we load.
+        final ClassLoader boot = Object.class.getClassLoader();
+        //noinspection ConstantConditions
+        this.name = sForString.unparcel(in);
+        this.icon = in.readInt();
+        this.labelRes = in.readInt();
+        this.nonLocalizedLabel = in.readCharSequence();
+        this.logo = in.readInt();
+        this.banner = in.readInt();
+        this.descriptionRes = in.readInt();
+        this.flags = in.readInt();
+        //noinspection ConstantConditions
+        this.packageName = sForString.unparcel(in);
+        this.intents = sForIntentInfos.unparcel(in);
+        this.metaData = in.readBundle(boot);
+    }
+
+    @NonNull
+    public String getName() {
+        return name;
+    }
+
+    public int getIcon() {
+        return icon;
+    }
+
+    public int getLabelRes() {
+        return labelRes;
+    }
+
+    @Nullable
+    public CharSequence getNonLocalizedLabel() {
+        return nonLocalizedLabel;
+    }
+
+    public int getLogo() {
+        return logo;
+    }
+
+    public int getBanner() {
+        return banner;
+    }
+
+    public int getDescriptionRes() {
+        return descriptionRes;
+    }
+
+    public int getFlags() {
+        return flags;
+    }
+
+    @NonNull
+    public String getPackageName() {
+        return packageName;
+    }
+
+    @Nullable
+    public Bundle getMetaData() {
+        return metaData;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
new file mode 100644
index 0000000..b37b617
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedComponentUtils.java
@@ -0,0 +1,100 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.TypedValue;
+
+import com.android.internal.annotations.VisibleForTesting;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+/** @hide */
+class ParsedComponentUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    static <Component extends ParsedComponent> ParseResult<Component> parseComponent(
+            Component component, String tag, ParsingPackage pkg, TypedArray array,
+            boolean useRoundIcon, ParseInput input, int bannerAttr,
+            @Nullable Integer descriptionAttr, int iconAttr, int labelAttr, int logoAttr,
+            int nameAttr, int roundIconAttr) {
+        String name = array.getNonConfigurationString(nameAttr, 0);
+        if (TextUtils.isEmpty(name)) {
+            return input.error(tag + " does not specify android:name");
+        }
+
+        String packageName = pkg.getPackageName();
+        String className = ParsingUtils.buildClassName(packageName, name);
+        if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(className)) {
+            return input.error(tag + " invalid android:name");
+        }
+
+        //noinspection ConstantConditions; null check done above with isEmpty
+        component.setName(className);
+        component.setPackageName(packageName);
+
+        if (useRoundIcon) {
+            component.icon = array.getResourceId(roundIconAttr, 0);
+        }
+
+        if (component.icon == 0) {
+            component.icon = array.getResourceId(iconAttr, 0);
+        }
+
+        component.logo = array.getResourceId(logoAttr, 0);
+        component.banner = array.getResourceId(bannerAttr, 0);
+
+        if (descriptionAttr != null) {
+            component.descriptionRes = array.getResourceId(descriptionAttr, 0);
+        }
+
+        TypedValue v = array.peekValue(labelAttr);
+        if (v != null) {
+            component.labelRes = v.resourceId;
+            if (v.resourceId == 0) {
+                component.nonLocalizedLabel = v.coerceToString();
+            }
+        }
+
+        return input.success(component);
+    }
+
+    static ParseResult<Bundle> addMetaData(ParsedComponent component, ParsingPackage pkg,
+            Resources resources, XmlResourceParser parser, ParseInput input) {
+        ParseResult<Bundle> result = ParsingPackageUtils.parseMetaData(pkg, resources,
+                parser, component.metaData, input);
+        if (result.isError()) {
+            return input.error(result);
+        }
+        Bundle bundle = result.getResult();
+        component.metaData = bundle;
+        return input.success(bundle);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedFeature.java b/core/java/android/content/pm/parsing/component/ParsedFeature.java
new file mode 100644
index 0000000..b8a9098
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedFeature.java
@@ -0,0 +1,229 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.StringRes;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.DataClass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A {@link android.R.styleable#AndroidManifestFeature &lt;feature&gt;} tag parsed from the
+ * manifest.
+ *
+ * @hide
+ */
+@DataClass(genAidl = false)
+public class ParsedFeature implements Parcelable {
+    /** Maximum length of featureId */
+    public static final int MAX_FEATURE_ID_LEN = 50;
+
+    /** Maximum amount of features per package */
+    private static final int MAX_NUM_FEATURES = 1000;
+
+    /** Id of the feature */
+    public final @NonNull String id;
+
+    /** User visible label fo the feature */
+    public final @StringRes int label;
+
+    /** Ids of previously declared features this feature inherits from */
+    public final @NonNull List<String> inheritFrom;
+
+    /**
+     * @return Is this set of features a valid combination for a single package?
+     */
+    public static boolean isCombinationValid(@Nullable List<ParsedFeature> features) {
+        if (features == null) {
+            return true;
+        }
+
+        ArraySet<String> featureIds = new ArraySet<>(features.size());
+        ArraySet<String> inheritFromFeatureIds = new ArraySet<>();
+
+        int numFeatures = features.size();
+        if (numFeatures > MAX_NUM_FEATURES) {
+            return false;
+        }
+
+        for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+            boolean wasAdded = featureIds.add(features.get(featureNum).id);
+            if (!wasAdded) {
+                // feature id is not unique
+                return false;
+            }
+        }
+
+        for (int featureNum = 0; featureNum < numFeatures; featureNum++) {
+            ParsedFeature feature = features.get(featureNum);
+
+            int numInheritFrom = feature.inheritFrom.size();
+            for (int inheritFromNum = 0; inheritFromNum < numInheritFrom; inheritFromNum++) {
+                String inheritFrom = feature.inheritFrom.get(inheritFromNum);
+
+                if (featureIds.contains(inheritFrom)) {
+                    // Cannot inherit from a feature that is still defined
+                    return false;
+                }
+
+                boolean wasAdded = inheritFromFeatureIds.add(inheritFrom);
+                if (!wasAdded) {
+                    // inheritFrom is not unique
+                    return false;
+                }
+            }
+        }
+
+        return true;
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedFeature.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @android.annotation.IntDef(prefix = "MAX_", value = {
+        MAX_FEATURE_ID_LEN,
+        MAX_NUM_FEATURES
+    })
+    @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.SOURCE)
+    @DataClass.Generated.Member
+    public @interface Max {}
+
+    @DataClass.Generated.Member
+    public static String maxToString(@Max int value) {
+        switch (value) {
+            case MAX_FEATURE_ID_LEN:
+                    return "MAX_FEATURE_ID_LEN";
+            case MAX_NUM_FEATURES:
+                    return "MAX_NUM_FEATURES";
+            default: return Integer.toHexString(value);
+        }
+    }
+
+    /**
+     * Creates a new ParsedFeature.
+     *
+     * @param id
+     *   Id of the feature
+     * @param label
+     *   User visible label fo the feature
+     * @param inheritFrom
+     *   Ids of previously declared features this feature inherits from
+     */
+    @DataClass.Generated.Member
+    public ParsedFeature(
+            @NonNull String id,
+            @StringRes int label,
+            @NonNull List<String> inheritFrom) {
+        this.id = id;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, id);
+        this.label = label;
+        com.android.internal.util.AnnotationValidations.validate(
+                StringRes.class, null, label);
+        this.inheritFrom = inheritFrom;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, inheritFrom);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeString(id);
+        dest.writeInt(label);
+        dest.writeStringList(inheritFrom);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected ParsedFeature(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        String _id = in.readString();
+        int _label = in.readInt();
+        List<String> _inheritFrom = new ArrayList<>();
+        in.readStringList(_inheritFrom);
+
+        this.id = _id;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, id);
+        this.label = _label;
+        com.android.internal.util.AnnotationValidations.validate(
+                StringRes.class, null, label);
+        this.inheritFrom = _inheritFrom;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, inheritFrom);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ParsedFeature> CREATOR
+            = new Parcelable.Creator<ParsedFeature>() {
+        @Override
+        public ParsedFeature[] newArray(int size) {
+            return new ParsedFeature[size];
+        }
+
+        @Override
+        public ParsedFeature createFromParcel(@NonNull Parcel in) {
+            return new ParsedFeature(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1581379861853L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedFeature.java",
+            inputSignatures = "public static final  int MAX_FEATURE_ID_LEN\nprivate static final  int MAX_NUM_FEATURES\npublic final @android.annotation.NonNull java.lang.String id\npublic final @android.annotation.StringRes int label\npublic final @android.annotation.NonNull java.util.List<java.lang.String> inheritFrom\npublic static  boolean isCombinationValid(java.util.List<android.content.pm.parsing.component.ParsedFeature>)\nclass ParsedFeature extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genAidl=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java b/core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java
new file mode 100644
index 0000000..fb52801
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedFeatureUtils.java
@@ -0,0 +1,109 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+
+import com.android.internal.R;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+/** @hide */
+public class ParsedFeatureUtils {
+
+    @NonNull
+    public static ParseResult<ParsedFeature> parseFeature(Resources res, XmlResourceParser parser,
+            ParseInput input) throws IOException, XmlPullParserException {
+        String featureId;
+        int label;
+        List<String> inheritFrom = null;
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeature);
+        if (sa == null) {
+            return input.error("<feature> could not be parsed");
+        }
+
+        try {
+            featureId = sa.getNonConfigurationString(R.styleable.AndroidManifestFeature_featureId,
+                    0);
+            if (featureId == null) {
+                return input.error("<featureId> does not specify android:featureId");
+            }
+            if (featureId.length() > ParsedFeature.MAX_FEATURE_ID_LEN) {
+                return input.error("<featureId> is too long. Max length is "
+                        + ParsedFeature.MAX_FEATURE_ID_LEN);
+            }
+
+            label = sa.getResourceId(R.styleable.AndroidManifestFeature_label, 0);
+            if (label == Resources.ID_NULL) {
+                return input.error("<featureId> does not specify android:label");
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        int type;
+        final int innerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals("inherit-from")) {
+                sa = res.obtainAttributes(parser, R.styleable.AndroidManifestFeatureInheritFrom);
+                if (sa == null) {
+                    return input.error("<inherit-from> could not be parsed");
+                }
+
+                try {
+                    String inheritFromId = sa.getNonConfigurationString(
+                            R.styleable.AndroidManifestFeatureInheritFrom_featureId,0);
+
+                    if (inheritFrom == null) {
+                        inheritFrom = new ArrayList<>();
+                    }
+                    inheritFrom.add(inheritFromId);
+                } finally {
+                    sa.recycle();
+                }
+            } else {
+                return input.error("Bad element under <feature>: " + tagName);
+            }
+        }
+
+        if (inheritFrom == null) {
+            inheritFrom = Collections.emptyList();
+        } else {
+            ((ArrayList) inheritFrom).trimToSize();
+        }
+
+        return input.success(new ParsedFeature(featureId, label, inheritFrom));
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
new file mode 100644
index 0000000..396a145
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedInstrumentation.java
@@ -0,0 +1,116 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide */
+public class ParsedInstrumentation extends ParsedComponent {
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String targetPackage;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String targetProcesses;
+    boolean handleProfiling;
+    boolean functionalTest;
+
+    public ParsedInstrumentation() {
+    }
+
+    public void setTargetPackage(@Nullable String targetPackage) {
+        this.targetPackage = TextUtils.safeIntern(targetPackage);
+    }
+
+    public void setTargetProcesses(@Nullable String targetProcesses) {
+        this.targetProcesses = TextUtils.safeIntern(targetProcesses);
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("Instrumentation{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        ComponentName.appendShortString(sb, getPackageName(), getName());
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        sForString.parcel(this.targetPackage, dest, flags);
+        sForString.parcel(this.targetProcesses, dest, flags);
+        dest.writeBoolean(this.handleProfiling);
+        dest.writeBoolean(this.functionalTest);
+    }
+
+    protected ParsedInstrumentation(Parcel in) {
+        super(in);
+        this.targetPackage = sForString.unparcel(in);
+        this.targetProcesses = sForString.unparcel(in);
+        this.handleProfiling = in.readByte() != 0;
+        this.functionalTest = in.readByte() != 0;
+    }
+
+    public static final Parcelable.Creator<ParsedInstrumentation> CREATOR =
+            new Parcelable.Creator<ParsedInstrumentation>() {
+                @Override
+                public ParsedInstrumentation createFromParcel(Parcel source) {
+                    return new ParsedInstrumentation(source);
+                }
+
+                @Override
+                public ParsedInstrumentation[] newArray(int size) {
+                    return new ParsedInstrumentation[size];
+                }
+            };
+
+    @Nullable
+    public String getTargetPackage() {
+        return targetPackage;
+    }
+
+    @Nullable
+    public String getTargetProcesses() {
+        return targetProcesses;
+    }
+
+    public boolean isHandleProfiling() {
+        return handleProfiling;
+    }
+
+    public boolean isFunctionalTest() {
+        return functionalTest;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedInstrumentationUtils.java b/core/java/android/content/pm/parsing/component/ParsedInstrumentationUtils.java
new file mode 100644
index 0000000..89645fc
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedInstrumentationUtils.java
@@ -0,0 +1,74 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+
+import com.android.internal.R;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+public class ParsedInstrumentationUtils {
+
+    @NonNull
+    public static ParseResult<ParsedInstrumentation> parseInstrumentation(ParsingPackage pkg,
+            Resources res, XmlResourceParser parser, boolean useRoundIcon,
+            ParseInput input) throws IOException, XmlPullParserException {
+        ParsedInstrumentation
+                instrumentation = new ParsedInstrumentation();
+        String tag = "<" + parser.getName() + ">";
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestInstrumentation);
+        try {
+            ParseResult<ParsedInstrumentation> result = ParsedComponentUtils.parseComponent(
+                    instrumentation, tag, pkg, sa, useRoundIcon, input,
+                    R.styleable.AndroidManifestInstrumentation_banner,
+                    null /*descriptionAttr*/,
+                    R.styleable.AndroidManifestInstrumentation_icon,
+                    R.styleable.AndroidManifestInstrumentation_label,
+                    R.styleable.AndroidManifestInstrumentation_logo,
+                    R.styleable.AndroidManifestInstrumentation_name,
+                    R.styleable.AndroidManifestInstrumentation_roundIcon);
+            if (result.isError()) {
+                return result;
+            }
+
+            // @formatter:off
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            instrumentation.setTargetPackage(sa.getNonResourceString(R.styleable.AndroidManifestInstrumentation_targetPackage));
+            instrumentation.setTargetProcesses(sa.getNonResourceString(R.styleable.AndroidManifestInstrumentation_targetProcesses));
+            instrumentation.handleProfiling = sa.getBoolean(R.styleable.AndroidManifestInstrumentation_handleProfiling, false);
+            instrumentation.functionalTest = sa.getBoolean(R.styleable.AndroidManifestInstrumentation_functionalTest, false);
+            // @formatter:on
+        } finally {
+            sa.recycle();
+        }
+
+        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, instrumentation,
+                input);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
new file mode 100644
index 0000000..0ba92cc
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfo.java
@@ -0,0 +1,200 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.Nullable;
+import android.content.IntentFilter;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Pair;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** @hide **/
+public final class ParsedIntentInfo extends IntentFilter {
+
+    public static final Parceler PARCELER = new Parceler();
+
+    public static class Parceler implements Parcelling<ParsedIntentInfo> {
+
+        @Override
+        public void parcel(ParsedIntentInfo item, Parcel dest, int parcelFlags) {
+            item.writeIntentInfoToParcel(dest, parcelFlags);
+        }
+
+        @Override
+        public ParsedIntentInfo unparcel(Parcel source) {
+            return new ParsedIntentInfo(source);
+        }
+    }
+
+    public static class ListParceler implements Parcelling<List<ParsedIntentInfo>> {
+
+        /**
+         * <p>
+         * Implementation note: The serialized form for the intent list also contains the name
+         * of the concrete class that's stored in the list, and assumes that every element of the
+         * list is of the same type. This is very similar to the original parcelable mechanism.
+         * We cannot use that directly because IntentInfo extends IntentFilter, which is parcelable
+         * and is public API. It also declares Parcelable related methods as final which means
+         * we can't extend them. The approach of using composition instead of inheritance leads to
+         * a large set of cascading changes in the PackageManagerService, which seem undesirable.
+         *
+         * <p>
+         * <b>WARNING: </b> The list of objects returned by this function might need to be fixed up
+         * to make sure their owner fields are consistent. See {@code fixupOwner}.
+         */
+        @Override
+        public void parcel(List<ParsedIntentInfo> item, Parcel dest, int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            final int size = item.size();
+            dest.writeInt(size);
+
+            for (int index = 0; index < size; index++) {
+                PARCELER.parcel(item.get(index), dest, parcelFlags);
+            }
+        }
+
+        @Override
+        public List<ParsedIntentInfo> unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            if (size == 0) {
+                return new ArrayList<>(0);
+            }
+
+            final ArrayList<ParsedIntentInfo> intentsList = new ArrayList<>(size);
+            for (int i = 0; i < size; ++i) {
+                intentsList.add(PARCELER.unparcel(source));
+            }
+
+            return intentsList;
+        }
+    }
+
+    public static class StringPairListParceler implements Parcelling<List<Pair<String, ParsedIntentInfo>>> {
+
+        @Override
+        public void parcel(List<Pair<String, ParsedIntentInfo>> item, Parcel dest,
+                int parcelFlags) {
+            if (item == null) {
+                dest.writeInt(-1);
+                return;
+            }
+
+            final int size = item.size();
+            dest.writeInt(size);
+
+            for (int index = 0; index < size; index++) {
+                Pair<String, ParsedIntentInfo> pair = item.get(index);
+                dest.writeString(pair.first);
+                PARCELER.parcel(pair.second, dest, parcelFlags);
+            }
+        }
+
+        @Override
+        public List<Pair<String, ParsedIntentInfo>> unparcel(Parcel source) {
+            int size = source.readInt();
+            if (size == -1) {
+                return null;
+            }
+
+            if (size == 0) {
+                return new ArrayList<>(0);
+            }
+
+            final List<Pair<String, ParsedIntentInfo>> list = new ArrayList<>(size);
+            for (int i = 0; i < size; ++i) {
+                list.add(Pair.create(source.readString(), PARCELER.unparcel(source)));
+            }
+
+            return list;
+        }
+    }
+
+    boolean hasDefault;
+    int labelRes;
+    @Nullable
+    CharSequence nonLocalizedLabel;
+    int icon;
+
+    public ParsedIntentInfo() {
+    }
+
+    public ParsedIntentInfo(Parcel in) {
+        super(in);
+        hasDefault = in.readBoolean();
+        labelRes = in.readInt();
+        nonLocalizedLabel = in.readCharSequence();
+        icon = in.readInt();
+    }
+
+    public void writeIntentInfoToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeBoolean(hasDefault);
+        dest.writeInt(labelRes);
+        dest.writeCharSequence(nonLocalizedLabel);
+        dest.writeInt(icon);
+    }
+
+    public String toString() {
+        return "ProviderIntentInfo{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + '}';
+    }
+
+    public static final Parcelable.Creator<ParsedIntentInfo> CREATOR =
+            new Parcelable.Creator<ParsedIntentInfo>() {
+                @Override
+                public ParsedIntentInfo createFromParcel(Parcel source) {
+                    return new ParsedIntentInfo(source);
+                }
+
+                @Override
+                public ParsedIntentInfo[] newArray(int size) {
+                    return new ParsedIntentInfo[size];
+                }
+            };
+
+    public boolean isHasDefault() {
+        return hasDefault;
+    }
+
+    public int getLabelRes() {
+        return labelRes;
+    }
+
+    @Nullable
+    public CharSequence getNonLocalizedLabel() {
+        return nonLocalizedLabel;
+    }
+
+    public int getIcon() {
+        return icon;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
new file mode 100644
index 0000000..a7b950b
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedIntentInfoUtils.java
@@ -0,0 +1,249 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageParser;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.PatternMatcher;
+import android.text.TextUtils;
+import android.util.Slog;
+import android.util.TypedValue;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Iterator;
+
+/** @hide */
+public class ParsedIntentInfoUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    public static ParseResult<ParsedIntentInfo> parseIntentInfo(String className,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, boolean allowGlobs,
+            boolean allowAutoVerify, ParseInput input)
+            throws XmlPullParserException, IOException {
+        ParsedIntentInfo intentInfo = new ParsedIntentInfo();
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestIntentFilter);
+        try {
+            intentInfo.setPriority(sa.getInt(R.styleable.AndroidManifestIntentFilter_priority, 0));
+            intentInfo.setOrder(sa.getInt(R.styleable.AndroidManifestIntentFilter_order, 0));
+
+            TypedValue v = sa.peekValue(R.styleable.AndroidManifestIntentFilter_label);
+            if (v != null) {
+                intentInfo.labelRes = v.resourceId;
+                if (v.resourceId == 0) {
+                    intentInfo.nonLocalizedLabel = v.coerceToString();
+                }
+            }
+
+            if (PackageParser.sUseRoundIcon) {
+                intentInfo.icon = sa.getResourceId(
+                        R.styleable.AndroidManifestIntentFilter_roundIcon, 0);
+            }
+
+            if (intentInfo.icon == 0) {
+                intentInfo.icon = sa.getResourceId(R.styleable.AndroidManifestIntentFilter_icon, 0);
+            }
+
+            if (allowAutoVerify) {
+                intentInfo.setAutoVerify(sa.getBoolean(
+                        R.styleable.AndroidManifestIntentFilter_autoVerify,
+                        false));
+            }
+        } finally {
+            sa.recycle();
+        }
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult result;
+            String nodeName = parser.getName();
+            switch (nodeName) {
+                case "action": {
+                    String value = parser.getAttributeValue(PackageParser.ANDROID_RESOURCES,
+                            "name");
+                    if (TextUtils.isEmpty(value)) {
+                        result = input.error("No value supplied for <android:name>");
+                    } else {
+                        intentInfo.addAction(value);
+                        result = input.success(null);
+                    }
+                    break;
+                }
+                case "category": {
+                    String value = parser.getAttributeValue(PackageParser.ANDROID_RESOURCES,
+                            "name");
+                    if (TextUtils.isEmpty(value)) {
+                        result = input.error("No value supplied for <android:name>");
+                    } else {
+                        intentInfo.addCategory(value);
+                        result = input.success(null);
+                    }
+                    break;
+                }
+                case "data":
+                    result = parseData(intentInfo, res, parser, allowGlobs, input);
+                    break;
+                default:
+                    result = ParsingUtils.unknownTag("<intent-filter>", pkg, parser, input);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        intentInfo.hasDefault = intentInfo.hasCategory(Intent.CATEGORY_DEFAULT);
+
+        if (PackageParser.DEBUG_PARSER) {
+            final StringBuilder cats = new StringBuilder("Intent d=");
+            cats.append(intentInfo.isHasDefault());
+            cats.append(", cat=");
+
+            final Iterator<String> it = intentInfo.categoriesIterator();
+            if (it != null) {
+                while (it.hasNext()) {
+                    cats.append(' ');
+                    cats.append(it.next());
+                }
+            }
+            Slog.d(TAG, cats.toString());
+        }
+
+        return input.success(intentInfo);
+    }
+
+    @NonNull
+    private static ParseResult<ParsedIntentInfo> parseData(ParsedIntentInfo intentInfo,
+            Resources resources, XmlResourceParser parser, boolean allowGlobs, ParseInput input) {
+        TypedArray sa = resources.obtainAttributes(parser, R.styleable.AndroidManifestData);
+        try {
+            String str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_mimeType, 0);
+            if (str != null) {
+                try {
+                    intentInfo.addDataType(str);
+                } catch (IntentFilter.MalformedMimeTypeException e) {
+                    return input.error(e.toString());
+                }
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_mimeGroup, 0);
+            if (str != null) {
+                intentInfo.addMimeGroup(str);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_scheme, 0);
+            if (str != null) {
+                intentInfo.addDataScheme(str);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_ssp, 0);
+            if (str != null) {
+                intentInfo.addDataSchemeSpecificPart(str,
+                        PatternMatcher.PATTERN_LITERAL);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_sspPrefix, 0);
+            if (str != null) {
+                intentInfo.addDataSchemeSpecificPart(str,
+                        PatternMatcher.PATTERN_PREFIX);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_sspPattern, 0);
+            if (str != null) {
+                if (!allowGlobs) {
+                    return input.error(
+                            "sspPattern not allowed here; ssp must be literal");
+                }
+                intentInfo.addDataSchemeSpecificPart(str,
+                        PatternMatcher.PATTERN_SIMPLE_GLOB);
+            }
+
+            String host = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_host, 0);
+            String port = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_port, 0);
+            if (host != null) {
+                intentInfo.addDataAuthority(host, port);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_path, 0);
+            if (str != null) {
+                intentInfo.addDataPath(str, PatternMatcher.PATTERN_LITERAL);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_pathPrefix, 0);
+            if (str != null) {
+                intentInfo.addDataPath(str, PatternMatcher.PATTERN_PREFIX);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_pathPattern, 0);
+            if (str != null) {
+                if (!allowGlobs) {
+                    return input.error(
+                            "pathPattern not allowed here; path must be literal");
+                }
+                intentInfo.addDataPath(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
+            }
+
+            str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestData_pathAdvancedPattern, 0);
+            if (str != null) {
+                if (!allowGlobs) {
+                    return input.error(
+                            "pathAdvancedPattern not allowed here; path must be literal");
+                }
+                intentInfo.addDataPath(str, PatternMatcher.PATTERN_ADVANCED_GLOB);
+            }
+
+            return input.success(null);
+        } finally {
+            sa.recycle();
+        }
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponent.java b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java
new file mode 100644
index 0000000..59e9a84
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedMainComponent.java
@@ -0,0 +1,153 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide */
+public class ParsedMainComponent extends ParsedComponent {
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String processName;
+    boolean directBootAware;
+    boolean enabled = true;
+    boolean exported;
+    int order;
+
+    @Nullable
+    String splitName;
+
+    public ParsedMainComponent() {
+    }
+
+    public ParsedMainComponent(ParsedMainComponent other) {
+        super(other);
+        this.processName = other.processName;
+        this.directBootAware = other.directBootAware;
+        this.enabled = other.enabled;
+        this.exported = other.exported;
+        this.order = other.order;
+        this.splitName = other.splitName;
+    }
+
+    public ParsedMainComponent setProcessName(String processName) {
+        this.processName = TextUtils.safeIntern(processName);
+        return this;
+    }
+
+    public ParsedMainComponent setEnabled(boolean enabled) {
+        this.enabled = enabled;
+        return this;
+    }
+
+    /**
+     * A main component's name is a class name. This makes code slightly more readable.
+     */
+    public String getClassName() {
+        return getName();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        sForString.parcel(this.processName, dest, flags);
+        dest.writeBoolean(this.directBootAware);
+        dest.writeBoolean(this.enabled);
+        dest.writeBoolean(this.exported);
+        dest.writeInt(this.order);
+        dest.writeString(this.splitName);
+    }
+
+    protected ParsedMainComponent(Parcel in) {
+        super(in);
+        this.processName = sForString.unparcel(in);
+        this.directBootAware = in.readBoolean();
+        this.enabled = in.readBoolean();
+        this.exported = in.readBoolean();
+        this.order = in.readInt();
+        this.splitName = in.readString();
+    }
+
+    public static final Parcelable.Creator<ParsedMainComponent> CREATOR =
+            new Parcelable.Creator<ParsedMainComponent>() {
+                @Override
+                public ParsedMainComponent createFromParcel(Parcel source) {
+                    return new ParsedMainComponent(source);
+                }
+
+                @Override
+                public ParsedMainComponent[] newArray(int size) {
+                    return new ParsedMainComponent[size];
+                }
+            };
+
+    @Nullable
+    public String getProcessName() {
+        return processName;
+    }
+
+    public boolean isDirectBootAware() {
+        return directBootAware;
+    }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public boolean isExported() {
+        return exported;
+    }
+
+    public int getOrder() {
+        return order;
+    }
+
+    @Nullable
+    public String getSplitName() {
+        return splitName;
+    }
+
+    public ParsedMainComponent setDirectBootAware(boolean value) {
+        directBootAware = value;
+        return this;
+    }
+
+    public ParsedMainComponent setExported(boolean value) {
+        exported = value;
+        return this;
+    }
+
+    public ParsedMainComponent setSplitName(@Nullable String value) {
+        splitName = value;
+        return this;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
new file mode 100644
index 0000000..6188f89
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedMainComponentUtils.java
@@ -0,0 +1,137 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.IntentFilter;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+class ParsedMainComponentUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    static <Component extends ParsedMainComponent> ParseResult<Component> parseMainComponent(
+            Component component, String tag, String[] separateProcesses, ParsingPackage pkg,
+            TypedArray array, int flags, boolean useRoundIcon, ParseInput input,
+            int bannerAttr, int descriptionAttr, @Nullable Integer directBootAwareAttr,
+            @Nullable Integer enabledAttr, int iconAttr, int labelAttr, int logoAttr, int nameAttr,
+            @Nullable Integer processAttr, int roundIconAttr, @Nullable Integer splitNameAttr) {
+        ParseResult<Component> result = ParsedComponentUtils.parseComponent(component, tag, pkg,
+                array, useRoundIcon, input, bannerAttr, descriptionAttr, iconAttr, labelAttr,
+                logoAttr, nameAttr, roundIconAttr);
+        if (result.isError()) {
+            return result;
+        }
+
+        if (directBootAwareAttr != null) {
+            component.directBootAware = array.getBoolean(directBootAwareAttr, false);
+            if (component.isDirectBootAware()) {
+                pkg.setPartiallyDirectBootAware(true);
+            }
+        }
+
+        if (enabledAttr != null) {
+            component.enabled = array.getBoolean(enabledAttr, true);
+        }
+
+        if (processAttr != null) {
+            CharSequence processName;
+            if (pkg.getTargetSdkVersion() >= Build.VERSION_CODES.FROYO) {
+                processName = array.getNonConfigurationString(processAttr,
+                        Configuration.NATIVE_CONFIG_VERSION);
+            } else {
+                // Some older apps have been seen to use a resource reference
+                // here that on older builds was ignored (with a warning).  We
+                // need to continue to do this for them so they don't break.
+                processName = array.getNonResourceString(processAttr);
+            }
+
+            // Backwards-compat, ignore error
+            ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName(
+                    pkg.getPackageName(), pkg.getProcessName(), processName, flags,
+                    separateProcesses, input);
+            if (processNameResult.isSuccess()) {
+                component.setProcessName(processNameResult.getResult());
+            } else {
+                // Backwards-compat, ignore error
+                processNameResult.ignoreError();
+            }
+        }
+
+        if (splitNameAttr != null) {
+            component.splitName = array.getNonConfigurationString(splitNameAttr, 0);
+        }
+
+        return input.success(component);
+    }
+
+    static ParseResult<ParsedIntentInfo> parseIntentFilter(
+            ParsedMainComponent mainComponent,
+            ParsingPackage pkg, Resources resources, XmlResourceParser parser,
+            boolean visibleToEphemeral, boolean allowGlobs, boolean allowAutoVerify,
+            boolean allowImplicitEphemeralVisibility, boolean failOnNoActions,
+            ParseInput input) throws IOException, XmlPullParserException {
+        ParseResult<ParsedIntentInfo> intentResult = ParsedIntentInfoUtils.parseIntentInfo(
+                mainComponent.getName(), pkg, resources, parser, allowGlobs,
+                allowAutoVerify, input);
+        if (intentResult.isError()) {
+            return input.error(intentResult);
+        }
+
+        ParsedIntentInfo intent = intentResult.getResult();
+        int actionCount = intent.countActions();
+        if (actionCount == 0 && failOnNoActions) {
+            Slog.w(TAG, "No actions in " + parser.getName() + " at " + pkg.getBaseCodePath() + " "
+                    + parser.getPositionDescription());
+            // Backward-compat, do not actually fail
+            return input.success(null);
+        }
+
+        int intentVisibility;
+        if (visibleToEphemeral) {
+            intentVisibility = IntentFilter.VISIBILITY_EXPLICIT;
+        } else if (allowImplicitEphemeralVisibility
+                && ComponentParseUtils.isImplicitlyExposedIntent(intent)){
+            intentVisibility = IntentFilter.VISIBILITY_IMPLICIT;
+        } else {
+            intentVisibility = IntentFilter.VISIBILITY_NONE;
+        }
+        intent.setVisibilityToInstantApp(intentVisibility);
+
+        return input.success(intentResult.getResult());
+    }
+
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermission.java b/core/java/android/content/pm/parsing/component/ParsedPermission.java
new file mode 100644
index 0000000..6c36ecb
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedPermission.java
@@ -0,0 +1,194 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.Nullable;
+import android.content.pm.PermissionInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide */
+public class ParsedPermission extends ParsedComponent {
+
+    @Nullable
+    String backgroundPermission;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String group;
+    int requestRes;
+    int protectionLevel;
+    boolean tree;
+    @Nullable
+    private ParsedPermissionGroup parsedPermissionGroup;
+
+    @VisibleForTesting
+    public ParsedPermission() {
+    }
+
+    public ParsedPermission(ParsedPermission other) {
+        super(other);
+        this.backgroundPermission = other.backgroundPermission;
+        this.group = other.group;
+        this.requestRes = other.requestRes;
+        this.protectionLevel = other.protectionLevel;
+        this.tree = other.tree;
+        this.parsedPermissionGroup = other.parsedPermissionGroup;
+    }
+
+    public ParsedPermission(ParsedPermission other, PermissionInfo pendingPermissionInfo,
+            String packageName, String name) {
+        this(other);
+
+        this.flags = pendingPermissionInfo.flags;
+        this.descriptionRes = pendingPermissionInfo.descriptionRes;
+
+        this.backgroundPermission = pendingPermissionInfo.backgroundPermission;
+        this.group = pendingPermissionInfo.group;
+        this.requestRes = pendingPermissionInfo.requestRes;
+        this.protectionLevel = pendingPermissionInfo.protectionLevel;
+
+        setName(name);
+        setPackageName(packageName);
+    }
+
+    public ParsedPermission setGroup(String group) {
+        this.group = TextUtils.safeIntern(group);
+        return this;
+    }
+
+    public ParsedPermission setFlags(int flags) {
+        this.flags = flags;
+        return this;
+    }
+
+    public boolean isRuntime() {
+        return getProtection() == PermissionInfo.PROTECTION_DANGEROUS;
+    }
+
+    public boolean isAppOp() {
+        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_APPOP) != 0;
+    }
+
+    @PermissionInfo.Protection
+    public int getProtection() {
+        return protectionLevel & PermissionInfo.PROTECTION_MASK_BASE;
+    }
+
+    public int getProtectionFlags() {
+        return protectionLevel & ~PermissionInfo.PROTECTION_MASK_BASE;
+    }
+
+    public int calculateFootprint() {
+        int size = getName().length();
+        if (getNonLocalizedLabel() != null) {
+            size += getNonLocalizedLabel().length();
+        }
+        return size;
+    }
+
+    public String toString() {
+        return "Permission{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + getName() + "}";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeString(this.backgroundPermission);
+        sForString.parcel(this.group, dest, flags);
+        dest.writeInt(this.requestRes);
+        dest.writeInt(this.protectionLevel);
+        dest.writeBoolean(this.tree);
+        dest.writeParcelable(this.parsedPermissionGroup, flags);
+    }
+
+    protected ParsedPermission(Parcel in) {
+        super(in);
+        // We use the boot classloader for all classes that we load.
+        final ClassLoader boot = Object.class.getClassLoader();
+        this.backgroundPermission = in.readString();
+        this.group = sForString.unparcel(in);
+        this.requestRes = in.readInt();
+        this.protectionLevel = in.readInt();
+        this.tree = in.readBoolean();
+        this.parsedPermissionGroup = in.readParcelable(boot);
+    }
+
+    public static final Parcelable.Creator<ParsedPermission> CREATOR =
+            new Parcelable.Creator<ParsedPermission>() {
+                @Override
+                public ParsedPermission createFromParcel(Parcel source) {
+                    return new ParsedPermission(source);
+                }
+
+                @Override
+                public ParsedPermission[] newArray(int size) {
+                    return new ParsedPermission[size];
+                }
+            };
+
+    @Nullable
+    public String getBackgroundPermission() {
+        return backgroundPermission;
+    }
+
+    @Nullable
+    public String getGroup() {
+        return group;
+    }
+
+    public int getRequestRes() {
+        return requestRes;
+    }
+
+    public int getProtectionLevel() {
+        return protectionLevel;
+    }
+
+    public boolean isTree() {
+        return tree;
+    }
+
+    @Nullable
+    public ParsedPermissionGroup getParsedPermissionGroup() {
+        return parsedPermissionGroup;
+    }
+
+    public ParsedPermission setProtectionLevel(int value) {
+        protectionLevel = value;
+        return this;
+    }
+
+    public ParsedPermission setParsedPermissionGroup(@Nullable ParsedPermissionGroup value) {
+        parsedPermissionGroup = value;
+        return this;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionGroup.java b/core/java/android/content/pm/parsing/component/ParsedPermissionGroup.java
new file mode 100644
index 0000000..741c00c
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedPermissionGroup.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing.component;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+
+/** @hide */
+public class ParsedPermissionGroup extends ParsedComponent {
+
+    int requestDetailResourceId;
+    int backgroundRequestResourceId;
+    int backgroundRequestDetailResourceId;
+    int requestRes;
+    int priority;
+
+    public void setPriority(int priority) {
+        this.priority = priority;
+    }
+
+    public String toString() {
+        return "PermissionGroup{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + getName() + "}";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(this.requestDetailResourceId);
+        dest.writeInt(this.backgroundRequestResourceId);
+        dest.writeInt(this.backgroundRequestDetailResourceId);
+        dest.writeInt(this.requestRes);
+        dest.writeInt(this.priority);
+    }
+
+    public ParsedPermissionGroup() {
+    }
+
+    protected ParsedPermissionGroup(Parcel in) {
+        super(in);
+        this.requestDetailResourceId = in.readInt();
+        this.backgroundRequestResourceId = in.readInt();
+        this.backgroundRequestDetailResourceId = in.readInt();
+        this.requestRes = in.readInt();
+        this.priority = in.readInt();
+    }
+
+    public static final Parcelable.Creator<ParsedPermissionGroup> CREATOR =
+            new Parcelable.Creator<ParsedPermissionGroup>() {
+                @Override
+                public ParsedPermissionGroup createFromParcel(Parcel source) {
+                    return new ParsedPermissionGroup(source);
+                }
+
+                @Override
+                public ParsedPermissionGroup[] newArray(int size) {
+                    return new ParsedPermissionGroup[size];
+                }
+            };
+
+    public int getRequestDetailResourceId() {
+        return requestDetailResourceId;
+    }
+
+    public int getBackgroundRequestResourceId() {
+        return backgroundRequestResourceId;
+    }
+
+    public int getBackgroundRequestDetailResourceId() {
+        return backgroundRequestDetailResourceId;
+    }
+
+    public int getRequestRes() {
+        return requestRes;
+    }
+
+    public int getPriority() {
+        return priority;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
new file mode 100644
index 0000000..1884a1e
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedPermissionUtils.java
@@ -0,0 +1,210 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.content.pm.PermissionInfo;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.Slog;
+
+import com.android.internal.R;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+public class ParsedPermissionUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    public static ParseResult<ParsedPermission> parsePermission(ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
+            throws IOException, XmlPullParserException {
+        String packageName = pkg.getPackageName();
+        ParsedPermission
+                permission = new ParsedPermission();
+        String tag = "<" + parser.getName() + ">";
+        final ParseResult<ParsedPermission> result;
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermission);
+        try {
+            result = ParsedComponentUtils.parseComponent(
+                    permission, tag, pkg, sa, useRoundIcon, input,
+                    R.styleable.AndroidManifestPermission_banner,
+                    R.styleable.AndroidManifestPermission_description,
+                    R.styleable.AndroidManifestPermission_icon,
+                    R.styleable.AndroidManifestPermission_label,
+                    R.styleable.AndroidManifestPermission_logo,
+                    R.styleable.AndroidManifestPermission_name,
+                    R.styleable.AndroidManifestPermission_roundIcon);
+            if (result.isError()) {
+                return result;
+            }
+
+            if (sa.hasValue(
+                    R.styleable.AndroidManifestPermission_backgroundPermission)) {
+                if ("android".equals(packageName)) {
+                    permission.backgroundPermission = sa.getNonResourceString(
+                            R.styleable
+                                    .AndroidManifestPermission_backgroundPermission);
+                } else {
+                    Slog.w(TAG, packageName + " defines a background permission. Only the "
+                            + "'android' package can do that.");
+                }
+            }
+
+            // Note: don't allow this value to be a reference to a resource
+            // that may change.
+            permission.setGroup(sa.getNonResourceString(
+                    R.styleable.AndroidManifestPermission_permissionGroup));
+
+            permission.requestRes = sa.getResourceId(
+                    R.styleable.AndroidManifestPermission_request, 0);
+
+            permission.protectionLevel = sa.getInt(
+                    R.styleable.AndroidManifestPermission_protectionLevel,
+                    PermissionInfo.PROTECTION_NORMAL);
+
+            permission.flags = sa.getInt(
+                    R.styleable.AndroidManifestPermission_permissionFlags, 0);
+
+            // For now only platform runtime permissions can be restricted
+            if (!permission.isRuntime() || !"android".equals(permission.getPackageName())) {
+                permission.flags &= ~PermissionInfo.FLAG_HARD_RESTRICTED;
+                permission.flags &= ~PermissionInfo.FLAG_SOFT_RESTRICTED;
+            } else {
+                // The platform does not get to specify conflicting permissions
+                if ((permission.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0
+                        && (permission.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0) {
+                    throw new IllegalStateException("Permission cannot be both soft and hard"
+                            + " restricted: " + permission.getName());
+                }
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        // TODO(b/135203078): This is impossible because of default value in above getInt
+        if (permission.protectionLevel == -1) {
+            return input.error("<permission> does not specify protectionLevel");
+        }
+
+        permission.protectionLevel = PermissionInfo.fixProtectionLevel(permission.protectionLevel);
+
+        if (permission.getProtectionFlags() != 0) {
+            if ((permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) == 0
+                    && (permission.protectionLevel & PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY)
+                    == 0
+                    && (permission.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE) !=
+                    PermissionInfo.PROTECTION_SIGNATURE) {
+                return input.error("<permission>  protectionLevel specifies a non-instant flag "
+                        + "but is not based on signature type");
+            }
+        }
+
+        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission, input);
+    }
+
+    @NonNull
+    public static ParseResult<ParsedPermission> parsePermissionTree(ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
+            throws IOException, XmlPullParserException {
+        ParsedPermission permission = new ParsedPermission();
+        String tag = "<" + parser.getName() + ">";
+        final ParseResult<ParsedPermission> result;
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionTree);
+        try {
+            result = ParsedComponentUtils.parseComponent(
+                    permission, tag, pkg, sa, useRoundIcon, input,
+                    R.styleable.AndroidManifestPermissionTree_banner,
+                    null /*descriptionAttr*/,
+                    R.styleable.AndroidManifestPermissionTree_icon,
+                    R.styleable.AndroidManifestPermissionTree_label,
+                    R.styleable.AndroidManifestPermissionTree_logo,
+                    R.styleable.AndroidManifestPermissionTree_name,
+                    R.styleable.AndroidManifestPermissionTree_roundIcon);
+            if (result.isError()) {
+                return result;
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        int index = permission.getName().indexOf('.');
+        if (index > 0) {
+            index = permission.getName().indexOf('.', index + 1);
+        }
+        if (index < 0) {
+            return input.error("<permission-tree> name has less than three segments: "
+                    + permission.getName());
+        }
+
+        permission.protectionLevel = PermissionInfo.PROTECTION_NORMAL;
+        permission.tree = true;
+
+        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permission,
+                input);
+    }
+
+    @NonNull
+    public static ParseResult<ParsedPermissionGroup> parsePermissionGroup(ParsingPackage pkg,
+            Resources res, XmlResourceParser parser, boolean useRoundIcon, ParseInput input)
+            throws IOException, XmlPullParserException {
+        ParsedPermissionGroup
+                permissionGroup = new ParsedPermissionGroup();
+        String tag = "<" + parser.getName() + ">";
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestPermissionGroup);
+        try {
+            ParseResult<ParsedPermissionGroup> result = ParsedComponentUtils.parseComponent(
+                    permissionGroup, tag, pkg, sa, useRoundIcon, input,
+                    R.styleable.AndroidManifestPermissionGroup_banner,
+                    R.styleable.AndroidManifestPermissionGroup_description,
+                    R.styleable.AndroidManifestPermissionGroup_icon,
+                    R.styleable.AndroidManifestPermissionGroup_label,
+                    R.styleable.AndroidManifestPermissionGroup_logo,
+                    R.styleable.AndroidManifestPermissionGroup_name,
+                    R.styleable.AndroidManifestPermissionGroup_roundIcon);
+            if (result.isError()) {
+                return result;
+            }
+
+            // @formatter:off
+            permissionGroup.requestDetailResourceId = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_requestDetail, 0);
+            permissionGroup.backgroundRequestResourceId = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_backgroundRequest, 0);
+            permissionGroup.backgroundRequestDetailResourceId = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_backgroundRequestDetail, 0);
+            permissionGroup.requestRes = sa.getResourceId(R.styleable.AndroidManifestPermissionGroup_request, 0);
+            permissionGroup.flags = sa.getInt(R.styleable.AndroidManifestPermissionGroup_permissionGroupFlags,0);
+            permissionGroup.priority = sa.getInt(R.styleable.AndroidManifestPermissionGroup_priority, 0);
+            // @formatter:on
+        } finally {
+            sa.recycle();
+        }
+
+        return ComponentParseUtils.parseAllMetaData(pkg, res, parser, tag, permissionGroup,
+                input);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcess.java b/core/java/android/content/pm/parsing/component/ParsedProcess.java
new file mode 100644
index 0000000..da7bf98
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedProcess.java
@@ -0,0 +1,166 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static java.util.Collections.emptySet;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+
+import java.util.Set;
+
+/** @hide */
+@DataClass(genGetters = true, genSetters = false, genParcelable = true, genAidl = false,
+        genBuilder = false)
+public class ParsedProcess implements Parcelable {
+
+    @NonNull
+    protected String name;
+    @NonNull
+    @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class)
+    protected Set<String> deniedPermissions = emptySet();
+
+    public ParsedProcess() {
+    }
+
+    public ParsedProcess(@NonNull ParsedProcess other) {
+        name = other.name;
+        deniedPermissions = new ArraySet<>(other.deniedPermissions);
+    }
+
+    public void addStateFrom(@NonNull ParsedProcess other) {
+        deniedPermissions = CollectionUtils.addAll(deniedPermissions, other.deniedPermissions);
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcess.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public ParsedProcess(
+            @NonNull String name,
+            @NonNull Set<String> deniedPermissions) {
+        this.name = name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, name);
+        this.deniedPermissions = deniedPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, deniedPermissions);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull String getName() {
+        return name;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull Set<String> getDeniedPermissions() {
+        return deniedPermissions;
+    }
+
+    @DataClass.Generated.Member
+    static Parcelling<Set<String>> sParcellingForDeniedPermissions =
+            Parcelling.Cache.get(
+                    Parcelling.BuiltIn.ForInternedStringSet.class);
+    static {
+        if (sParcellingForDeniedPermissions == null) {
+            sParcellingForDeniedPermissions = Parcelling.Cache.put(
+                    new Parcelling.BuiltIn.ForInternedStringSet());
+        }
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeString(name);
+        sParcellingForDeniedPermissions.parcel(deniedPermissions, dest, flags);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    protected ParsedProcess(@NonNull Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        String _name = in.readString();
+        Set<String> _deniedPermissions = sParcellingForDeniedPermissions.unparcel(in);
+
+        this.name = _name;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, name);
+        this.deniedPermissions = _deniedPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, deniedPermissions);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<ParsedProcess> CREATOR
+            = new Parcelable.Creator<ParsedProcess>() {
+        @Override
+        public ParsedProcess[] newArray(int size) {
+            return new ParsedProcess[size];
+        }
+
+        @Override
+        public ParsedProcess createFromParcel(@NonNull Parcel in) {
+            return new ParsedProcess(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1581452315946L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/android/content/pm/parsing/component/ParsedProcess.java",
+            inputSignatures = "protected @android.annotation.NonNull java.lang.String name\nprotected @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedStringSet.class) java.util.Set<java.lang.String> deniedPermissions\npublic  void addStateFrom(android.content.pm.parsing.component.ParsedProcess)\nclass ParsedProcess extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genGetters=true, genSetters=false, genParcelable=true, genAidl=false, genBuilder=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
new file mode 100644
index 0000000..4825066
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedProcessUtils.java
@@ -0,0 +1,212 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import android.annotation.NonNull;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import com.android.internal.R;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.XmlUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Set;
+
+/** @hide */
+public class ParsedProcessUtils {
+
+    private static final String TAG = ParsingUtils.TAG;
+
+    @NonNull
+    private static ParseResult<Set<String>> parseDenyPermission(Set<String> perms,
+            Resources res, XmlResourceParser parser, ParseInput input)
+            throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestDenyPermission);
+        try {
+            String perm = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestDenyPermission_name, 0);
+            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)) {
+                perms = CollectionUtils.add(perms, perm);
+            }
+        } finally {
+            sa.recycle();
+        }
+        XmlUtils.skipCurrentTag(parser);
+        return input.success(perms);
+    }
+
+    @NonNull
+    private static ParseResult<Set<String>> parseAllowPermission(Set<String> perms, Resources res,
+            XmlResourceParser parser, ParseInput input)
+            throws IOException, XmlPullParserException {
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestAllowPermission);
+        try {
+            String perm = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestAllowPermission_name, 0);
+            if (perm != null && perm.equals(android.Manifest.permission.INTERNET)) {
+                perms = CollectionUtils.remove(perms, perm);
+            }
+        } finally {
+            sa.recycle();
+        }
+        XmlUtils.skipCurrentTag(parser);
+        return input.success(perms);
+    }
+
+    @NonNull
+    private static ParseResult<ParsedProcess> parseProcess(Set<String> perms, String[] separateProcesses,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags,
+            ParseInput input) throws IOException, XmlPullParserException {
+        ParsedProcess proc = new ParsedProcess();
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProcess);
+        try {
+            if (perms != null) {
+                proc.deniedPermissions = new ArraySet<>(perms);
+            }
+
+            proc.name = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestProcess_process, 0);
+            ParseResult<String> processNameResult = ComponentParseUtils.buildProcessName(
+                    pkg.getPackageName(), pkg.getPackageName(), proc.name, flags, separateProcesses,
+                    input);
+            if (processNameResult.isError()) {
+                return input.error(processNameResult);
+            }
+
+            proc.name = processNameResult.getResult();
+
+            if (proc.name == null || proc.name.length() <= 0) {
+                return input.error("<process> does not specify android:process");
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        int type;
+        final int innerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            ParseResult<?> result;
+
+            String tagName = parser.getName();
+            switch (tagName) {
+                case "deny-permission":
+                    ParseResult<Set<String>> denyResult = parseDenyPermission(
+                            proc.deniedPermissions, res, parser, input);
+                    result = denyResult;
+                    if (denyResult.isSuccess()) {
+                        proc.deniedPermissions = denyResult.getResult();
+                    }
+                    break;
+                case "allow-permission":
+                    ParseResult<Set<String>> allowResult = parseAllowPermission(
+                            proc.deniedPermissions, res, parser, input);
+                    result = allowResult;
+                    if (allowResult.isSuccess()) {
+                        proc.deniedPermissions = allowResult.getResult();
+                    }
+                    break;
+                default:
+                    result = ParsingUtils.unknownTag("<process>", pkg, parser, input);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        return input.success(proc);
+    }
+
+    @NonNull
+    public static ParseResult<ArrayMap<String, ParsedProcess>> parseProcesses(
+            String[] separateProcesses, ParsingPackage pkg, Resources res,
+            XmlResourceParser parser, int flags, ParseInput input)
+            throws IOException, XmlPullParserException {
+        Set<String> deniedPerms = null;
+        ArrayMap<String, ParsedProcess> processes = new ArrayMap<>();
+
+        int type;
+        final int innerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > innerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            ParseResult<?> result;
+
+            String tagName = parser.getName();
+            switch (tagName) {
+                case "deny-permission":
+                    ParseResult<Set<String>> denyResult = parseDenyPermission(deniedPerms, res,
+                            parser, input);
+                    result = denyResult;
+                    if (denyResult.isSuccess()) {
+                        deniedPerms = denyResult.getResult();
+                    }
+                    break;
+                case "allow-permission":
+                    ParseResult<Set<String>> allowResult = parseAllowPermission(deniedPerms, res,
+                            parser, input);
+                    result = allowResult;
+                    if (allowResult.isSuccess()) {
+                        deniedPerms = allowResult.getResult();
+                    }
+                    break;
+                case "process":
+                    ParseResult<ParsedProcess> processResult = parseProcess(deniedPerms,
+                            separateProcesses, pkg, res, parser, flags, input);
+                    result = processResult;
+                    if (processResult.isSuccess()) {
+                        ParsedProcess process = processResult.getResult();
+                        if (processes.put(process.name, process) != null) {
+                            result = input.error(
+                                    "<process> specified existing name '" + process.name + "'");
+                        }
+                    }
+                    break;
+                default:
+                    result = ParsingUtils.unknownTag("<processes>", pkg, parser, input);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+
+        }
+
+        return input.success(processes);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProvider.java b/core/java/android/content/pm/parsing/component/ParsedProvider.java
new file mode 100644
index 0000000..d2c531d
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedProvider.java
@@ -0,0 +1,195 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.content.pm.PathPermission;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.PatternMatcher;
+import android.text.TextUtils;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide **/
+public class ParsedProvider extends ParsedMainComponent {
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String authority;
+    boolean syncable;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String readPermission;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String writePermission;
+    boolean grantUriPermissions;
+    boolean forceUriPermissions;
+    boolean multiProcess;
+    int initOrder;
+    @Nullable
+    PatternMatcher[] uriPermissionPatterns;
+    @Nullable
+    PathPermission[] pathPermissions;
+
+    public ParsedProvider(ParsedProvider other) {
+        super(other);
+
+        this.authority = other.authority;
+        this.syncable = other.syncable;
+        this.readPermission = other.readPermission;
+        this.writePermission = other.writePermission;
+        this.grantUriPermissions = other.grantUriPermissions;
+        this.forceUriPermissions = other.forceUriPermissions;
+        this.multiProcess = other.multiProcess;
+        this.initOrder = other.initOrder;
+        this.uriPermissionPatterns = other.uriPermissionPatterns;
+        this.pathPermissions = other.pathPermissions;
+    }
+
+    public void setAuthority(String authority) {
+        this.authority = TextUtils.safeIntern(authority);
+    }
+
+    public void setSyncable(boolean syncable) {
+        this.syncable = syncable;
+    }
+
+    public void setReadPermission(String readPermission) {
+        // Empty string must be converted to null
+        this.readPermission = TextUtils.isEmpty(readPermission)
+                ? null : readPermission.intern();
+    }
+
+    public void setWritePermission(String writePermission) {
+        // Empty string must be converted to null
+        this.writePermission = TextUtils.isEmpty(writePermission)
+                ? null : writePermission.intern();
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("Provider{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        ComponentName.appendShortString(sb, getPackageName(), getName());
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        sForString.parcel(this.authority, dest, flags);
+        dest.writeBoolean(this.syncable);
+        sForString.parcel(this.readPermission, dest, flags);
+        sForString.parcel(this.writePermission, dest, flags);
+        dest.writeBoolean(this.grantUriPermissions);
+        dest.writeBoolean(this.forceUriPermissions);
+        dest.writeBoolean(this.multiProcess);
+        dest.writeInt(this.initOrder);
+        dest.writeTypedArray(this.uriPermissionPatterns, flags);
+        dest.writeTypedArray(this.pathPermissions, flags);
+    }
+
+    public ParsedProvider() {
+    }
+
+    protected ParsedProvider(Parcel in) {
+        super(in);
+        //noinspection ConstantConditions
+        this.authority = sForString.unparcel(in);
+        this.syncable = in.readBoolean();
+        this.readPermission = sForString.unparcel(in);
+        this.writePermission = sForString.unparcel(in);
+        this.grantUriPermissions = in.readBoolean();
+        this.forceUriPermissions = in.readBoolean();
+        this.multiProcess = in.readBoolean();
+        this.initOrder = in.readInt();
+        this.uriPermissionPatterns = in.createTypedArray(PatternMatcher.CREATOR);
+        this.pathPermissions = in.createTypedArray(PathPermission.CREATOR);
+    }
+
+    public static final Parcelable.Creator<ParsedProvider> CREATOR = new Creator<ParsedProvider>() {
+        @Override
+        public ParsedProvider createFromParcel(Parcel source) {
+            return new ParsedProvider(source);
+        }
+
+        @Override
+        public ParsedProvider[] newArray(int size) {
+            return new ParsedProvider[size];
+        }
+    };
+
+    @NonNull
+    public String getAuthority() {
+        return authority;
+    }
+
+    public boolean isSyncable() {
+        return syncable;
+    }
+
+    @Nullable
+    public String getReadPermission() {
+        return readPermission;
+    }
+
+    @Nullable
+    public String getWritePermission() {
+        return writePermission;
+    }
+
+    public boolean isGrantUriPermissions() {
+        return grantUriPermissions;
+    }
+
+    public boolean isForceUriPermissions() {
+        return forceUriPermissions;
+    }
+
+    public boolean isMultiProcess() {
+        return multiProcess;
+    }
+
+    public int getInitOrder() {
+        return initOrder;
+    }
+
+    @Nullable
+    public PatternMatcher[] getUriPermissionPatterns() {
+        return uriPermissionPatterns;
+    }
+
+    @Nullable
+    public PathPermission[] getPathPermissions() {
+        return pathPermissions;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
new file mode 100644
index 0000000..aa5ea8d
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedProviderUtils.java
@@ -0,0 +1,355 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.component.ComponentParseUtils.flag;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageParser;
+import android.content.pm.PathPermission;
+import android.content.pm.ProviderInfo;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.os.Build;
+import android.os.PatternMatcher;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/** @hide */
+public class ParsedProviderUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    public static ParseResult<ParsedProvider> parseProvider(String[] separateProcesses,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags,
+            boolean useRoundIcon, ParseInput input)
+            throws IOException, XmlPullParserException {
+        String authority;
+        boolean visibleToEphemeral;
+
+        final int targetSdkVersion = pkg.getTargetSdkVersion();
+        final String packageName = pkg.getPackageName();
+        final ParsedProvider provider = new ParsedProvider();
+        final String tag = parser.getName();
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestProvider);
+        try {
+            ParseResult<ParsedProvider> result =
+                    ParsedMainComponentUtils.parseMainComponent(provider, tag, separateProcesses,
+                    pkg, sa, flags, useRoundIcon, input,
+                    R.styleable.AndroidManifestProvider_banner,
+                    R.styleable.AndroidManifestProvider_description,
+                    R.styleable.AndroidManifestProvider_directBootAware,
+                    R.styleable.AndroidManifestProvider_enabled,
+                    R.styleable.AndroidManifestProvider_icon,
+                    R.styleable.AndroidManifestProvider_label,
+                    R.styleable.AndroidManifestProvider_logo,
+                    R.styleable.AndroidManifestProvider_name,
+                    R.styleable.AndroidManifestProvider_process,
+                    R.styleable.AndroidManifestProvider_roundIcon,
+                    R.styleable.AndroidManifestProvider_splitName);
+            if (result.isError()) {
+                return result;
+            }
+
+            authority = sa.getNonConfigurationString(R.styleable.AndroidManifestProvider_authorities, 0);
+
+            // For compatibility, applications targeting API level 16 or lower
+            // should have their content providers exported by default, unless they
+            // specify otherwise.
+            provider.exported = sa.getBoolean(R.styleable.AndroidManifestProvider_exported,
+                    targetSdkVersion < Build.VERSION_CODES.JELLY_BEAN_MR1);
+
+            provider.syncable = sa.getBoolean(R.styleable.AndroidManifestProvider_syncable, false);
+
+            String permission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestProvider_permission, 0);
+            String readPermission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestProvider_readPermission, 0);
+            if (readPermission == null) {
+                readPermission = permission;
+            }
+            if (readPermission == null) {
+                provider.setReadPermission(pkg.getPermission());
+            } else {
+                provider.setReadPermission(readPermission);
+            }
+            String writePermission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestProvider_writePermission, 0);
+            if (writePermission == null) {
+                writePermission = permission;
+            }
+            if (writePermission == null) {
+                provider.setWritePermission(pkg.getPermission());
+            } else {
+                provider.setWritePermission(writePermission);
+            }
+
+            provider.grantUriPermissions = sa.getBoolean(R.styleable.AndroidManifestProvider_grantUriPermissions, false);
+            provider.forceUriPermissions = sa.getBoolean(R.styleable.AndroidManifestProvider_forceUriPermissions, false);
+            provider.multiProcess = sa.getBoolean(R.styleable.AndroidManifestProvider_multiprocess, false);
+            provider.initOrder = sa.getInt(R.styleable.AndroidManifestProvider_initOrder, 0);
+
+            provider.flags |= flag(ProviderInfo.FLAG_SINGLE_USER, R.styleable.AndroidManifestProvider_singleUser, sa);
+
+            visibleToEphemeral = sa.getBoolean(R.styleable.AndroidManifestProvider_visibleToInstantApps, false);
+            if (visibleToEphemeral) {
+                provider.flags |= ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                pkg.setVisibleToInstantApps(true);
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        if (pkg.isCantSaveState()) {
+            // A heavy-weight application can not have providers in its main process
+            if (Objects.equals(provider.getProcessName(), packageName)) {
+                return input.error("Heavy-weight applications can not have providers"
+                        + " in main process");
+            }
+        }
+
+        if (authority == null) {
+            return input.error("<provider> does not include authorities attribute");
+        }
+        if (authority.length() <= 0) {
+            return input.error("<provider> has empty authorities attribute");
+        }
+        provider.setAuthority(authority);
+
+        return parseProviderTags(pkg, tag, res, parser, visibleToEphemeral, provider, input);
+    }
+
+    @NonNull
+    private static ParseResult<ParsedProvider> parseProviderTags(ParsingPackage pkg, String tag,
+            Resources res, XmlResourceParser parser, boolean visibleToEphemeral,
+            ParsedProvider provider, ParseInput input)
+            throws XmlPullParserException, IOException {
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            String name = parser.getName();
+            final ParseResult result;
+            switch (name) {
+                case "intent-filter":
+                    ParseResult<ParsedIntentInfo> intentResult = ParsedMainComponentUtils
+                            .parseIntentFilter(provider, pkg, res, parser, visibleToEphemeral,
+                                    true /*allowGlobs*/, false /*allowAutoVerify*/,
+                                    false /*allowImplicitEphemeralVisibility*/,
+                                    false /*failOnNoActions*/, input);
+                    result = intentResult;
+                    if (intentResult.isSuccess()) {
+                        ParsedIntentInfo intent = intentResult.getResult();
+                        provider.order = Math.max(intent.getOrder(), provider.order);
+                        provider.addIntent(intent);
+                    }
+                    break;
+                case "meta-data":
+                    result = ParsedComponentUtils.addMetaData(provider, pkg, res, parser, input);
+                    break;
+                case "grant-uri-permission": {
+                    result = parseGrantUriPermission(provider, pkg, res, parser, input);
+                    break;
+                }
+                case "path-permission": {
+                    result = parsePathPermission(provider, pkg, res, parser, input);
+                    break;
+                }
+                default:
+                    result = ParsingUtils.unknownTag(tag, pkg, parser, input);
+                    break;
+            }
+
+            if (result.isError()) {
+                return input.error(result);
+            }
+        }
+
+        return input.success(provider);
+    }
+
+    @NonNull
+    private static ParseResult<ParsedProvider> parseGrantUriPermission(ParsedProvider provider,
+            ParsingPackage pkg, Resources resources, XmlResourceParser parser, ParseInput input) {
+        TypedArray sa = resources.obtainAttributes(parser,
+                R.styleable.AndroidManifestGrantUriPermission);
+        try {
+            String name = parser.getName();
+            // Pattern has priority over prefix over literal path
+            PatternMatcher pa = null;
+            String str = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestGrantUriPermission_pathPattern, 0);
+            if (str != null) {
+                pa = new PatternMatcher(str, PatternMatcher.PATTERN_SIMPLE_GLOB);
+            } else {
+                str = sa.getNonConfigurationString(
+                        R.styleable.AndroidManifestGrantUriPermission_pathPrefix, 0);
+                if (str != null) {
+                    pa = new PatternMatcher(str, PatternMatcher.PATTERN_PREFIX);
+                } else {
+                    str = sa.getNonConfigurationString(
+                            R.styleable.AndroidManifestGrantUriPermission_path, 0);
+                    if (str != null) {
+                        pa = new PatternMatcher(str, PatternMatcher.PATTERN_LITERAL);
+                    }
+                }
+            }
+
+            if (pa != null) {
+                if (provider.uriPermissionPatterns == null) {
+                    provider.uriPermissionPatterns = new PatternMatcher[1];
+                    provider.uriPermissionPatterns[0] = pa;
+                } else {
+                    final int N = provider.uriPermissionPatterns.length;
+                    PatternMatcher[] newp = new PatternMatcher[N + 1];
+                    System.arraycopy(provider.uriPermissionPatterns, 0, newp, 0, N);
+                    newp[N] = pa;
+                    provider.uriPermissionPatterns = newp;
+                }
+                provider.grantUriPermissions = true;
+            } else {
+                if (PackageParser.RIGID_PARSER) {
+                    return input.error("No path, pathPrefix, or pathPattern for <path-permission>");
+                }
+
+                Slog.w(TAG, "Unknown element under <path-permission>: " + name + " at "
+                        + pkg.getBaseCodePath() + " " + parser.getPositionDescription());
+            }
+
+            return input.success(provider);
+        } finally {
+            sa.recycle();
+        }
+    }
+
+    @NonNull
+    private static ParseResult<ParsedProvider> parsePathPermission(ParsedProvider provider,
+            ParsingPackage pkg, Resources resources, XmlResourceParser parser, ParseInput input) {
+        TypedArray sa = resources.obtainAttributes(parser,
+                R.styleable.AndroidManifestPathPermission);
+        try {
+            String name = parser.getName();
+
+            String permission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestPathPermission_permission, 0);
+            String readPermission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestPathPermission_readPermission, 0);
+            if (readPermission == null) {
+                readPermission = permission;
+            }
+            String writePermission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestPathPermission_writePermission, 0);
+            if (writePermission == null) {
+                writePermission = permission;
+            }
+
+            boolean havePerm = false;
+            if (readPermission != null) {
+                readPermission = readPermission.intern();
+                havePerm = true;
+            }
+            if (writePermission != null) {
+                writePermission = writePermission.intern();
+                havePerm = true;
+            }
+
+            if (!havePerm) {
+                if (PackageParser.RIGID_PARSER) {
+                    return input.error(
+                            "No readPermission or writePermission for <path-permission>");
+                }
+                Slog.w(TAG, "No readPermission or writePermission for <path-permission>: "
+                        + name + " at " + pkg.getBaseCodePath() + " " + parser.getPositionDescription());
+                return input.success(provider);
+            }
+
+            // Advanced has priority over simply over prefix over literal
+            PathPermission pa = null;
+            String path = sa.getNonConfigurationString(R.styleable.AndroidManifestPathPermission_pathAdvancedPattern, 0);
+            if (path != null) {
+                pa = new PathPermission(path, PatternMatcher.PATTERN_ADVANCED_GLOB, readPermission,
+                        writePermission);
+            } else {
+                path = sa.getNonConfigurationString(R.styleable.AndroidManifestPathPermission_pathPattern, 0);
+                if (path != null) {
+                    pa = new PathPermission(path, PatternMatcher.PATTERN_SIMPLE_GLOB,
+                            readPermission, writePermission);
+                } else {
+                    path = sa.getNonConfigurationString(
+                            R.styleable.AndroidManifestPathPermission_pathPrefix, 0);
+                    if (path != null) {
+                        pa = new PathPermission(path, PatternMatcher.PATTERN_PREFIX, readPermission,
+                                writePermission);
+                    } else {
+                        path = sa.getNonConfigurationString(R.styleable.AndroidManifestPathPermission_path, 0);
+                        if (path != null) {
+                            pa = new PathPermission(path, PatternMatcher.PATTERN_LITERAL,
+                                    readPermission, writePermission);
+                        }
+                    }
+                }
+            }
+
+            if (pa != null) {
+                if (provider.pathPermissions == null) {
+                    provider.pathPermissions = new PathPermission[1];
+                    provider.pathPermissions[0] = pa;
+                } else {
+                    final int N = provider.pathPermissions.length;
+                    PathPermission[] newp = new PathPermission[N + 1];
+                    System.arraycopy(provider.pathPermissions, 0, newp, 0, N);
+                    newp[N] = pa;
+                    provider.pathPermissions = newp;
+                }
+            } else {
+                if (PackageParser.RIGID_PARSER) {
+                    return input.error(
+                            "No path, pathPrefix, or pathPattern for <path-permission>");
+                }
+
+                Slog.w(TAG, "No path, pathPrefix, or pathPattern for <path-permission>: "
+                        + name + " at " + pkg.getBaseCodePath()
+                        + " "
+                        + parser.getPositionDescription());
+            }
+
+            return input.success(provider);
+        } finally {
+            sa.recycle();
+        }
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedService.java b/core/java/android/content/pm/parsing/component/ParsedService.java
new file mode 100644
index 0000000..591eef7
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedService.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.parsing.component;
+
+import static android.content.pm.parsing.ParsingPackageImpl.sForString;
+
+import android.annotation.Nullable;
+import android.content.ComponentName;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+
+/** @hide **/
+public class ParsedService extends ParsedMainComponent {
+
+    int foregroundServiceType;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    private String permission;
+
+    public ParsedService(ParsedService other) {
+        super(other);
+        this.foregroundServiceType = other.foregroundServiceType;
+        this.permission = other.permission;
+    }
+
+    public ParsedMainComponent setPermission(String permission) {
+        // Empty string must be converted to null
+        this.permission = TextUtils.isEmpty(permission) ? null : permission.intern();
+        return this;
+    }
+
+    public String toString() {
+        StringBuilder sb = new StringBuilder(128);
+        sb.append("Service{");
+        sb.append(Integer.toHexString(System.identityHashCode(this)));
+        sb.append(' ');
+        ComponentName.appendShortString(sb, getPackageName(), getName());
+        sb.append('}');
+        return sb.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        dest.writeInt(this.foregroundServiceType);
+        sForString.parcel(this.permission, dest, flags);
+    }
+
+    public ParsedService() {
+    }
+
+    protected ParsedService(Parcel in) {
+        super(in);
+        this.foregroundServiceType = in.readInt();
+        this.permission = sForString.unparcel(in);
+    }
+
+    public static final Parcelable.Creator<ParsedService> CREATOR = new Creator<ParsedService>() {
+        @Override
+        public ParsedService createFromParcel(Parcel source) {
+            return new ParsedService(source);
+        }
+
+        @Override
+        public ParsedService[] newArray(int size) {
+            return new ParsedService[size];
+        }
+    };
+
+    public int getForegroundServiceType() {
+        return foregroundServiceType;
+    }
+
+    @Nullable
+    public String getPermission() {
+        return permission;
+    }
+}
diff --git a/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
new file mode 100644
index 0000000..8a8a066
--- /dev/null
+++ b/core/java/android/content/pm/parsing/component/ParsedServiceUtils.java
@@ -0,0 +1,165 @@
+/*
+ * 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.content.pm.parsing.component;
+
+import static android.content.pm.parsing.component.ComponentParseUtils.flag;
+
+import android.annotation.NonNull;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.ParsingUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/** @hide */
+public class ParsedServiceUtils {
+
+    private static final String TAG = ParsingPackageUtils.TAG;
+
+    @NonNull
+    public static ParseResult<ParsedService> parseService(String[] separateProcesses,
+            ParsingPackage pkg, Resources res, XmlResourceParser parser, int flags,
+            boolean useRoundIcon, ParseInput input)
+            throws XmlPullParserException, IOException {
+        boolean visibleToEphemeral;
+        boolean setExported;
+
+        final String packageName = pkg.getPackageName();
+        final ParsedService service = new ParsedService();
+        String tag = parser.getName();
+
+        TypedArray sa = res.obtainAttributes(parser, R.styleable.AndroidManifestService);
+        try {
+            ParseResult<ParsedService> result = ParsedMainComponentUtils.parseMainComponent(
+                    service, tag, separateProcesses, pkg, sa, flags, useRoundIcon, input,
+                    R.styleable.AndroidManifestService_banner,
+                    R.styleable.AndroidManifestService_description,
+                    R.styleable.AndroidManifestService_directBootAware,
+                    R.styleable.AndroidManifestService_enabled,
+                    R.styleable.AndroidManifestService_icon,
+                    R.styleable.AndroidManifestService_label,
+                    R.styleable.AndroidManifestService_logo,
+                    R.styleable.AndroidManifestService_name,
+                    R.styleable.AndroidManifestService_process,
+                    R.styleable.AndroidManifestService_roundIcon,
+                    R.styleable.AndroidManifestService_splitName
+            );
+
+            if (result.isError()) {
+                return result;
+            }
+
+            setExported = sa.hasValue(R.styleable.AndroidManifestService_exported);
+            if (setExported) {
+                service.exported = sa.getBoolean(R.styleable.AndroidManifestService_exported,
+                        false);
+            }
+
+            String permission = sa.getNonConfigurationString(
+                    R.styleable.AndroidManifestService_permission, 0);
+            service.setPermission(permission != null ? permission : pkg.getPermission());
+
+            service.foregroundServiceType = sa.getInt(
+                    R.styleable.AndroidManifestService_foregroundServiceType,
+                    ServiceInfo.FOREGROUND_SERVICE_TYPE_NONE);
+
+            service.flags |= flag(ServiceInfo.FLAG_STOP_WITH_TASK,
+                    R.styleable.AndroidManifestService_stopWithTask, sa)
+                    | flag(ServiceInfo.FLAG_ISOLATED_PROCESS,
+                    R.styleable.AndroidManifestService_isolatedProcess, sa)
+                    | flag(ServiceInfo.FLAG_EXTERNAL_SERVICE,
+                    R.styleable.AndroidManifestService_externalService, sa)
+                    | flag(ServiceInfo.FLAG_USE_APP_ZYGOTE,
+                    R.styleable.AndroidManifestService_useAppZygote, sa)
+                    | flag(ServiceInfo.FLAG_SINGLE_USER,
+                    R.styleable.AndroidManifestService_singleUser, sa);
+
+            visibleToEphemeral = sa.getBoolean(
+                    R.styleable.AndroidManifestService_visibleToInstantApps, false);
+            if (visibleToEphemeral) {
+                service.flags |= ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP;
+                pkg.setVisibleToInstantApps(true);
+            }
+        } finally {
+            sa.recycle();
+        }
+
+        if (pkg.isCantSaveState()) {
+            // A heavy-weight application can not have services in its main process
+            // We can do direct compare because we intern all strings.
+            if (Objects.equals(service.getProcessName(), packageName)) {
+                return input.error("Heavy-weight applications can not have services "
+                        + "in main process");
+            }
+        }
+        final int depth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG
+                || parser.getDepth() > depth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            final ParseResult parseResult;
+            switch (parser.getName()) {
+                case "intent-filter":
+                    ParseResult<ParsedIntentInfo> intentResult = ParsedMainComponentUtils
+                            .parseIntentFilter(service, pkg, res, parser, visibleToEphemeral,
+                                    true /*allowGlobs*/, false /*allowAutoVerify*/,
+                                    false /*allowImplicitEphemeralVisibility*/,
+                                    false /*failOnNoActions*/, input);
+                    parseResult = intentResult;
+                    if (intentResult.isSuccess()) {
+                        ParsedIntentInfo intent = intentResult.getResult();
+                        service.order = Math.max(intent.getOrder(), service.order);
+                        service.addIntent(intent);
+                    }
+                    break;
+                case "meta-data":
+                    parseResult = ParsedComponentUtils.addMetaData(service, pkg, res, parser, input);
+                    break;
+                default:
+                    parseResult = ParsingUtils.unknownTag(tag, pkg, parser, input);
+                    break;
+            }
+
+            if (parseResult.isError()) {
+                return input.error(parseResult);
+            }
+        }
+
+        if (!setExported) {
+            service.exported = service.getIntents().size() > 0;
+        }
+
+        return input.success(service);
+    }
+}
diff --git a/core/java/android/content/pm/parsing/result/ParseInput.java b/core/java/android/content/pm/parsing/result/ParseInput.java
new file mode 100644
index 0000000..c468506
--- /dev/null
+++ b/core/java/android/content/pm/parsing/result/ParseInput.java
@@ -0,0 +1,70 @@
+/*
+ * 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.content.pm.parsing.result;
+
+import android.annotation.Hide;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+
+/**
+ * Used as a method parameter which is then transformed into a {@link ParseResult}. This is
+ * generalized as it doesn't matter what type this input is for. It's simply to hide the
+ * methods of {@link ParseResult}.
+ *
+ * @hide
+ */
+public interface ParseInput {
+
+    <ResultType> ParseResult<ResultType> success(ResultType result);
+
+    /** @see #error(int, String, Exception) */
+    <ResultType> ParseResult<ResultType> error(int parseError);
+
+    /**
+     * This will assign errorCode to {@link PackageManager#INSTALL_PARSE_FAILED_MANIFEST_MALFORMED}.
+     * @see #error(int, String, Exception)
+     */
+    <ResultType> ParseResult<ResultType> error(@NonNull String parseError);
+
+    /** @see #error(int, String, Exception) */
+    <ResultType> ParseResult<ResultType> error(int parseError, @Nullable String errorMessage);
+
+    /**
+     * Marks this as an error result. When this method is called, the return value <b>must</b>
+     * be returned to the exit of the parent method that took in this {@link ParseInput} as a
+     * parameter.
+     *
+     * The calling site of that method is then expected to check the result for error, and
+     * continue to bubble up if it is an error.
+     *
+     * Or, if the code explicitly handles an error,
+     * {@link ParseResult#ignoreError()} should be called.
+     *
+     * If the result {@link ParseResult#isSuccess()}, then it can be used as-is, as
+     * overlapping/consecutive successes are allowed.
+     */
+    <ResultType> ParseResult<ResultType> error(int parseError, @Nullable String errorMessage,
+            @Nullable Exception exception);
+
+    /**
+     * Moves the error in {@param result} to this input's type. In practice this does nothing
+     * but cast the type of the {@link ParseResult} for type safety, since the parameter
+     * and the receiver should be the same object.
+     */
+    <ResultType> ParseResult<ResultType> error(ParseResult result);
+}
diff --git a/core/java/android/content/pm/parsing/result/ParseResult.java b/core/java/android/content/pm/parsing/result/ParseResult.java
new file mode 100644
index 0000000..338048c
--- /dev/null
+++ b/core/java/android/content/pm/parsing/result/ParseResult.java
@@ -0,0 +1,76 @@
+/*
+ * 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.content.pm.parsing.result;
+
+import android.annotation.Nullable;
+import android.content.pm.PackageParser;
+
+/**
+ * The output side of {@link ParseInput}, which must result from a method call on
+ * {@link ParseInput}.
+ *
+ * When using this class, keep in mind that all {@link ParseInput}s and {@link ParseResult}s
+ * are the exact same object, scoped to a per {@link PackageParser} instance, per thread basis,
+ * thrown around and casted everywhere for type safety.
+ *
+ * @hide
+ */
+public interface ParseResult<ResultType> {
+
+    /**
+     * Un-marks this result as an error, also allowing it to be re-used as {@link ParseInput}.
+     *
+     * This should only be used in cases where it's absolutely certain that error handling is
+     * irrelevant. Such as for backwards compatibility where it previously didn't fail and that
+     * behavior has to be maintained.
+     *
+     * Mostly an alias for readability.
+     */
+    void ignoreError();
+
+    /**
+     * Returns true if the result is not an error and thus contains a valid object.
+     *
+     * For backwards-compat reasons, it's possible to have a successful result with a null
+     * result object, depending on the behavior of the parsing method.
+     *
+     * It is expected that every method calls this to check for an error state to bubble up
+     * the error to its parent method after every parse method call.
+     *
+     * It is not always necessary to check this, as it is valid to return any ParseResult from
+     * a method so long as the type matches <b>without casting it</b>.
+     *
+     * The infrastructure is set up such that as long as a result is the proper type and
+     * the right side of success vs. error, it can be bubble up through all its parent methods.
+     */
+    boolean isSuccess();
+
+    /**
+     * Opposite of {@link #isSuccess()} for readability.
+     */
+    boolean isError();
+
+    ResultType getResult();
+
+    int getErrorCode();
+
+    @Nullable
+    String getErrorMessage();
+
+    @Nullable
+    Exception getException();
+}
diff --git a/core/java/android/content/pm/parsing/result/ParseTypeImpl.java b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
new file mode 100644
index 0000000..9b22f09
--- /dev/null
+++ b/core/java/android/content/pm/parsing/result/ParseTypeImpl.java
@@ -0,0 +1,145 @@
+/*
+ * 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.content.pm.parsing.result;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.parsing.ParsingUtils;
+import android.util.Log;
+
+import java.util.Arrays;
+
+/** @hide */
+public class ParseTypeImpl implements ParseInput, ParseResult<Object> {
+
+    private static final String TAG = ParsingUtils.TAG;
+
+    private static final boolean DEBUG_FILL_STACK_TRACE = false;
+
+    private static final boolean DEBUG_LOG_ON_ERROR = false;
+
+    private Object result;
+
+    private int errorCode = PackageManager.INSTALL_SUCCEEDED;
+
+    @Nullable
+    private String errorMessage;
+
+    @Nullable
+    private Exception exception;
+
+    public ParseInput reset() {
+        this.result = null;
+        this.errorCode = PackageManager.INSTALL_SUCCEEDED;
+        this.errorMessage = null;
+        this.exception = null;
+        return this;
+    }
+
+    @Override
+    public void ignoreError() {
+        reset();
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> success(ResultType result) {
+        if (errorCode != PackageManager.INSTALL_SUCCEEDED || errorMessage != null) {
+            throw new IllegalStateException("Cannot set to success after set to error, was "
+                    + errorMessage, exception);
+        }
+        this.result = result;
+        //noinspection unchecked
+        return (ParseResult<ResultType>) this;
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> error(int parseError) {
+        return error(parseError, null);
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> error(@NonNull String parseError) {
+        return error(PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED, parseError);
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> error(int errorCode,
+            @Nullable String errorMessage) {
+        return error(errorCode, errorMessage, null);
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> error(ParseResult intentResult) {
+        return error(intentResult.getErrorCode(), intentResult.getErrorMessage());
+    }
+
+    @Override
+    public <ResultType> ParseResult<ResultType> error(int errorCode, @Nullable String errorMessage,
+            Exception exception) {
+        this.errorCode = errorCode;
+        this.errorMessage = errorMessage;
+        this.exception = exception;
+
+        if (DEBUG_FILL_STACK_TRACE) {
+            if (exception == null) {
+                this.exception = new Exception();
+            }
+        }
+
+        if (DEBUG_LOG_ON_ERROR) {
+            Exception exceptionToLog = this.exception != null ? this.exception : new Exception();
+            Log.w(TAG, "ParseInput set to error " + errorCode + ", " + errorMessage,
+                    exceptionToLog);
+        }
+
+        //noinspection unchecked
+        return (ParseResult<ResultType>) this;
+    }
+
+    @Override
+    public Object getResult() {
+        return this.result;
+    }
+
+    @Override
+    public boolean isSuccess() {
+        return errorCode == PackageManager.INSTALL_SUCCEEDED;
+    }
+
+    @Override
+    public boolean isError() {
+        return !isSuccess();
+    }
+
+    @Override
+    public int getErrorCode() {
+        return errorCode;
+    }
+
+    @Nullable
+    @Override
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Nullable
+    @Override
+    public Exception getException() {
+        return exception;
+    }
+}
diff --git a/core/java/android/content/res/AssetManager.java b/core/java/android/content/res/AssetManager.java
index 1b01758..f295f8c 100644
--- a/core/java/android/content/res/AssetManager.java
+++ b/core/java/android/content/res/AssetManager.java
@@ -38,6 +38,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.om.OverlayConfig;
 
 import java.io.FileDescriptor;
 import java.io.FileNotFoundException;
@@ -242,14 +243,11 @@
         try {
             final ArrayList<ApkAssets> apkAssets = new ArrayList<>();
             apkAssets.add(ApkAssets.loadFromPath(frameworkPath, true /*system*/));
-            final String[] systemIdmapPaths = nativeCreateIdmapsForStaticOverlaysTargetingAndroid();
-            if (systemIdmapPaths != null) {
-                for (String idmapPath : systemIdmapPaths) {
-                    apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
-                }
-            } else {
-                Log.w(TAG, "'idmap2 --scan' failed: no static=\"true\" overlays targeting "
-                        + "\"android\" will be loaded");
+
+            final String[] systemIdmapPaths =
+                    OverlayConfig.getZygoteInstance().createImmutableFrameworkIdmapsInZygote();
+            for (String idmapPath : systemIdmapPaths) {
+                apkAssets.add(ApkAssets.loadOverlayFromPath(idmapPath, true /*system*/));
             }
 
             sSystemApkAssetsSet = new ArraySet<>(apkAssets);
diff --git a/core/java/android/debug/AdbManager.java b/core/java/android/debug/AdbManager.java
index 0a76bed..7714dd8 100644
--- a/core/java/android/debug/AdbManager.java
+++ b/core/java/android/debug/AdbManager.java
@@ -31,6 +31,114 @@
 public class AdbManager {
     private static final String TAG = "AdbManager";
 
+    /**
+     * Action indicating the state change of wireless debugging. Can be either
+     *   STATUS_CONNECTED
+     *   STATUS_DISCONNECTED
+     *
+     * @hide
+     */
+    public static final String WIRELESS_DEBUG_STATE_CHANGED_ACTION =
+            "com.android.server.adb.WIRELESS_DEBUG_STATUS";
+
+    /**
+     * Contains the list of paired devices.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_DEBUG_PAIRED_DEVICES_ACTION =
+            "com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES";
+
+    /**
+     * Action indicating the status of a pairing. Can be either
+     *   WIRELESS_STATUS_FAIL
+     *   WIRELESS_STATUS_SUCCESS
+     *   WIRELESS_STATUS_CANCELLED
+     *   WIRELESS_STATUS_PAIRING_CODE
+     *   WIRELESS_STATUS_CONNECTED
+     *
+     * @hide
+     */
+    public static final String WIRELESS_DEBUG_PAIRING_RESULT_ACTION =
+            "com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT";
+
+    /**
+     * Extra containing the PairDevice map of paired/pairing devices.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_DEVICES_EXTRA = "devices_map";
+
+    /**
+     * The status of the pairing/unpairing.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_STATUS_EXTRA = "status";
+
+    /**
+     * The PairDevice.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_PAIR_DEVICE_EXTRA = "pair_device";
+
+    /**
+     * The six-digit pairing code.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_PAIRING_CODE_EXTRA = "pairing_code";
+
+    /**
+     * The adb connection/pairing port that was opened.
+     *
+     * @hide
+     */
+    public static final String WIRELESS_DEBUG_PORT_EXTRA = "adb_port";
+
+    /**
+     * Status indicating the pairing/unpairing failed.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_FAIL = 0;
+
+    /**
+     * Status indicating the pairing/unpairing succeeded.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_SUCCESS = 1;
+
+    /**
+     * Status indicating the pairing/unpairing was cancelled.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_CANCELLED = 2;
+
+    /**
+     * Status indicating the pairing code for pairing.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_PAIRING_CODE = 3;
+
+    /**
+     * Status indicating wireless debugging is connected.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_CONNECTED = 4;
+
+    /**
+     * Status indicating wireless debugging is disconnected.
+     *
+     * @hide
+     */
+    public static final int WIRELESS_STATUS_DISCONNECTED = 5;
+
     private final Context mContext;
     private final IAdbManager mService;
 
diff --git a/core/java/android/debug/AdbManagerInternal.java b/core/java/android/debug/AdbManagerInternal.java
index 51eb7fc..0bd9f19 100644
--- a/core/java/android/debug/AdbManagerInternal.java
+++ b/core/java/android/debug/AdbManagerInternal.java
@@ -42,7 +42,7 @@
     /**
      * Returns {@code true} if ADB debugging is enabled.
      */
-    public abstract boolean isAdbEnabled();
+    public abstract boolean isAdbEnabled(byte transportType);
 
     /**
      * Returns the file that contains all of the ADB keys used by the device.
diff --git a/core/java/android/service/controls/IControlsLoadCallback.aidl b/core/java/android/debug/AdbTransportType.aidl
similarity index 62%
copy from core/java/android/service/controls/IControlsLoadCallback.aidl
copy to core/java/android/debug/AdbTransportType.aidl
index bfc61cd..6904615 100644
--- a/core/java/android/service/controls/IControlsLoadCallback.aidl
+++ b/core/java/android/debug/AdbTransportType.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2020, The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-package android.service.controls;
+package android.debug;
 
-import android.service.controls.Control;
+/** @hide */
+@Backing(type="byte")
+enum AdbTransportType {
+    USB,
+    WIFI,
+}
 
-/**
- * @hide
- */
-oneway interface IControlsLoadCallback {
-    void accept(in IBinder token, in List<Control> controls);
-}
\ No newline at end of file
diff --git a/core/java/android/debug/IAdbManager.aidl b/core/java/android/debug/IAdbManager.aidl
index c48fc07..aea7633 100644
--- a/core/java/android/debug/IAdbManager.aidl
+++ b/core/java/android/debug/IAdbManager.aidl
@@ -43,6 +43,62 @@
     void clearDebuggingKeys();
 
     /**
+     * Allow ADB wireless debugging on the connected network. If {@code alwaysAllow}
+     * is {@code true}, add {@code bssid} to list of networks that the user has
+     * approved.
+     *
+     * @param alwaysAllow if true, add permanently to list of allowed networks
+     * @param bssid BSSID of the network
+     */
+    void allowWirelessDebugging(boolean alwaysAllow, String bssid);
+
+    /**
+     * Deny ADB wireless debugging on the connected network.
+     */
+    void denyWirelessDebugging();
+
+    /**
+     * Returns a Map<String, PairDevice> with the key fingerprint mapped to the device information.
+     */
+    Map getPairedDevices();
+
+    /**
+     * Unpair the device identified by the key fingerprint it uses.
+     *
+     * @param fingerprint fingerprint of the key the device is using.
+     */
+    void unpairDevice(String fingerprint);
+
+    /**
+     * Enables pairing by pairing code. The result of the enable will be sent via intent action
+     * {@link android.debug.AdbManager#WIRELESS_DEBUG_ENABLE_DISCOVER_ACTION}. Furthermore, the
+     * pairing code will also be sent in the intent as an extra
+     * @{link android.debug.AdbManager#WIRELESS_PAIRING_CODE_EXTRA}. Note that only one
+     * pairing method can be enabled at a time, either by pairing code, or by QR code.
+     */
+    void enablePairingByPairingCode();
+
+    /**
+     * Enables pairing by QR code. The result of the enable will be sent via intent action
+     * {@link android.debug.AdbManager#WIRELESS_DEBUG_ENABLE_DISCOVER_ACTION}. Note that only one
+     * pairing method can be enabled at a time, either by pairing code, or by QR code.
+     *
+     * @param serviceName The MDNS service name parsed from the QR code.
+     * @param password The password parsed from the QR code.
+     */
+    void enablePairingByQrCode(String serviceName, String password);
+
+    /**
+     * Returns the network port that adb wireless server is running on.
+     */
+    int getAdbWirelessPort();
+
+    /**
+     * Disables pairing.
+     */
+    void disablePairing();
+
+    /**
      * Returns true if device supports secure Adb over Wi-Fi.
      */
     boolean isAdbWifiSupported();
diff --git a/core/java/android/debug/IAdbTransport.aidl b/core/java/android/debug/IAdbTransport.aidl
index 77211fc93..f018813 100644
--- a/core/java/android/debug/IAdbTransport.aidl
+++ b/core/java/android/debug/IAdbTransport.aidl
@@ -16,7 +16,9 @@
 
 package android.debug;
 
+import android.debug.AdbTransportType;
+
 /** @hide */
 interface IAdbTransport {
-    void onAdbEnabled(boolean enabled);
+    void onAdbEnabled(boolean enabled, in AdbTransportType type);
 }
diff --git a/core/java/android/debug/PairDevice.java b/core/java/android/debug/PairDevice.java
new file mode 100644
index 0000000..2d5b446
--- /dev/null
+++ b/core/java/android/debug/PairDevice.java
@@ -0,0 +1,112 @@
+/*
+ * 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.debug;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.annotations.Immutable;
+import com.android.internal.util.Preconditions;
+
+/**
+ * Contains information about the client in an ADB connection.
+ * @hide
+ */
+@Immutable
+public class PairDevice implements Parcelable {
+    /**
+     * The human-readable name of the device.
+     */
+    @NonNull private final String mName;
+
+    /**
+     * The device's guid.
+     */
+    @NonNull private final String mGuid;
+
+    /**
+     * Indicates whether the device is currently connected to adbd.
+     */
+    private final boolean mConnected;
+
+    public PairDevice(@NonNull String name, @NonNull String guid, boolean connected) {
+        Preconditions.checkStringNotEmpty(name);
+        Preconditions.checkStringNotEmpty(guid);
+        mName = name;
+        mGuid = guid;
+        mConnected = connected;
+    }
+
+    /**
+     * @return the device name.
+     */
+    @NonNull
+    public String getDeviceName() {
+        return mName;
+    }
+
+    /**
+     * @return the device GUID.
+     */
+    @NonNull
+    public String getGuid() {
+        return mGuid;
+    }
+
+    /**
+     * @return the adb connection state of the device.
+     */
+    public boolean isConnected() {
+        return mConnected;
+    }
+
+    @Override
+    public void writeToParcel(@NonNull Parcel dest, int flags) {
+        dest.writeString(mName);
+        dest.writeString(mGuid);
+        dest.writeBoolean(mConnected);
+    }
+
+    /**
+     * @return Human-readable info about the object.
+     */
+    @Override
+    public String toString() {
+        return "\n" + mName + "\n" + mGuid + "\n" + mConnected;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @NonNull
+    public static final Parcelable.Creator<PairDevice> CREATOR =
+            new Creator<PairDevice>() {
+                @Override
+                public PairDevice createFromParcel(Parcel source) {
+                    return new PairDevice(source.readString(), source.readString(),
+                            source.readBoolean());
+                }
+
+                @Override
+                public PairDevice[] newArray(int size) {
+                    return new PairDevice[size];
+                }
+            };
+}
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 24d9311..cc0c1a30 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -688,17 +688,19 @@
      * <tr><th colspan="5">Concurrent stream guaranteed configurations</th></tr>
      * <tr><th colspan="2" id="rb">Target 1</th><th colspan="2" id="rb">Target 2</th><th rowspan="2">Sample use case(s)</th> </tr>
      * <tr><th>Type</th><th id="rb">Max size</th><th>Type</th><th id="rb">Max size</th> </tr>
-     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td>  <td colspan="2" id="rb"></td> <td>In-app video / image processing.</td> </tr>
-     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td>  <td colspan="2" id="rb"></td> <td>In-app viewfinder analysis.</td> </tr>
-     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code YUV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
-     * <tr> <td>{@code YUV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>In-app video / processing with preview.</td> </tr>
-     * <tr> <td>{@code PRIV}</td><td id="rb">{@code MAXIMUM}</td> <td>{@code PRIV }</td><td id="rb">{@code MAXIMUM}</td> <td>Standard Recording.</td> </tr>
+     * <tr> <td>{@code YUV}</td><td id="rb">{@code s1440p}</td>  <td colspan="2" id="rb"></td> <td>In-app video / image processing.</td> </tr>
+     * <tr> <td>{@code PRIV}</td><td id="rb">{@code s1440p}</td>  <td colspan="2" id="rb"></td> <td>In-app viewfinder analysis.</td> </tr>
+     * <tr> <td>{@code JPEG}</td><td id="rb">{@code s1440p}</td>  <td colspan="2" id="rb"></td> <td>No viewfinder still image capture.</td> </tr>
+     * <tr> <td>{@code YUV / PRIV}</td><td id="rb">{@code s720p}</td> <td>{@code JPEG}</td><td id="rb">{@code s1440p}</td> <td> Standard still imaging.</td> </tr>
+     * <tr> <td>{@code YUV / PRIV}</td><td id="rb">{@code s720p}</td> <td>{@code YUV / PRIV }</td><td id="rb">{@code s1440p}</td> <td>In-app video / processing with preview.</td> </tr>
      * </table><br>
      * </p>
      *
-     * <p> For guaranteed concurrent stream configurations, MAXIMUM refers to the camera device's
-     * resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+     * <p> For guaranteed concurrent stream configurations:</p>
+     * <p> s720p refers to the camera device's resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
      * 720p(1280X720) whichever is lower. </p>
+     * <p> s1440p refers to the camera device's resolution for that format from {@link StreamConfigurationMap#getOutputSizes} or
+     * 1440p(1920X1440) whichever is lower. </p>
      * <p>MONOCHROME-capability ({@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES}
      * includes {@link CameraMetadata#REQUEST_AVAILABLE_CAPABILITIES_MONOCHROME MONOCHROME}) devices
      * supporting {@link android.graphics.ImageFormat#Y8 Y8} support substituting {@code YUV}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 17c83f3..743ce7b 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -140,6 +140,11 @@
      * <p>The set of combinations doesn't contain physical cameras that can only be used as
      * part of a logical multi-camera device.</p>
      *
+     * <p> If a new camera id becomes available through
+     * {@link AvailabilityCallback#onCameraUnavailable(String)}, clients can call
+     * this method to check if new combinations of camera ids which can stream concurrently are
+     * available.
+     *
      * @return The set of combinations of currently connected camera devices, that may have
      *         sessions configured concurrently. The set of combinations will be empty if no such
      *         combinations are supported by the camera subsystem.
diff --git a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
index 41e1443..f0fab6a 100644
--- a/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
+++ b/core/java/android/hardware/camera2/params/MandatoryStreamCombination.java
@@ -267,7 +267,7 @@
                 mStreamsInformation.hashCode());
     }
 
-    private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM, s720p }
+    private static enum SizeThreshold { VGA, PREVIEW, RECORD, MAXIMUM, s720p, s1440p }
     private static enum ReprocessType { NONE, PRIVATE, YUV }
     private static final class StreamTemplate {
         public int mFormat;
@@ -651,23 +651,38 @@
 
     private static StreamCombinationTemplate sConcurrentStreamCombinations[] = {
         new StreamCombinationTemplate(new StreamTemplate [] {
-                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p) },
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p) },
                 "In-app video / image processing"),
         new StreamCombinationTemplate(new StreamTemplate [] {
-                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p) },
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p) },
                 "preview / preview to GPU"),
         new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.JPEG, SizeThreshold.s1440p) },
+                "No view-finder still image capture"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
                 new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p),
-                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p)},
+                "Two-input in app video / image processing"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p)},
+                "High resolution video recording with preview"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s1440p)},
+                "In-app video / image processing with preview"),
+        new StreamCombinationTemplate(new StreamTemplate [] {
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s1440p)},
                 "In-app video / image processing with preview"),
         new StreamCombinationTemplate(new StreamTemplate [] {
                 new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
-                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p)},
-                "In-app video / image processing with preview"),
+                new StreamTemplate(ImageFormat.JPEG, SizeThreshold.s1440p)},
+                "Standard stil image capture"),
         new StreamCombinationTemplate(new StreamTemplate [] {
-                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p),
-                new StreamTemplate(ImageFormat.PRIVATE, SizeThreshold.s720p)},
-                "Standard Recording"),
+                new StreamTemplate(ImageFormat.YUV_420_888, SizeThreshold.s720p),
+                new StreamTemplate(ImageFormat.JPEG, SizeThreshold.s1440p)},
+                "Standard still image capture"),
     };
 
     /**
@@ -720,6 +735,7 @@
                          + " cannot have mandatory concurrent streams");
             }
             Size size720p = new Size(1280, 720);
+            Size size1440p = new Size(1920, 1440);
 
             ArrayList<MandatoryStreamCombination> availableConcurrentStreamCombinations =
                     new ArrayList<MandatoryStreamCombination>();
@@ -732,8 +748,16 @@
                 for (StreamTemplate template : combTemplate.mStreamTemplates) {
                     MandatoryStreamInformation streamInfo;
                     List<Size> sizes = new ArrayList<Size>();
+                    Size formatSize = null;
+                    switch (template.mSizeThreshold) {
+                        case s1440p:
+                            formatSize = size1440p;
+                            break;
+                        default:
+                            formatSize = size720p;
+                    }
                     Size sizeChosen =
-                            getMinSize(size720p,
+                            getMinSize(formatSize,
                                     getMaxSize(mStreamConfigMap.getOutputSizes(template.mFormat)));
                     sizes.add(sizeChosen);
                     try {
diff --git a/core/java/android/hardware/display/DeviceProductInfo.java b/core/java/android/hardware/display/DeviceProductInfo.java
new file mode 100644
index 0000000..ce26cb0
--- /dev/null
+++ b/core/java/android/hardware/display/DeviceProductInfo.java
@@ -0,0 +1,224 @@
+/*
+ * 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.hardware.display;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Product-specific information about the display or the directly connected device on the
+ * display chain. For example, if the display is transitively connected, this field may contain
+ * product information about the intermediate device.
+ * @hide
+ */
+public final class DeviceProductInfo implements Parcelable {
+    private final String mName;
+    private final String mManufacturerPnpId;
+    private final String mProductId;
+    private final Integer mModelYear;
+    private final ManufactureDate mManufactureDate;
+
+    public DeviceProductInfo(
+            String name,
+            String manufacturerPnpId,
+            String productId,
+            Integer modelYear,
+            ManufactureDate manufactureDate) {
+        this.mName = name;
+        this.mManufacturerPnpId = manufacturerPnpId;
+        this.mProductId = productId;
+        this.mModelYear = modelYear;
+        this.mManufactureDate = manufactureDate;
+    }
+
+    private DeviceProductInfo(Parcel in) {
+        mName = in.readString();
+        mManufacturerPnpId = in.readString();
+        mProductId = (String) in.readValue(null);
+        mModelYear = (Integer) in.readValue(null);
+        mManufactureDate = (ManufactureDate) in.readValue(null);
+    }
+
+    /**
+     * @return Display name.
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * @return Manufacturer Plug and Play ID.
+     */
+    public String getManufacturerPnpId() {
+        return mManufacturerPnpId;
+    }
+
+    /**
+     * @return Manufacturer product ID.
+     */
+    public String getProductId() {
+        return mProductId;
+    }
+
+    /**
+     * @return Model year of the device. Typically exactly one of model year or
+     *      manufacture date will be present.
+     */
+    public Integer getModelYear() {
+        return mModelYear;
+    }
+
+    /**
+     * @return Manufacture date. Typically exactly one of model year or manufacture
+     * date will be present.
+     */
+    public ManufactureDate getManufactureDate() {
+        return mManufactureDate;
+    }
+
+    @Override
+    public String toString() {
+        return "DeviceProductInfo{"
+                + "name="
+                + mName
+                + ", manufacturerPnpId="
+                + mManufacturerPnpId
+                + ", productId="
+                + mProductId
+                + ", modelYear="
+                + mModelYear
+                + ", manufactureDate="
+                + mManufactureDate
+                + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        DeviceProductInfo that = (DeviceProductInfo) o;
+        return Objects.equals(mName, that.mName)
+                && Objects.equals(mManufacturerPnpId, that.mManufacturerPnpId)
+                && Objects.equals(mProductId, that.mProductId)
+                && Objects.equals(mModelYear, that.mModelYear)
+                && Objects.equals(mManufactureDate, that.mManufactureDate);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mName, mManufacturerPnpId, mProductId, mModelYear, mManufactureDate);
+    }
+
+    public static final Creator<DeviceProductInfo> CREATOR =
+            new Creator<DeviceProductInfo>() {
+                @Override
+                public DeviceProductInfo createFromParcel(Parcel in) {
+                    return new DeviceProductInfo(in);
+                }
+
+                @Override
+                public DeviceProductInfo[] newArray(int size) {
+                    return new DeviceProductInfo[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mName);
+        dest.writeString(mManufacturerPnpId);
+        dest.writeValue(mProductId);
+        dest.writeValue(mModelYear);
+        dest.writeValue(mManufactureDate);
+    }
+
+    /**
+     * Stores information about the date of manufacture.
+     *
+     * @hide
+     */
+    public static class ManufactureDate implements Parcelable {
+        private final Integer mWeek;
+        private final Integer mYear;
+
+        public ManufactureDate(Integer week, Integer year) {
+            mWeek = week;
+            mYear = year;
+        }
+
+        protected ManufactureDate(Parcel in) {
+            mWeek = (Integer) in.readValue(null);
+            mYear = (Integer) in.readValue(null);
+        }
+
+        @Override
+        public void writeToParcel(Parcel dest, int flags) {
+            dest.writeValue(mWeek);
+            dest.writeValue(mYear);
+        }
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        public static final Creator<ManufactureDate> CREATOR =
+                new Creator<ManufactureDate>() {
+                    @Override
+                    public ManufactureDate createFromParcel(Parcel in) {
+                        return new ManufactureDate(in);
+                    }
+
+                    @Override
+                    public ManufactureDate[] newArray(int size) {
+                        return new ManufactureDate[size];
+                    }
+                };
+
+        public int getYear() {
+            return mYear;
+        }
+
+        public int getWeek() {
+            return mWeek;
+        }
+
+        @Override
+        public String toString() {
+            return "ManufactureDate{week=" + mWeek + ", year=" + mYear + '}';
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) return true;
+            if (o == null || getClass() != o.getClass()) return false;
+            ManufactureDate that = (ManufactureDate) o;
+            return Objects.equals(mWeek, that.mWeek) && Objects.equals(mYear, that.mYear);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(mWeek, mYear);
+        }
+    }
+}
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 3a0660d..9b9889e 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -97,8 +97,10 @@
         }
 
         @Override // binder call
-        public void onAuthenticationSucceeded(long deviceId, Face face, int userId) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, face).sendToTarget();
+        public void onAuthenticationSucceeded(long deviceId, Face face, int userId,
+                boolean isStrongBiometric) {
+            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 0,
+                    face).sendToTarget();
         }
 
         @Override // binder call
@@ -814,6 +816,7 @@
         private Face mFace;
         private CryptoObject mCryptoObject;
         private int mUserId;
+        private boolean mIsStrongBiometric;
 
         /**
          * Authentication result
@@ -822,10 +825,12 @@
          * @param face   the recognized face data, if allowed.
          * @hide
          */
-        public AuthenticationResult(CryptoObject crypto, Face face, int userId) {
+        public AuthenticationResult(CryptoObject crypto, Face face, int userId,
+                boolean isStrongBiometric) {
             mCryptoObject = crypto;
             mFace = face;
             mUserId = userId;
+            mIsStrongBiometric = isStrongBiometric;
         }
 
         /**
@@ -857,6 +862,16 @@
         public int getUserId() {
             return mUserId;
         }
+
+        /**
+         * Check whether the strength of the face modality associated with this operation is strong
+         * (i.e. not weak or convenience).
+         *
+         * @hide
+         */
+        public boolean isStrongBiometric() {
+            return mIsStrongBiometric;
+        }
     }
 
     /**
@@ -1056,7 +1071,8 @@
                             msg.arg2 /* vendorCode */);
                     break;
                 case MSG_AUTHENTICATION_SUCCEEDED:
-                    sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */);
+                    sendAuthenticatedSucceeded((Face) msg.obj, msg.arg1 /* userId */,
+                            msg.arg2 == 1 /* isStrongBiometric */);
                     break;
                 case MSG_AUTHENTICATION_FAILED:
                     sendAuthenticatedFailed();
@@ -1133,10 +1149,10 @@
         }
     }
 
-    private void sendAuthenticatedSucceeded(Face face, int userId) {
+    private void sendAuthenticatedSucceeded(Face face, int userId, boolean isStrongBiometric) {
         if (mAuthenticationCallback != null) {
             final AuthenticationResult result =
-                    new AuthenticationResult(mCryptoObject, face, userId);
+                    new AuthenticationResult(mCryptoObject, face, userId, isStrongBiometric);
             mAuthenticationCallback.onAuthenticationSucceeded(result);
         }
     }
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 8ba2473..6318274 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -110,4 +110,7 @@
     void getFeature(int userId, int feature, IFaceServiceReceiver receiver, String opPackageName);
 
     void userActivity();
+
+    // Initialize the OEM configured biometric strength
+    void initConfiguredStrength(int strength);
 }
diff --git a/core/java/android/hardware/face/IFaceServiceReceiver.aidl b/core/java/android/hardware/face/IFaceServiceReceiver.aidl
index 10f9c43..7582308 100644
--- a/core/java/android/hardware/face/IFaceServiceReceiver.aidl
+++ b/core/java/android/hardware/face/IFaceServiceReceiver.aidl
@@ -24,7 +24,8 @@
 oneway interface IFaceServiceReceiver {
     void onEnrollResult(long deviceId, int faceId, int remaining);
     void onAcquired(long deviceId, int acquiredInfo, int vendorCode);
-    void onAuthenticationSucceeded(long deviceId, in Face face, int userId);
+    void onAuthenticationSucceeded(long deviceId, in Face face, int userId,
+            boolean isStrongBiometric);
     void onAuthenticationFailed(long deviceId);
     void onError(long deviceId, int error, int vendorCode);
     void onRemoved(long deviceId, int faceId, int remaining);
diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java
index f301a5c..dc8ea5e 100644
--- a/core/java/android/hardware/fingerprint/FingerprintManager.java
+++ b/core/java/android/hardware/fingerprint/FingerprintManager.java
@@ -176,6 +176,7 @@
         private Fingerprint mFingerprint;
         private CryptoObject mCryptoObject;
         private int mUserId;
+        private boolean mIsStrongBiometric;
 
         /**
          * Authentication result
@@ -184,10 +185,12 @@
          * @param fingerprint the recognized fingerprint data, if allowed.
          * @hide
          */
-        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId) {
+        public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint, int userId,
+                boolean isStrongBiometric) {
             mCryptoObject = crypto;
             mFingerprint = fingerprint;
             mUserId = userId;
+            mIsStrongBiometric = isStrongBiometric;
         }
 
         /**
@@ -211,6 +214,15 @@
          * @hide
          */
         public int getUserId() { return mUserId; }
+
+        /**
+         * Check whether the strength of the fingerprint modality associated with this operation is
+         * strong (i.e. not weak or convenience).
+         * @hide
+         */
+        public boolean isStrongBiometric() {
+            return mIsStrongBiometric;
+        }
     };
 
     /**
@@ -833,7 +845,8 @@
                             msg.arg2 /* vendorCode */);
                     break;
                 case MSG_AUTHENTICATION_SUCCEEDED:
-                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */);
+                    sendAuthenticatedSucceeded((Fingerprint) msg.obj, msg.arg1 /* userId */,
+                            msg.arg2 == 1 /* isStrongBiometric */);
                     break;
                 case MSG_AUTHENTICATION_FAILED:
                     sendAuthenticatedFailed();
@@ -890,10 +903,10 @@
         }
     }
 
-    private void sendAuthenticatedSucceeded(Fingerprint fp, int userId) {
+    private void sendAuthenticatedSucceeded(Fingerprint fp, int userId, boolean isStrongBiometric) {
         if (mAuthenticationCallback != null) {
             final AuthenticationResult result =
-                    new AuthenticationResult(mCryptoObject, fp, userId);
+                    new AuthenticationResult(mCryptoObject, fp, userId, isStrongBiometric);
             mAuthenticationCallback.onAuthenticationSucceeded(result);
         }
     }
@@ -1078,8 +1091,10 @@
         }
 
         @Override // binder call
-        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId) {
-            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, 0, fp).sendToTarget();
+        public void onAuthenticationSucceeded(long deviceId, Fingerprint fp, int userId,
+                boolean isStrongBiometric) {
+            mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, userId, isStrongBiometric ? 1 : 0,
+                    fp).sendToTarget();
         }
 
         @Override // binder call
diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
index f2ffd08d..0285448 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl
@@ -113,4 +113,7 @@
 
     // Removes a callback set by addClientActiveCallback
     void removeClientActiveCallback(IFingerprintClientActiveCallback callback);
+
+    // Initialize the OEM configured biometric strength
+    void initConfiguredStrength(int strength);
 }
diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
index cf1c94e..4412cee 100644
--- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
+++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl
@@ -24,7 +24,8 @@
 oneway interface IFingerprintServiceReceiver {
     void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining);
     void onAcquired(long deviceId, int acquiredInfo, int vendorCode);
-    void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId);
+    void onAuthenticationSucceeded(long deviceId, in Fingerprint fp, int userId,
+            boolean isStrongBiometric);
     void onAuthenticationFailed(long deviceId);
     void onError(long deviceId, int error, int vendorCode);
     void onRemoved(long deviceId, int fingerId, int groupId, int remaining);
diff --git a/core/java/android/hardware/iris/IIrisService.aidl b/core/java/android/hardware/iris/IIrisService.aidl
index 8cf3c13..5ef0a0c 100644
--- a/core/java/android/hardware/iris/IIrisService.aidl
+++ b/core/java/android/hardware/iris/IIrisService.aidl
@@ -21,4 +21,6 @@
  * @hide
  */
 interface IIrisService {
-}
\ No newline at end of file
+    // Initialize the OEM configured biometric strength
+    void initConfiguredStrength(int strength);
+}
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 086db10..d16f070 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -18,6 +18,7 @@
 package android.hardware.usb;
 
 import android.Manifest;
+import android.annotation.LongDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresFeature;
@@ -337,12 +338,14 @@
      * Code for the mtp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_MTP = GadgetFunction.MTP;
 
     /**
      * Code for the ptp usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_PTP = GadgetFunction.PTP;
 
     /**
@@ -356,24 +359,28 @@
      * Code for the midi usb function. Passed as a mask into {@link #setCurrentFunctions(long)}
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_MIDI = GadgetFunction.MIDI;
 
     /**
      * Code for the accessory usb function.
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_ACCESSORY = GadgetFunction.ACCESSORY;
 
     /**
      * Code for the audio source usb function.
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_AUDIO_SOURCE = GadgetFunction.AUDIO_SOURCE;
 
     /**
      * Code for the adb usb function.
      * {@hide}
      */
+    @SystemApi
     public static final long FUNCTION_ADB = GadgetFunction.ADB;
 
     /**
@@ -399,6 +406,20 @@
         FUNCTION_NAME_TO_CODE.put(UsbManager.USB_FUNCTION_NCM, FUNCTION_NCM);
     }
 
+    /** @hide */
+    @LongDef(flag = true, prefix = { "FUNCTION_" }, value = {
+            FUNCTION_NONE,
+            FUNCTION_MTP,
+            FUNCTION_PTP,
+            FUNCTION_RNDIS,
+            FUNCTION_MIDI,
+            FUNCTION_ACCESSORY,
+            FUNCTION_AUDIO_SOURCE,
+            FUNCTION_ADB,
+            FUNCTION_NCM,
+    })
+    public @interface UsbFunctionMode {}
+
     private final Context mContext;
     private final IUsbManager mService;
 
@@ -721,7 +742,7 @@
      */
     @SystemApi
     @RequiresPermission(Manifest.permission.MANAGE_USB)
-    public void setCurrentFunctions(long functions) {
+    public void setCurrentFunctions(@UsbFunctionMode long functions) {
         try {
             mService.setCurrentFunctions(functions);
         } catch (RemoteException e) {
diff --git a/core/java/android/inputmethodservice/IInputMethodWrapper.java b/core/java/android/inputmethodservice/IInputMethodWrapper.java
index 2a441de..f0b1eaa 100644
--- a/core/java/android/inputmethodservice/IInputMethodWrapper.java
+++ b/core/java/android/inputmethodservice/IInputMethodWrapper.java
@@ -19,7 +19,6 @@
 import android.annotation.BinderThread;
 import android.annotation.MainThread;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.Binder;
@@ -29,7 +28,6 @@
 import android.os.ResultReceiver;
 import android.util.Log;
 import android.view.InputChannel;
-import android.view.autofill.AutofillId;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
 import android.view.inputmethod.InputConnection;
@@ -46,6 +44,7 @@
 import com.android.internal.view.IInputMethod;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 import com.android.internal.view.InputConnectionWrapper;
 
 import java.io.FileDescriptor;
@@ -233,8 +232,9 @@
                 return;
             case DO_CREATE_INLINE_SUGGESTIONS_REQUEST:
                 args = (SomeArgs) msg.obj;
-                inputMethod.onCreateInlineSuggestionsRequest((ComponentName) args.arg1,
-                        (AutofillId) args.arg2, (IInlineSuggestionsRequestCallback) args.arg3);
+                inputMethod.onCreateInlineSuggestionsRequest(
+                        (InlineSuggestionsRequestInfo) args.arg1,
+                        (IInlineSuggestionsRequestCallback) args.arg2);
                 return;
 
         }
@@ -279,11 +279,10 @@
 
     @BinderThread
     @Override
-    public void onCreateInlineSuggestionsRequest(ComponentName componentName, AutofillId autofillId,
+    public void onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo,
             IInlineSuggestionsRequestCallback cb) {
         mCaller.executeOrSendMessage(
-                mCaller.obtainMessageOOO(DO_CREATE_INLINE_SUGGESTIONS_REQUEST, componentName,
-                        autofillId, cb));
+                mCaller.obtainMessageOO(DO_CREATE_INLINE_SUGGESTIONS_REQUEST, requestInfo, cb));
     }
 
     @BinderThread
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index b1aa67e..20a4ab3 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -34,7 +34,6 @@
 import android.app.ActivityManager;
 import android.app.Dialog;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
@@ -74,7 +73,6 @@
 import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.view.animation.AnimationUtils;
-import android.view.autofill.AutofillId;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.CursorAnchorInfo;
 import android.view.inputmethod.EditorInfo;
@@ -99,6 +97,7 @@
 import com.android.internal.inputmethod.InputMethodPrivilegedOperations;
 import com.android.internal.inputmethod.InputMethodPrivilegedOperationsRegistry;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -526,12 +525,13 @@
          */
         @MainThread
         @Override
-        public void onCreateInlineSuggestionsRequest(ComponentName componentName,
-                AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
+        public void onCreateInlineSuggestionsRequest(
+                @NonNull InlineSuggestionsRequestInfo requestInfo,
+                @NonNull IInlineSuggestionsRequestCallback cb) {
             if (DEBUG) {
                 Log.d(TAG, "InputMethodService received onCreateInlineSuggestionsRequest()");
             }
-            handleOnCreateInlineSuggestionsRequest(componentName, cb);
+            handleOnCreateInlineSuggestionsRequest(requestInfo, cb);
         }
 
         /**
@@ -742,11 +742,14 @@
 
     // TODO(b/137800469): Add detailed docs explaining the inline suggestions process.
     /**
-     * Returns an {@link InlineSuggestionsRequest} to be sent to Autofill.
+     * This method should be implemented by subclass which supports displaying autofill inline
+     * suggestion.
      *
-     * <p>Should be implemented by subclasses.</p>
+     * @param uiExtras the extras that contain the UI renderer related information
+     * @return an {@link InlineSuggestionsRequest} to be sent to Autofill.
      */
-    public @Nullable InlineSuggestionsRequest onCreateInlineSuggestionsRequest() {
+    @Nullable
+    public InlineSuggestionsRequest onCreateInlineSuggestionsRequest(@NonNull Bundle uiExtras) {
         return null;
     }
 
@@ -764,7 +767,8 @@
     }
 
     @MainThread
-    private void handleOnCreateInlineSuggestionsRequest(@NonNull ComponentName componentName,
+    private void handleOnCreateInlineSuggestionsRequest(
+            @NonNull InlineSuggestionsRequestInfo requestInfo,
             @NonNull IInlineSuggestionsRequestCallback callback) {
         if (!mInputStarted) {
             try {
@@ -779,8 +783,9 @@
         if (mInlineSuggestionSession != null) {
             mInlineSuggestionSession.invalidateSession();
         }
-        mInlineSuggestionSession = new InlineSuggestionSession(componentName, callback,
-                this::getEditorInfoPackageName, this::onCreateInlineSuggestionsRequest,
+        mInlineSuggestionSession = new InlineSuggestionSession(requestInfo.getComponentName(),
+                callback, this::getEditorInfoPackageName,
+                () -> onCreateInlineSuggestionsRequest(requestInfo.getUiExtras()),
                 this::getHostInputToken, this::onInlineSuggestionsResponse);
     }
 
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index ea26ede..62eff45 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1279,7 +1279,8 @@
     @UnsupportedAppUsage
     public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
         try {
-            return mService.getDefaultNetworkCapabilitiesForUser(userId);
+            return mService.getDefaultNetworkCapabilitiesForUser(
+                    userId, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -1361,7 +1362,7 @@
     @Nullable
     public NetworkCapabilities getNetworkCapabilities(@Nullable Network network) {
         try {
-            return mService.getNetworkCapabilities(network);
+            return mService.getNetworkCapabilities(network, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -4039,10 +4040,9 @@
             @NonNull PendingIntent operation) {
         printStackTrace();
         checkPendingIntentNotNull(operation);
-        final String callingPackageName = mContext.getOpPackageName();
         try {
             mService.pendingRequestForNetwork(
-                    request.networkCapabilities, operation, callingPackageName);
+                    request.networkCapabilities, operation, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
@@ -4154,10 +4154,9 @@
             @NonNull PendingIntent operation) {
         printStackTrace();
         checkPendingIntentNotNull(operation);
-        final String callingPackageName = mContext.getOpPackageName();
         try {
             mService.pendingListenForNetwork(
-                    request.networkCapabilities, operation, callingPackageName);
+                    request.networkCapabilities, operation, mContext.getOpPackageName());
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         } catch (ServiceSpecificException e) {
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index 1c7628f..d84d05d 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -60,7 +60,8 @@
     NetworkInfo[] getAllNetworkInfo();
     Network getNetworkForType(int networkType);
     Network[] getAllNetworks();
-    NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId);
+    NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
+            int userId, String callingPackageName);
 
     boolean isNetworkSupported(int networkType);
 
@@ -69,7 +70,7 @@
     LinkProperties getLinkPropertiesForType(int networkType);
     LinkProperties getLinkProperties(in Network network);
 
-    NetworkCapabilities getNetworkCapabilities(in Network network);
+    NetworkCapabilities getNetworkCapabilities(in Network network, String callingPackageName);
 
     @UnsupportedAppUsage
     NetworkState[] getAllNetworkState();
diff --git a/core/java/android/net/Ikev2VpnProfile.java b/core/java/android/net/Ikev2VpnProfile.java
index 42b4da1..f19a341 100644
--- a/core/java/android/net/Ikev2VpnProfile.java
+++ b/core/java/android/net/Ikev2VpnProfile.java
@@ -25,7 +25,10 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Process;
 import android.security.Credentials;
+import android.security.KeyStore;
+import android.security.keystore.AndroidKeyStoreProvider;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.VpnProfile;
@@ -59,6 +62,11 @@
  *     Exchange, Version 2 (IKEv2)</a>
  */
 public final class Ikev2VpnProfile extends PlatformVpnProfile {
+    /** Prefix for when a Private Key is an alias to look for in KeyStore @hide */
+    public static final String PREFIX_KEYSTORE_ALIAS = "KEYSTORE_ALIAS:";
+    /** Prefix for when a Private Key is stored directly in the profile @hide */
+    public static final String PREFIX_INLINE = "INLINE:";
+
     private static final String MISSING_PARAM_MSG_TMPL = "Required parameter was not provided: %s";
     private static final String EMPTY_CERT = "";
 
@@ -339,7 +347,8 @@
                 break;
             case TYPE_IKEV2_IPSEC_RSA:
                 profile.ipsecUserCert = certificateToPemString(mUserCert);
-                profile.ipsecSecret = encodeForIpsecSecret(mRsaPrivateKey.getEncoded());
+                profile.ipsecSecret =
+                        PREFIX_INLINE + encodeForIpsecSecret(mRsaPrivateKey.getEncoded());
                 profile.ipsecCaCert =
                         mServerRootCaCert == null ? "" : certificateToPemString(mServerRootCaCert);
                 break;
@@ -360,6 +369,22 @@
     @NonNull
     public static Ikev2VpnProfile fromVpnProfile(@NonNull VpnProfile profile)
             throws IOException, GeneralSecurityException {
+        return fromVpnProfile(profile, null);
+    }
+
+    /**
+     * Builds the Ikev2VpnProfile from the given profile.
+     *
+     * @param profile the source VpnProfile to build from
+     * @param keyStore the Android Keystore instance to use to retrieve the private key, or null if
+     *     the private key is PEM-encoded into the profile.
+     * @return The IKEv2/IPsec VPN profile
+     * @hide
+     */
+    @NonNull
+    public static Ikev2VpnProfile fromVpnProfile(
+            @NonNull VpnProfile profile, @Nullable KeyStore keyStore)
+            throws IOException, GeneralSecurityException {
         final Builder builder = new Builder(profile.server, profile.ipsecIdentifier);
         builder.setProxy(profile.proxy);
         builder.setAllowedAlgorithms(profile.getAllowedAlgorithms());
@@ -378,8 +403,21 @@
                 builder.setAuthPsk(decodeFromIpsecSecret(profile.ipsecSecret));
                 break;
             case TYPE_IKEV2_IPSEC_RSA:
+                final PrivateKey key;
+                if (profile.ipsecSecret.startsWith(PREFIX_KEYSTORE_ALIAS)) {
+                    Objects.requireNonNull(keyStore, "Missing Keystore for aliased PrivateKey");
+
+                    final String alias =
+                            profile.ipsecSecret.substring(PREFIX_KEYSTORE_ALIAS.length());
+                    key = AndroidKeyStoreProvider.loadAndroidKeyStorePrivateKeyFromKeystore(
+                            keyStore, alias, Process.myUid());
+                } else if (profile.ipsecSecret.startsWith(PREFIX_INLINE)) {
+                    key = getPrivateKey(profile.ipsecSecret.substring(PREFIX_INLINE.length()));
+                } else {
+                    throw new IllegalArgumentException("Invalid RSA private key prefix");
+                }
+
                 final X509Certificate userCert = certificateFromPemString(profile.ipsecUserCert);
-                final PrivateKey key = getPrivateKey(profile.ipsecSecret);
                 final X509Certificate serverRootCa = certificateFromPemString(profile.ipsecCaCert);
                 builder.setAuthDigitalSignature(userCert, key, serverRootCa);
                 break;
@@ -391,6 +429,39 @@
     }
 
     /**
+     * Validates that the VpnProfile is acceptable for the purposes of an Ikev2VpnProfile.
+     *
+     * @hide
+     */
+    public static boolean isValidVpnProfile(@NonNull VpnProfile profile) {
+        if (profile.server.isEmpty() || profile.ipsecIdentifier.isEmpty()) {
+            return false;
+        }
+
+        switch (profile.type) {
+            case TYPE_IKEV2_IPSEC_USER_PASS:
+                if (profile.username.isEmpty() || profile.password.isEmpty()) {
+                    return false;
+                }
+                break;
+            case TYPE_IKEV2_IPSEC_PSK:
+                if (profile.ipsecSecret.isEmpty()) {
+                    return false;
+                }
+                break;
+            case TYPE_IKEV2_IPSEC_RSA:
+                if (profile.ipsecSecret.isEmpty() || profile.ipsecUserCert.isEmpty()) {
+                    return false;
+                }
+                break;
+            default:
+                return false;
+        }
+
+        return true;
+    }
+
+    /**
      * Converts a X509 Certificate to a PEM-formatted string.
      *
      * <p>Must be public due to runtime-package restrictions.
@@ -432,7 +503,6 @@
 
     /** @hide */
     @NonNull
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
     public static String encodeForIpsecSecret(@NonNull byte[] secret) {
         checkNotNull(secret, MISSING_PARAM_MSG_TMPL, "secret");
 
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index f8b51dd..83f9980 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -830,6 +830,23 @@
      * <p>This field keeps track of the UID of the app that created this network and is in charge of
      * its lifecycle. This could be the UID of apps such as the Wifi network suggestor, the running
      * VPN, or Carrier Service app managing a cellular data connection.
+     *
+     * <p>For NetworkCapability instances being sent from ConnectivityService, this value MUST be
+     * reset to Process.INVALID_UID unless all the following conditions are met:
+     *
+     * <ol>
+     *   <li>The destination app is the network owner
+     *   <li>The destination app has the ACCESS_FINE_LOCATION permission granted
+     *   <li>The user's location toggle is on
+     * </ol>
+     *
+     * This is because the owner UID is location-sensitive. The apps that request a network could
+     * know where the device is if they can tell for sure the system has connected to the network
+     * they requested.
+     *
+     * <p>This is populated by the network agents and for the NetworkCapabilities instance sent by
+     * an app to the System Server, the value MUST be reset to Process.INVALID_UID by the system
+     * server.
      */
     private int mOwnerUid = Process.INVALID_UID;
 
@@ -842,7 +859,16 @@
     }
 
     /**
-     * Retrieves the UID of the owner app.
+     * Retrieves the UID of the app that owns this network.
+     *
+     * <p>For user privacy reasons, this field will only be populated if:
+     *
+     * <ol>
+     *   <li>The calling app is the network owner
+     *   <li>The calling app has the ACCESS_FINE_LOCATION permission granted
+     *   <li>The user's location toggle is on
+     * </ol>
+     *
      */
     public int getOwnerUid() {
         return mOwnerUid;
@@ -880,8 +906,9 @@
      * @param administratorUids the UIDs to be set as administrators of this Network.
      * @hide
      */
+    @NonNull
     @SystemApi
-    public @NonNull NetworkCapabilities setAdministratorUids(
+    public NetworkCapabilities setAdministratorUids(
             @NonNull final List<Integer> administratorUids) {
         mAdministratorUids.clear();
         mAdministratorUids.addAll(administratorUids);
diff --git a/core/java/android/net/VpnManager.java b/core/java/android/net/VpnManager.java
index f19ba0f..2041cfb 100644
--- a/core/java/android/net/VpnManager.java
+++ b/core/java/android/net/VpnManager.java
@@ -126,7 +126,11 @@
         return getIntentForConfirmation();
     }
 
-    /** Delete the VPN profile configuration that was provisioned by the calling app */
+    /**
+     * Delete the VPN profile configuration that was provisioned by the calling app
+     *
+     * @throws SecurityException if this would violate user settings
+     */
     public void deleteProvisionedVpnProfile() {
         try {
             mService.deleteVpnProfile(mContext.getOpPackageName());
diff --git a/core/java/android/os/IThermalService.aidl b/core/java/android/os/IThermalService.aidl
index 8c98960..ad00233 100644
--- a/core/java/android/os/IThermalService.aidl
+++ b/core/java/android/os/IThermalService.aidl
@@ -103,4 +103,11 @@
       * {@hide}
       */
     List<CoolingDevice> getCurrentCoolingDevicesWithType(in int type);
+
+    /**
+     * @param forecastSeconds how many seconds ahead to forecast the provided headroom
+     * @return forecasted thermal headroom, normalized such that 1.0 indicates that throttling will
+     *     occur; returns NaN if the headroom or forecast is unavailable
+     */
+    float getThermalHeadroom(int forecastSeconds);
 }
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a8fa6db..199b5d5 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -18,7 +18,9 @@
 
 import android.Manifest.permission;
 import android.annotation.CallbackExecutor;
+import android.annotation.CurrentTimeMillisLong;
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -39,6 +41,7 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * This class gives you control of the power state of the device.
@@ -916,20 +919,22 @@
     final IPowerManager mService;
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
     final Handler mHandler;
+    final IThermalService mThermalService;
 
     /** We lazily initialize it.*/
     private DeviceIdleManager mDeviceIdleManager;
 
-    IThermalService mThermalService;
     private final ArrayMap<OnThermalStatusChangedListener, IThermalStatusListener>
             mListenerMap = new ArrayMap<>();
 
     /**
      * {@hide}
      */
-    public PowerManager(Context context, IPowerManager service, Handler handler) {
+    public PowerManager(Context context, IPowerManager service, IThermalService thermalService,
+            Handler handler) {
         mContext = context;
         mService = service;
+        mThermalService = thermalService;
         mHandler = handler;
     }
 
@@ -1877,18 +1882,11 @@
      * thermal throttling.
      */
     public @ThermalStatus int getCurrentThermalStatus() {
-        synchronized (this) {
-            if (mThermalService == null) {
-                mThermalService = IThermalService.Stub.asInterface(
-                        ServiceManager.getService(Context.THERMAL_SERVICE));
-            }
-            try {
-                return mThermalService.getCurrentThermalStatus();
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        try {
+            return mThermalService.getCurrentThermalStatus();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
-
     }
 
     /**
@@ -1915,13 +1913,7 @@
      */
     public void addThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
-        synchronized (this) {
-            if (mThermalService == null) {
-                mThermalService = IThermalService.Stub.asInterface(
-                        ServiceManager.getService(Context.THERMAL_SERVICE));
-            }
-            this.addThermalStatusListener(mContext.getMainExecutor(), listener);
-        }
+        this.addThermalStatusListener(mContext.getMainExecutor(), listener);
     }
 
     /**
@@ -1934,35 +1926,29 @@
             @NonNull OnThermalStatusChangedListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         Preconditions.checkNotNull(executor, "executor cannot be null");
-        synchronized (this) {
-            if (mThermalService == null) {
-                mThermalService = IThermalService.Stub.asInterface(
-                        ServiceManager.getService(Context.THERMAL_SERVICE));
-            }
-            Preconditions.checkArgument(!mListenerMap.containsKey(listener),
-                    "Listener already registered: " + listener);
-            IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
-                @Override
-                public void onStatusChange(int status) {
-                    final long token = Binder.clearCallingIdentity();
-                    try {
-                        executor.execute(() -> {
-                            listener.onThermalStatusChanged(status);
-                        });
-                    } finally {
-                        Binder.restoreCallingIdentity(token);
-                    }
+        Preconditions.checkArgument(!mListenerMap.containsKey(listener),
+                "Listener already registered: " + listener);
+        IThermalStatusListener internalListener = new IThermalStatusListener.Stub() {
+            @Override
+            public void onStatusChange(int status) {
+                final long token = Binder.clearCallingIdentity();
+                try {
+                    executor.execute(() -> {
+                        listener.onThermalStatusChanged(status);
+                    });
+                } finally {
+                    Binder.restoreCallingIdentity(token);
                 }
-            };
-            try {
-                if (mThermalService.registerThermalStatusListener(internalListener)) {
-                    mListenerMap.put(listener, internalListener);
-                } else {
-                    throw new RuntimeException("Listener failed to set");
-                }
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
             }
+        };
+        try {
+            if (mThermalService.registerThermalStatusListener(internalListener)) {
+                mListenerMap.put(listener, internalListener);
+            } else {
+                throw new RuntimeException("Listener failed to set");
+            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
@@ -1973,22 +1959,72 @@
      */
     public void removeThermalStatusListener(@NonNull OnThermalStatusChangedListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
-        synchronized (this) {
-            if (mThermalService == null) {
-                mThermalService = IThermalService.Stub.asInterface(
-                        ServiceManager.getService(Context.THERMAL_SERVICE));
+        IThermalStatusListener internalListener = mListenerMap.get(listener);
+        Preconditions.checkArgument(internalListener != null, "Listener was not added");
+        try {
+            if (mThermalService.unregisterThermalStatusListener(internalListener)) {
+                mListenerMap.remove(listener);
+            } else {
+                throw new RuntimeException("Listener failed to remove");
             }
-            IThermalStatusListener internalListener = mListenerMap.get(listener);
-            Preconditions.checkArgument(internalListener != null, "Listener was not added");
-            try {
-                if (mThermalService.unregisterThermalStatusListener(internalListener)) {
-                    mListenerMap.remove(listener);
-                } else {
-                    throw new RuntimeException("Listener failed to remove");
-                }
-            } catch (RemoteException e) {
-                throw e.rethrowFromSystemServer();
-            }
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    @CurrentTimeMillisLong
+    private final AtomicLong mLastHeadroomUpdate = new AtomicLong(0L);
+    private static final int MINIMUM_HEADROOM_TIME_MILLIS = 500;
+
+    /**
+     * Provides an estimate of how much thermal headroom the device currently has before hitting
+     * severe throttling.
+     *
+     * Note that this only attempts to track the headroom of slow-moving sensors, such as the skin
+     * temperature sensor. This means that there is no benefit to calling this function more
+     * frequently than about once per second, and attempts to call significantly more frequently may
+     * result in the function returning {@code NaN}.
+     *
+     * In addition, in order to be able to provide an accurate forecast, the system does not attempt
+     * to forecast until it has multiple temperature samples from which to extrapolate. This should
+     * only take a few seconds from the time of the first call, but during this time, no forecasting
+     * will occur, and the current headroom will be returned regardless of the value of
+     * {@code forecastSeconds}.
+     *
+     * The value returned is a non-negative float that represents how much of the thermal envelope
+     * is in use (or is forecasted to be in use). A value of 1.0 indicates that the device is (or
+     * will be) throttled at {@link #THERMAL_STATUS_SEVERE}. Such throttling can affect the CPU,
+     * GPU, and other subsystems. Values may exceed 1.0, but there is no implied mapping to specific
+     * thermal status levels beyond that point. This means that values greater than 1.0 may
+     * correspond to {@link #THERMAL_STATUS_SEVERE}, but may also represent heavier throttling.
+     *
+     * A value of 0.0 corresponds to a fixed distance from 1.0, but does not correspond to any
+     * particular thermal status or temperature. Values on (0.0, 1.0] may be expected to scale
+     * linearly with temperature, though temperature changes over time are typically not linear.
+     * Negative values will be clamped to 0.0 before returning.
+     *
+     * @param forecastSeconds how many seconds in the future to forecast. Given that device
+     *                        conditions may change at any time, forecasts from further in the
+     *                        future will likely be less accurate than forecasts in the near future.
+     * @return a value greater than or equal to 0.0 where 1.0 indicates the SEVERE throttling
+     *         threshold, as described above. Returns NaN if the device does not support this
+     *         functionality or if this function is called significantly faster than once per
+     *         second.
+     */
+    public float getThermalHeadroom(@IntRange(from = 0, to = 60) int forecastSeconds) {
+        // Rate-limit calls into the thermal service
+        long now = SystemClock.elapsedRealtime();
+        long timeSinceLastUpdate = now - mLastHeadroomUpdate.get();
+        if (timeSinceLastUpdate < MINIMUM_HEADROOM_TIME_MILLIS) {
+            return Float.NaN;
+        }
+
+        try {
+            float forecast = mThermalService.getThermalHeadroom(forecastSeconds);
+            mLastHeadroomUpdate.set(SystemClock.elapsedRealtime());
+            return forecast;
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
         }
     }
 
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index be22458..d60820e 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import static java.nio.charset.StandardCharsets.UTF_8;
 
 import android.annotation.NonNull;
@@ -33,6 +35,7 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.PackageManager;
+import android.hardware.display.DisplayManager;
 import android.provider.Settings;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -614,7 +617,8 @@
 
             // On TV, reboot quiescently if the screen is off
             if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_LEANBACK)) {
-                if (context.getDisplay().getState() != Display.STATE_ON) {
+                DisplayManager dm = context.getSystemService(DisplayManager.class);
+                if (dm.getDisplay(DEFAULT_DISPLAY).getState() != Display.STATE_ON) {
                     reason += ",quiescent";
                 }
             }
diff --git a/core/java/android/os/StrictMode.java b/core/java/android/os/StrictMode.java
index 3faaff7..e8af564 100644
--- a/core/java/android/os/StrictMode.java
+++ b/core/java/android/os/StrictMode.java
@@ -42,6 +42,7 @@
 import android.os.strictmode.ExplicitGcViolation;
 import android.os.strictmode.FileUriExposedViolation;
 import android.os.strictmode.ImplicitDirectBootViolation;
+import android.os.strictmode.IncorrectContextUseViolation;
 import android.os.strictmode.InstanceCountViolation;
 import android.os.strictmode.IntentReceiverLeakedViolation;
 import android.os.strictmode.LeakedClosableViolation;
@@ -250,6 +251,7 @@
             DETECT_VM_UNTAGGED_SOCKET,
             DETECT_VM_NON_SDK_API_USAGE,
             DETECT_VM_IMPLICIT_DIRECT_BOOT,
+            DETECT_VM_INCORRECT_CONTEXT_USE,
             PENALTY_GATHER,
             PENALTY_LOG,
             PENALTY_DIALOG,
@@ -289,6 +291,8 @@
     private static final int DETECT_VM_IMPLICIT_DIRECT_BOOT = 1 << 10;
     /** @hide */
     private static final int DETECT_VM_CREDENTIAL_PROTECTED_WHILE_LOCKED = 1 << 11;
+    /** @hide */
+    private static final int DETECT_VM_INCORRECT_CONTEXT_USE = 1 << 12;
 
     /** @hide */
     private static final int DETECT_VM_ALL = 0x0000ffff;
@@ -871,6 +875,9 @@
                 if (targetSdk >= Build.VERSION_CODES.Q) {
                     detectCredentialProtectedWhileLocked();
                 }
+                if (targetSdk >= Build.VERSION_CODES.R) {
+                    detectIncorrectContextUse();
+                }
 
                 // TODO: Decide whether to detect non SDK API usage beyond a certain API level.
                 // TODO: enable detectImplicitDirectBoot() once system is less noisy
@@ -1028,6 +1035,32 @@
             }
 
             /**
+             * Detect attempts to invoke a method on a {@link Context} that is not suited for such
+             * operation.
+             * <p>An example of this is trying to obtain an instance of visual service (e.g.
+             * {@link android.view.WindowManager}) from a non-visual {@link Context}. This is not
+             * allowed, since a non-visual {@link Context} is not adjusted to any visual area, and
+             * therefore can report incorrect metrics or resources.
+             * @see Context#getDisplay()
+             * @see Context#getSystemService(String)
+             * @hide
+             */
+            @TestApi
+            public @NonNull Builder detectIncorrectContextUse() {
+                return enable(DETECT_VM_INCORRECT_CONTEXT_USE);
+            }
+
+            /**
+             * Disable detection of incorrect context use.
+             * TODO(b/149790106): Fix usages and remove.
+             * @hide
+             */
+            @TestApi
+            public @NonNull Builder permitIncorrectContextUse() {
+                return disable(DETECT_VM_INCORRECT_CONTEXT_USE);
+            }
+
+            /**
              * Crashes the whole process on violation. This penalty runs at the end of all enabled
              * penalties so you'll still get your logging or other violations before the process
              * dies.
@@ -2057,6 +2090,11 @@
     }
 
     /** @hide */
+    public static boolean vmIncorrectContextUseEnabled() {
+        return (sVmPolicy.mask & DETECT_VM_INCORRECT_CONTEXT_USE) != 0;
+    }
+
+    /** @hide */
     public static void onSqliteObjectLeaked(String message, Throwable originStack) {
         onVmPolicyViolation(new SqliteObjectLeakedViolation(message, originStack));
     }
@@ -2130,6 +2168,11 @@
         onVmPolicyViolation(new ImplicitDirectBootViolation());
     }
 
+    /** @hide */
+    public static void onIncorrectContextUsed(String message, Throwable originStack) {
+        onVmPolicyViolation(new IncorrectContextUseViolation(message, originStack));
+    }
+
     /** Assume locked until we hear otherwise */
     private static volatile boolean sUserKeyUnlocked = false;
 
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 6d1f646..0f2060a 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -33,8 +33,8 @@
 import android.annotation.WorkerThread;
 import android.app.Activity;
 import android.app.ActivityManager;
-import android.app.admin.DevicePolicyManager;
 import android.app.PropertyInvalidatedCache;
+import android.app.admin.DevicePolicyManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -63,6 +63,7 @@
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 /**
  * Manages users and user details on a multi-user system. There are two major categories of
@@ -151,12 +152,23 @@
     public static final int QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED = 0x1;
 
     /**
+     * Flag passed to {@link #requestQuietModeEnabled} to request disabling quiet mode without
+     * asking for credentials. This is used when managed profile password is forgotten. It starts
+     * the user in locked state so that a direct boot aware DPC could reset the password.
+     * Should not be used together with
+     * {@link #QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED} or an exception will be thrown.
+     * @hide
+     */
+    public static final int QUIET_MODE_DISABLE_DONT_ASK_CREDENTIAL = 0x2;
+
+    /**
      * List of flags available for the {@link #requestQuietModeEnabled} method.
      * @hide
      */
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(flag = true, prefix = { "QUIET_MODE_" }, value = {
-            QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED })
+            QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED,
+            QUIET_MODE_DISABLE_DONT_ASK_CREDENTIAL})
     public @interface QuietModeFlag {}
 
     /**
@@ -2706,10 +2718,11 @@
             Manifest.permission.CREATE_USERS})
     @UserHandleAware
     public @Nullable UserHandle createProfile(@NonNull String name, @NonNull String userType,
-            @Nullable String[] disallowedPackages) throws UserOperationException {
+            @NonNull Set<String> disallowedPackages) throws UserOperationException {
         try {
             return mService.createProfileForUserWithThrow(name, userType, 0,
-                    mUserId, disallowedPackages).getUserHandle();
+                    mUserId, disallowedPackages.toArray(
+                            new String[disallowedPackages.size()])).getUserHandle();
         } catch (ServiceSpecificException e) {
             return returnNullOrThrowUserOperationException(e,
                     mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.R);
@@ -3343,19 +3356,46 @@
     }
 
     /**
-     * Returns a list of ids for profiles associated with the context user including the user
-     * itself.
+     * Returns a list of ids for enabled profiles associated with the context user including the
+     * user itself.
      *
-     * @param enabledOnly whether to return only {@link UserInfo#isEnabled() enabled} profiles
      * @return A non-empty list of UserHandles associated with the calling user.
-     *
      * @hide
      */
     @SystemApi
     @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
             Manifest.permission.CREATE_USERS}, conditional = true)
     @UserHandleAware
-    public @NonNull List<UserHandle> getUserProfiles(boolean enabledOnly) {
+    public @NonNull List<UserHandle> getEnabledProfiles() {
+        return getProfiles(true);
+    }
+
+    /**
+     * Returns a list of ids for all profiles associated with the context user including the user
+     * itself.
+     *
+     * @return A non-empty list of UserHandles associated with the calling user.
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS}, conditional = true)
+    @UserHandleAware
+    public @NonNull List<UserHandle> getAllProfiles() {
+        return getProfiles(false);
+    }
+
+    /**
+     * Returns a list of ids for profiles associated with the context user including the user
+     * itself.
+     *
+     * @param enabledOnly whether to return only {@link UserInfo#isEnabled() enabled} profiles
+     * @return A non-empty list of UserHandles associated with the calling user.
+     */
+    @RequiresPermission(anyOf = {Manifest.permission.MANAGE_USERS,
+            Manifest.permission.CREATE_USERS}, conditional = true)
+    @UserHandleAware
+    private @NonNull List<UserHandle> getProfiles(boolean enabledOnly) {
         final int[] userIds = getProfileIds(mUserId, enabledOnly);
         final List<UserHandle> result = new ArrayList<>(userIds.length);
         for (int userId : userIds) {
@@ -3521,12 +3561,13 @@
             boolean enableQuietMode, @NonNull UserHandle userHandle, IntentSender target) {
         return requestQuietModeEnabled(enableQuietMode, userHandle, target, 0);
     }
+
     /**
      * Similar to {@link #requestQuietModeEnabled(boolean, UserHandle)}, except you can specify
      * a target to start when user is unlocked. If {@code target} is specified, caller must have
      * the {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
-     * @see {@link #requestQuietModeEnabled(boolean, UserHandle)}
+     * @see #requestQuietModeEnabled(boolean, UserHandle)
      * @hide
      */
     public boolean requestQuietModeEnabled(
diff --git a/core/java/android/os/incremental/IncrementalStorage.java b/core/java/android/os/incremental/IncrementalStorage.java
index f4e1f96..dea495b 100644
--- a/core/java/android/os/incremental/IncrementalStorage.java
+++ b/core/java/android/os/incremental/IncrementalStorage.java
@@ -434,6 +434,11 @@
             signature = V4Signature.readFrom(input);
         }
 
+        if (!signature.isVersionSupported()) {
+            throw new IOException("v4 signature version " + signature.version
+                    + " is not supported");
+        }
+
         final byte[] rootHash = signature.verityRootHash;
         final byte[] additionalData = signature.v3Digest;
         final byte[] pkcs7Signature = signature.pkcs7SignatureBlock;
diff --git a/core/java/android/os/incremental/V4Signature.java b/core/java/android/os/incremental/V4Signature.java
index 6516917..17adfc8 100644
--- a/core/java/android/os/incremental/V4Signature.java
+++ b/core/java/android/os/incremental/V4Signature.java
@@ -31,7 +31,9 @@
  */
 public class V4Signature {
     public static final String EXT = ".idsig";
+    public static final int SUPPORTED_VERSION = 1;
 
+    public final int version;
     public final byte[] verityRootHash;
     public final byte[] v3Digest;
     public final byte[] pkcs7SignatureBlock;
@@ -71,20 +73,27 @@
         }
     }
 
+    boolean isVersionSupported() {
+        return this.version == SUPPORTED_VERSION;
+    }
+
     static V4Signature readFrom(DataInputStream stream) throws IOException {
+        final int version = stream.readInt();
         byte[] verityRootHash = readBytes(stream);
         byte[] v3Digest = readBytes(stream);
         byte[] pkcs7SignatureBlock = readBytes(stream);
-        return new V4Signature(verityRootHash, v3Digest, pkcs7SignatureBlock);
+        return new V4Signature(version, verityRootHash, v3Digest, pkcs7SignatureBlock);
     }
 
-    V4Signature(byte[] verityRootHash, byte[] v3Digest, byte[] pkcs7SignatureBlock) {
+    V4Signature(int version, byte[] verityRootHash, byte[] v3Digest, byte[] pkcs7SignatureBlock) {
+        this.version = version;
         this.verityRootHash = verityRootHash;
         this.v3Digest = v3Digest;
         this.pkcs7SignatureBlock = pkcs7SignatureBlock;
     }
 
     void writeTo(DataOutputStream stream) throws IOException {
+        stream.writeInt(this.version);
         writeBytes(stream, this.verityRootHash);
         writeBytes(stream, this.v3Digest);
         writeBytes(stream, this.pkcs7SignatureBlock);
diff --git a/core/java/android/os/storage/StorageManager.java b/core/java/android/os/storage/StorageManager.java
index 8d04df0..1454aac 100644
--- a/core/java/android/os/storage/StorageManager.java
+++ b/core/java/android/os/storage/StorageManager.java
@@ -29,6 +29,7 @@
 import static android.app.AppOpsManager.OP_WRITE_MEDIA_VIDEO;
 import static android.content.ContentResolver.DEPRECATE_DATA_PREFIX;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.os.UserHandle.PER_USER_RANGE;
 
 import android.annotation.BytesLong;
 import android.annotation.CallbackExecutor;
@@ -2324,17 +2325,34 @@
     private static final String XATTR_CACHE_TOMBSTONE = "user.cache_tombstone";
 
 
-   // Matches AID_MEDIA_RW in android_filesystem_config.h
-    private static final int QUOTA_PROJECT_ID_MEDIA_NONE = 1023;
+    // Project IDs below must match android_projectid_config.h
+    /**
+     * Default project ID for files on external storage
+     *
+     * {@hide}
+     */
+    public static final int PROJECT_ID_EXT_DEFAULT = 1000;
 
-    // Matches AID_MEDIA_IMAGE in android_filesystem_config.h
-    private static final int QUOTA_PROJECT_ID_MEDIA_IMAGE = 1057;
+    /**
+     * project ID for audio files on external storage
+     *
+     * {@hide}
+     */
+    public static final int PROJECT_ID_EXT_MEDIA_AUDIO = 1001;
 
-    // Matches AID_MEDIA_AUDIO in android_filesystem_config.h
-    private static final int QUOTA_PROJECT_ID_MEDIA_AUDIO = 1055;
+    /**
+     * project ID for video files on external storage
+     *
+     * {@hide}
+     */
+    public static final int PROJECT_ID_EXT_MEDIA_VIDEO = 1002;
 
-    // Matches AID_MEDIA_VIDEO in android_filesystem_config.h
-    private static final int QUOTA_PROJECT_ID_MEDIA_VIDEO = 1056;
+    /**
+     * project ID for image files on external storage
+     *
+     * {@hide}
+     */
+    public static final int PROJECT_ID_EXT_MEDIA_IMAGE = 1003;
 
     /**
      * Constant for use with
@@ -2388,6 +2406,11 @@
 
     private static native boolean setQuotaProjectId(String path, long projectId);
 
+    private static long getProjectIdForUser(int userId, int projectId) {
+        // Much like UserHandle.getUid(), store the user ID in the upper bits
+        return userId * PER_USER_RANGE + projectId;
+    }
+
     /**
      * Let StorageManager know that the quota type for a file on external storage should
      * be updated. Android tracks quotas for various media types. Consequently, this should be
@@ -2417,18 +2440,27 @@
             @QuotaType int quotaType) throws IOException {
         long projectId;
         final String filePath = path.getCanonicalPath();
+        final StorageVolume volume = getStorageVolume(path);
+        if (volume == null) {
+            throw new IllegalStateException("Failed to update quota type for " + filePath);
+        }
+
+        final int userId = volume.getOwner().getIdentifier();
+        if (userId < 0) {
+            throw new IllegalStateException("Failed to update quota type for " + filePath);
+        }
         switch (quotaType) {
             case QUOTA_TYPE_MEDIA_NONE:
-                projectId = QUOTA_PROJECT_ID_MEDIA_NONE;
+                projectId = getProjectIdForUser(userId, PROJECT_ID_EXT_DEFAULT);
                 break;
             case QUOTA_TYPE_MEDIA_AUDIO:
-                projectId = QUOTA_PROJECT_ID_MEDIA_AUDIO;
+                projectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_AUDIO);
                 break;
             case QUOTA_TYPE_MEDIA_VIDEO:
-                projectId = QUOTA_PROJECT_ID_MEDIA_VIDEO;
+                projectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_VIDEO);
                 break;
             case QUOTA_TYPE_MEDIA_IMAGE:
-                projectId = QUOTA_PROJECT_ID_MEDIA_IMAGE;
+                projectId = getProjectIdForUser(userId, PROJECT_ID_EXT_MEDIA_IMAGE);
                 break;
             default:
                 throw new IllegalArgumentException("Invalid quota type: " + quotaType);
diff --git a/core/java/android/os/storage/StorageManagerInternal.java b/core/java/android/os/storage/StorageManagerInternal.java
index e78aef5..a2def7f 100644
--- a/core/java/android/os/storage/StorageManagerInternal.java
+++ b/core/java/android/os/storage/StorageManagerInternal.java
@@ -16,9 +16,12 @@
 
 package android.os.storage;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.os.IVold;
 
+import java.util.Set;
+
 /**
  * Mount service local interface.
  *
@@ -97,6 +100,12 @@
     }
 
     /**
+     * Check if fuse is running in target user, if it's running then setup its obb directories.
+     * TODO: System server should store a list of active pids that obb is not mounted and use it.
+     */
+    public abstract void prepareObbDirs(int userId, Set<String> packageList, String processName);
+
+    /**
      * Add a listener to listen to reset event in StorageManagerService.
      *
      * @param listener The listener that will be notified on reset events.
@@ -124,4 +133,14 @@
      * legacy storage, {@code false} otherwise.
      */
     public abstract boolean hasLegacyExternalStorage(int uid);
+
+    /**
+     * Makes sure app-private data directories on external storage are setup correctly
+     * after an application is installed or upgraded. The main use for this is OBB dirs,
+     * which can be created/modified by the installer.
+     *
+     * @param packageName the package name of the package
+     * @param uid the uid of the package
+     */
+    public abstract void prepareAppDataAfterInstall(@NonNull String packageName, int uid);
 }
diff --git a/core/java/android/os/strictmode/IncorrectContextUseViolation.java b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
new file mode 100644
index 0000000..647db17
--- /dev/null
+++ b/core/java/android/os/strictmode/IncorrectContextUseViolation.java
@@ -0,0 +1,35 @@
+/*
+ * 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.os.strictmode;
+
+import android.content.Context;
+
+/**
+ * Incorrect usage of {@link Context}, such as obtaining a visual service from non-visual
+ * {@link Context} instance.
+ * @see Context#getSystemService(String)
+ * @see Context#getDisplayNoVerify()
+ * @hide
+ */
+public final class IncorrectContextUseViolation extends Violation {
+
+    /** @hide */
+    public IncorrectContextUseViolation(String message, Throwable originStack) {
+        super(message);
+        initCause(originStack);
+    }
+}
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index f6072f9..b898271 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -8595,6 +8595,15 @@
         public static final String NOTIFICATION_HISTORY_ENABLED = "notification_history_enabled";
 
         /**
+         * When enabled conversations marked as favorites will be set to bubble.
+         *
+         * The value 1 - enable, 0 - disable
+         * @hide
+         */
+        public static final String BUBBLE_IMPORTANT_CONVERSATIONS
+                = "bubble_important_conversations";
+
+        /**
          * Whether notifications are dismissed by a right-to-left swipe (instead of a left-to-right
          * swipe).
          *
@@ -8751,6 +8760,13 @@
                 "location_permissions_upgrade_to_q_mode";
 
         /**
+         * Whether or not the system Auto Revoke feature is disabled.
+         * @hide
+         */
+        @SystemApi
+        public static final String AUTO_REVOKE_DISABLED = "auto_revoke_disabled";
+
+        /**
          * Map of android.theme.customization.* categories to the enabled overlay package for that
          * category, formatted as a serialized {@link org.json.JSONObject}. If there is no
          * corresponding package included for a category, then all overlay packages in that
@@ -9084,26 +9100,34 @@
          * Set to one of {@link #WIFI_SLEEP_POLICY_DEFAULT},
          * {@link #WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED}, or
          * {@link #WIFI_SLEEP_POLICY_NEVER}.
+         * @deprecated This is no longer used or set by the platform.
          */
+        @Deprecated
         public static final String WIFI_SLEEP_POLICY = "wifi_sleep_policy";
 
         /**
          * Value for {@link #WIFI_SLEEP_POLICY} to use the default Wi-Fi sleep
          * policy, which is to sleep shortly after the turning off
          * according to the {@link #STAY_ON_WHILE_PLUGGED_IN} setting.
+         * @deprecated This is no longer used by the platform.
          */
+        @Deprecated
         public static final int WIFI_SLEEP_POLICY_DEFAULT = 0;
 
         /**
          * Value for {@link #WIFI_SLEEP_POLICY} to use the default policy when
          * the device is on battery, and never go to sleep when the device is
          * plugged in.
+         * @deprecated This is no longer used by the platform.
          */
+        @Deprecated
         public static final int WIFI_SLEEP_POLICY_NEVER_WHILE_PLUGGED = 1;
 
         /**
          * Value for {@link #WIFI_SLEEP_POLICY} to never go to sleep.
+         * @deprecated This is no longer used by the platform.
          */
+        @Deprecated
         public static final int WIFI_SLEEP_POLICY_NEVER = 2;
 
         /**
@@ -9251,11 +9275,17 @@
         public static final String CUSTOM_BUGREPORT_HANDLER_USER = "custom_bugreport_handler_user";
 
         /**
-         * Whether ADB is enabled.
+         * Whether ADB over USB is enabled.
          */
         public static final String ADB_ENABLED = "adb_enabled";
 
         /**
+         * Whether ADB over Wifi is enabled.
+         * @hide
+         */
+        public static final String ADB_WIFI_ENABLED = "adb_wifi_enabled";
+
+        /**
          * Whether Views are allowed to save their attribute data.
          * @hide
          */
@@ -10197,7 +10227,9 @@
        /**
         * Delay (in seconds) before repeating the Wi-Fi networks available notification.
         * Connecting to a network will reset the timer.
+        * @deprecated This is no longer used or set by the platform.
         */
+       @Deprecated
        public static final String WIFI_NETWORKS_AVAILABLE_REPEAT_DELAY =
                "wifi_networks_available_repeat_delay";
 
@@ -10227,7 +10259,9 @@
        /**
         * When the number of open networks exceeds this number, the
         * least-recently-used excess networks will be removed.
+        * @deprecated This is no longer used or set by the platform.
         */
+       @Deprecated
        public static final String WIFI_NUM_OPEN_NETWORKS_KEPT = "wifi_num_open_networks_kept";
 
        /**
@@ -10238,8 +10272,8 @@
        /**
         * Setting to allow scans to be enabled even wifi is turned off for connectivity.
         * @hide
+        * @deprecated To be removed.
         */
-       @SystemApi
        public static final String WIFI_SCAN_ALWAYS_AVAILABLE =
                 "wifi_scan_always_enabled";
 
@@ -10248,8 +10282,8 @@
          *
          * Type: int (0 for false, 1 for true)
          * @hide
+         * @deprecated To be removed.
          */
-        @SystemApi
         public static final String WIFI_P2P_PENDING_FACTORY_RESET =
                 "wifi_p2p_pending_factory_reset";
 
@@ -10258,8 +10292,8 @@
          *
          * Type: int (0 for false, 1 for true)
          * @hide
+         * @deprecated To be removed.
          */
-        @SystemApi
         public static final String SOFT_AP_TIMEOUT_ENABLED = "soft_ap_timeout_enabled";
 
         /**
@@ -10304,6 +10338,7 @@
          * Most readers of this setting should simply check if value == 1 to determined the
          * enabled state.
          * @hide
+         * @deprecated To be removed.
          */
         public static final String NETWORK_RECOMMENDATIONS_ENABLED =
                 "network_recommendations_enabled";
@@ -10343,13 +10378,11 @@
 
         /**
          * Whether wifi scan throttle is enabled or not.
-         * This is intended to be used via adb commands or a menu in developer option to turn off
-         * the default wifi scan throttling mechanism for apps.
          *
          * Type: int (0 for false, 1 for true)
          * @hide
+         * @deprecated To be removed.
          */
-        @SystemApi
         public static final String WIFI_SCAN_THROTTLE_ENABLED = "wifi_scan_throttle_enabled";
 
         /**
@@ -10451,8 +10484,8 @@
         * Setting to enable verbose logging in Wi-Fi; disabled by default, and setting to 1
         * will enable it. In the future, additional values may be supported.
         * @hide
+        * @deprecated To be removed.
         */
-       @SystemApi
        public static final String WIFI_VERBOSE_LOGGING_ENABLED =
                "wifi_verbose_logging_enabled";
 
@@ -10477,8 +10510,8 @@
          * Default values are provided by code or device configurations.
          * Errors in the parameters will cause the entire setting to be ignored.
          * @hide
+         * @deprecated This is no longer used or set by the platform.
          */
-        @SystemApi
         public static final String WIFI_SCORE_PARAMS =
                 "wifi_score_params";
 
@@ -10520,8 +10553,8 @@
        /**
         * The Wi-Fi peer-to-peer device name
         * @hide
+        * @deprecated To be removed.
         */
-       @SystemApi
        public static final String WIFI_P2P_DEVICE_NAME = "wifi_p2p_device_name";
 
        /**
@@ -11482,6 +11515,7 @@
          * exempted_sync_duration           (long)
          * system_interaction_duration      (long)
          * initial_foreground_service_start_duration (long)
+         * cross_profile_apps_share_standby_buckets  (boolean)
          * </pre>
          *
          * <p>
@@ -14129,6 +14163,13 @@
          */
         @SystemApi
         public static final String COMMON_CRITERIA_MODE = "common_criteria_mode";
+
+        /**
+         * The usage amount of advanced battery. The value is 0~100.
+         *
+         * @hide
+         */
+        public static final String ADVANCED_BATTERY_USAGE_AMOUNT = "advanced_battery_usage_amount";
     }
 
     /**
@@ -14291,7 +14332,6 @@
          *
          * @hide
          */
-        @SystemApi
         @RequiresPermission(Manifest.permission.MONITOR_DEVICE_CONFIG_ACCESS)
         public static void registerMonitorCallback(@NonNull ContentResolver resolver,
                 @NonNull RemoteCallback callback) {
diff --git a/core/java/android/service/autofill/InlineSuggestionRenderService.java b/core/java/android/service/autofill/InlineSuggestionRenderService.java
index 4aafb63..29069e7 100644
--- a/core/java/android/service/autofill/InlineSuggestionRenderService.java
+++ b/core/java/android/service/autofill/InlineSuggestionRenderService.java
@@ -25,6 +25,7 @@
 import android.app.slice.Slice;
 import android.content.Intent;
 import android.graphics.PixelFormat;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -118,6 +119,14 @@
     }
 
     /**
+     *  Returns the metadata about the renderer. Returns {@code null} if no metadata is provided.
+     */
+    @Nullable
+    public Bundle onGetInlineSuggestionsRendererInfo() {
+        return null;
+    }
+
+    /**
      * Renders the slice into a view.
      */
     @Nullable
diff --git a/core/java/android/service/controls/ControlsProviderService.java b/core/java/android/service/controls/ControlsProviderService.java
index de4c056..b23d0cd 100644
--- a/core/java/android/service/controls/ControlsProviderService.java
+++ b/core/java/android/service/controls/ControlsProviderService.java
@@ -15,10 +15,14 @@
  */
 package android.service.controls;
 
+import android.Manifest;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.Service;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
@@ -34,7 +38,6 @@
 
 import com.android.internal.util.Preconditions;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.concurrent.Flow.Publisher;
@@ -51,6 +54,20 @@
     @SdkConstant(SdkConstantType.SERVICE_ACTION)
     public static final String SERVICE_CONTROLS =
             "android.service.controls.ControlsProviderService";
+
+    /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_ADD_CONTROL =
+            "android.service.controls.action.ADD_CONTROL";
+
+    /**
+     * @hide
+     */
+    public static final String EXTRA_CONTROL =
+            "android.service.controls.extra.CONTROL";
+
     /**
      * @hide
      */
@@ -70,25 +87,48 @@
      * Retrieve all available controls, using the stateless builder
      * {@link Control.StatelessBuilder} to build each Control, then use the
      * provided consumer to callback to the call originator.
+     *
+     * @deprecated Removing consumer-based load apis. Use publisherForAllAvailable() instead
      */
-    public abstract void loadAvailableControls(@NonNull Consumer<List<Control>> consumer);
-
-    /**
-     * (Optional) The service may be asked to provide a small number of recommended controls, in
-     * order to suggest some controls to the user for favoriting. The controls shall be built using
-     * the stateless builder {@link Control.StatelessBuilder}, followed by an invocation to the
-     * provided consumer to callback to the call originator. If the number of controls
-     * is greater than maxNumber, the list will be truncated.
-     */
-    public void loadSuggestedControls(int maxNumber, @NonNull Consumer<List<Control>> consumer) {
-        // Override to change the default behavior
+    @Deprecated
+    public void loadAvailableControls(@NonNull Consumer<List<Control>> consumer) {
+        // pending removal
         consumer.accept(Collections.emptyList());
     }
 
     /**
-     * Return a valid Publisher for the given controlIds. This publisher will be asked
-     * to provide updates for the given list of controlIds as long as the Subscription
-     * is valid.
+     * Publisher for all available controls
+     *
+     * Retrieve all available controls. Use the stateless builder {@link Control.StatelessBuilder}
+     * to build each Control. Call {@link Subscriber#onComplete} when done loading all unique
+     * controls, or {@link Subscriber#onError} for error scenarios. Duplicate Controls will
+     * replace the original.
+     */
+    @Nullable
+    public Publisher<Control> publisherForAllAvailable() {
+        // will be abstract and @nonnull when consumers are removed
+        return null;
+    }
+
+    /**
+     * (Optional) Publisher for suggested controls
+     *
+     * The service may be asked to provide a small number of recommended controls, in
+     * order to suggest some controls to the user for favoriting. The controls shall be built using
+     * the stateless builder {@link Control.StatelessBuilder}. The number of controls requested
+     * through {@link Subscription#request} will be limited. Call {@link Subscriber#onComplete}
+     * when done, or {@link Subscriber#onError} for error scenarios.
+     */
+    @Nullable
+    public Publisher<Control> publisherForSuggested() {
+        return null;
+    }
+
+    /**
+     * Return a valid Publisher for the given controlIds. This publisher will be asked to provide
+     * updates for the given list of controlIds as long as the {@link Subscription} is valid.
+     * Calls to {@link Subscriber#onComplete} will not be expected. Instead, wait for the call from
+     * {@link Subscription#cancel} to indicate that updates are no longer required.
      */
     @NonNull
     public abstract Publisher<Control> publisherFor(@NonNull List<String> controlIds);
@@ -113,13 +153,13 @@
         mToken = bundle.getBinder(CALLBACK_TOKEN);
 
         return new IControlsProvider.Stub() {
-            public void load(IControlsLoadCallback cb) {
-                mHandler.obtainMessage(RequestHandler.MSG_LOAD, cb).sendToTarget();
+            public void load(IControlsSubscriber subscriber) {
+                mHandler.obtainMessage(RequestHandler.MSG_LOAD, subscriber).sendToTarget();
             }
 
-            public void loadSuggested(int maxNumber, IControlsLoadCallback cb) {
-                LoadMessage msg = new LoadMessage(maxNumber, cb);
-                mHandler.obtainMessage(RequestHandler.MSG_LOAD_SUGGESTED, msg).sendToTarget();
+            public void loadSuggested(IControlsSubscriber subscriber) {
+                mHandler.obtainMessage(RequestHandler.MSG_LOAD_SUGGESTED, subscriber)
+                        .sendToTarget();
             }
 
             public void subscribe(List<String> controlIds,
@@ -148,73 +188,56 @@
         private static final int MSG_ACTION = 3;
         private static final int MSG_LOAD_SUGGESTED = 4;
 
-        /**
-         * This the maximum number of controls that can be loaded via
-         * {@link ControlsProviderService#loadAvailablecontrols}. Anything over this number
-         * will be truncated.
-         */
-        private static final int MAX_NUMBER_OF_CONTROLS_ALLOWED = 1000;
-
         RequestHandler(Looper looper) {
             super(looper);
         }
 
         public void handleMessage(Message msg) {
             switch(msg.what) {
-                case MSG_LOAD:
-                    final IControlsLoadCallback cb = (IControlsLoadCallback) msg.obj;
-                    ControlsProviderService.this.loadAvailableControls(consumerFor(
-                            MAX_NUMBER_OF_CONTROLS_ALLOWED, cb));
-                    break;
+                case MSG_LOAD: {
+                    final IControlsSubscriber cs = (IControlsSubscriber) msg.obj;
+                    final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);
 
-                case MSG_LOAD_SUGGESTED:
-                    final LoadMessage lMsg = (LoadMessage) msg.obj;
-                    ControlsProviderService.this.loadSuggestedControls(lMsg.mMaxNumber,
-                            consumerFor(lMsg.mMaxNumber, lMsg.mCb));
+                    Publisher<Control> publisher =
+                            ControlsProviderService.this.publisherForAllAvailable();
+                    if (publisher == null) {
+                        ControlsProviderService.this.loadAvailableControls(consumerFor(proxy));
+                    } else {
+                        publisher.subscribe(proxy);
+                    }
                     break;
+                }
 
-                case MSG_SUBSCRIBE:
+                case MSG_LOAD_SUGGESTED: {
+                    final IControlsSubscriber cs = (IControlsSubscriber) msg.obj;
+                    final SubscriberProxy proxy = new SubscriberProxy(true, mToken, cs);
+
+                    Publisher<Control> publisher =
+                            ControlsProviderService.this.publisherForSuggested();
+                    if (publisher == null) {
+                        Log.i(TAG, "No publisher provided for suggested controls");
+                        proxy.onComplete();
+                    } else {
+                        publisher.subscribe(proxy);
+                    }
+                    break;
+                }
+
+                case MSG_SUBSCRIBE: {
                     final SubscribeMessage sMsg = (SubscribeMessage) msg.obj;
-                    final IControlsSubscriber cs = sMsg.mSubscriber;
-                    Subscriber<Control> s = new Subscriber<Control>() {
-                            public void onSubscribe(Subscription subscription) {
-                                try {
-                                    cs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
-                                } catch (RemoteException ex) {
-                                    ex.rethrowAsRuntimeException();
-                                }
-                            }
-                            public void onNext(@NonNull Control statefulControl) {
-                                Preconditions.checkNotNull(statefulControl);
-                                try {
-                                    cs.onNext(mToken, statefulControl);
-                                } catch (RemoteException ex) {
-                                    ex.rethrowAsRuntimeException();
-                                }
-                            }
-                            public void onError(Throwable t) {
-                                try {
-                                    cs.onError(mToken, t.toString());
-                                } catch (RemoteException ex) {
-                                    ex.rethrowAsRuntimeException();
-                                }
-                            }
-                            public void onComplete() {
-                                try {
-                                    cs.onComplete(mToken);
-                                } catch (RemoteException ex) {
-                                    ex.rethrowAsRuntimeException();
-                                }
-                            }
-                        };
-                    ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(s);
-                    break;
+                    final SubscriberProxy proxy = new SubscriberProxy(false, mToken,
+                            sMsg.mSubscriber);
 
-                case MSG_ACTION:
+                    ControlsProviderService.this.publisherFor(sMsg.mControlIds).subscribe(proxy);
+                    break;
+                }
+
+                case MSG_ACTION: {
                     final ActionMessage aMsg = (ActionMessage) msg.obj;
                     ControlsProviderService.this.performControlAction(aMsg.mControlId,
                             aMsg.mAction, consumerFor(aMsg.mControlId, aMsg.mCb));
                     break;
+                }
             }
         }
 
@@ -234,40 +257,116 @@
             };
         }
 
-        private Consumer<List<Control>> consumerFor(int maxNumber, IControlsLoadCallback cb) {
-            return (@NonNull List<Control> controls) -> {
+        /**
+         * Method will be removed during migration to publisher
+         */
+        private Consumer<List<Control>> consumerFor(final Subscriber<Control> subscriber) {
+            return (@NonNull final List<Control> controls) -> {
                 Preconditions.checkNotNull(controls);
-                if (controls.size() > maxNumber) {
-                    Log.w(TAG, "Too many controls. Provided: " + controls.size() + ", Max allowed: "
-                            + maxNumber + ". Truncating the list.");
-                    controls = controls.subList(0, maxNumber);
-                }
 
-                List<Control> list = new ArrayList<>();
-                for (Control control: controls) {
-                    if (control == null) {
-                        Log.e(TAG, "onLoad: null control.");
-                    }
-                    if (isStatelessControl(control)) {
-                        list.add(control);
-                    } else {
-                        Log.w(TAG, "onLoad: control is not stateless.");
-                        list.add(new Control.StatelessBuilder(control).build());
-                    }
-                }
-                try {
-                    cb.accept(mToken, list);
-                } catch (RemoteException ex) {
-                    ex.rethrowAsRuntimeException();
-                }
+                subscriber.onSubscribe(new Subscription() {
+                        public void request(long n) {
+                            for (Control control: controls) {
+                                Control c;
+                                if (control == null) {
+                                    Log.e(TAG, "onLoad: null control.");
+                                }
+                                if (isStatelessControl(control)) {
+                                    c = control;
+                                } else {
+                                    Log.w(TAG, "onLoad: control is not stateless.");
+                                    c = new Control.StatelessBuilder(control).build();
+                                }
+
+                                subscriber.onNext(c);
+                            }
+                            subscriber.onComplete();
+                        }
+
+                        public void cancel() {}
+                    });
             };
         }
+    }
 
-        private boolean isStatelessControl(Control control) {
-            return (control.getStatus() == Control.STATUS_UNKNOWN
-                    && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
-                    && TextUtils.isEmpty(control.getStatusText()));
+    private static boolean isStatelessControl(Control control) {
+        return (control.getStatus() == Control.STATUS_UNKNOWN
+                && control.getControlTemplate().getTemplateType() == ControlTemplate.TYPE_NONE
+                && TextUtils.isEmpty(control.getStatusText()));
+    }
+
+    private static class SubscriberProxy implements Subscriber<Control> {
+        private IBinder mToken;
+        private IControlsSubscriber mCs;
+        private boolean mEnforceStateless;
+
+        SubscriberProxy(boolean enforceStateless, IBinder token, IControlsSubscriber cs) {
+            mEnforceStateless = enforceStateless;
+            mToken = token;
+            mCs = cs;
         }
+
+        public void onSubscribe(Subscription subscription) {
+            try {
+                mCs.onSubscribe(mToken, new SubscriptionAdapter(subscription));
+            } catch (RemoteException ex) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        public void onNext(@NonNull Control control) {
+            Preconditions.checkNotNull(control);
+            try {
+                if (mEnforceStateless && !isStatelessControl(control)) {
+                    Log.w(TAG, "onNext(): control is not stateless. Use the "
+                            + "Control.StatelessBuilder() to build the control.");
+                    control = new Control.StatelessBuilder(control).build();
+                }
+                mCs.onNext(mToken, control);
+            } catch (RemoteException ex) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        public void onError(Throwable t) {
+            try {
+                mCs.onError(mToken, t.toString());
+            } catch (RemoteException ex) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+        public void onComplete() {
+            try {
+                mCs.onComplete(mToken);
+            } catch (RemoteException ex) {
+                ex.rethrowAsRuntimeException();
+            }
+        }
+    }
+
+    /**
+     * Request SystemUI to prompt the user to add a control to favorites.
+     *
+     * @param context A context
+     * @param componentName Component name of the {@link ControlsProviderService}
+     * @param control A stateless control to show to the user
+     */
+    public static void requestAddControl(@NonNull Context context,
+            @NonNull ComponentName componentName,
+            @NonNull Control control) {
+        Preconditions.checkNotNull(context);
+        Preconditions.checkNotNull(componentName);
+        Preconditions.checkNotNull(control);
+        final ComponentName sysuiComponent = ComponentName.unflattenFromString(
+                context.getResources().getString(
+                        com.android.internal.R.string.config_systemUIServiceComponent));
+        Intent intent = new Intent(ACTION_ADD_CONTROL);
+        intent.putExtra(Intent.EXTRA_COMPONENT_NAME, componentName);
+        intent.setPackage(sysuiComponent.getPackageName());
+        if (isStatelessControl(control)) {
+            intent.putExtra(EXTRA_CONTROL, control);
+        } else {
+            intent.putExtra(EXTRA_CONTROL, new Control.StatelessBuilder(control).build());
+        }
+        context.sendBroadcast(intent, Manifest.permission.BIND_CONTROLS);
     }
 
     private static class SubscriptionAdapter extends IControlsSubscription.Stub {
@@ -307,14 +406,4 @@
             this.mSubscriber = subscriber;
         }
     }
-
-    private static class LoadMessage {
-        final int mMaxNumber;
-        final IControlsLoadCallback mCb;
-
-        LoadMessage(int maxNumber, IControlsLoadCallback cb) {
-            this.mMaxNumber = maxNumber;
-            this.mCb = cb;
-        }
-    }
 }
diff --git a/core/java/android/service/controls/IControlsProvider.aidl b/core/java/android/service/controls/IControlsProvider.aidl
index 4375fbb..0cb06b4 100644
--- a/core/java/android/service/controls/IControlsProvider.aidl
+++ b/core/java/android/service/controls/IControlsProvider.aidl
@@ -17,7 +17,6 @@
 package android.service.controls;
 
 import android.service.controls.IControlsActionCallback;
-import android.service.controls.IControlsLoadCallback;
 import android.service.controls.IControlsSubscriber;
 import android.service.controls.actions.ControlActionWrapper;
 
@@ -25,9 +24,9 @@
  * @hide
  */
 oneway interface IControlsProvider {
-    void load(IControlsLoadCallback cb);
+    void load(IControlsSubscriber subscriber);
 
-    void loadSuggested(int maxNumber, IControlsLoadCallback cb);
+    void loadSuggested(IControlsSubscriber subscriber);
 
     void subscribe(in List<String> controlIds,
              IControlsSubscriber subscriber);
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
index 7d3b13b..f37e01d 100644
--- a/core/java/android/service/notification/ConditionProviderService.java
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -58,7 +58,7 @@
  * &lt;/service></pre>
  *
  *  <p> Condition providers cannot be bound by the system on
- * {@link ActivityManager#isLowRamDevice() low ram} devices</p>
+ * {@link ActivityManager#isLowRamDevice() low ram} devices running Android Q (and below)</p>
  *
  * @deprecated Instead of using an automatically bound service, use
  * {@link android.app.NotificationManager#setAutomaticZenRuleState(String, Condition)} to tell the
diff --git a/core/java/android/service/notification/ConversationChannelWrapper.java b/core/java/android/service/notification/ConversationChannelWrapper.java
index 9847695..ab465ab 100644
--- a/core/java/android/service/notification/ConversationChannelWrapper.java
+++ b/core/java/android/service/notification/ConversationChannelWrapper.java
@@ -33,6 +33,8 @@
     private CharSequence mGroupLabel;
     private CharSequence mParentChannelLabel;
     private ShortcutInfo mShortcutInfo;
+    private String mPkg;
+    private int mUid;
 
     public ConversationChannelWrapper() {}
 
@@ -41,6 +43,8 @@
         mGroupLabel = in.readCharSequence();
         mParentChannelLabel = in.readCharSequence();
         mShortcutInfo = in.readParcelable(ShortcutInfo.class.getClassLoader());
+        mPkg = in.readStringNoHelper();
+        mUid = in.readInt();
     }
 
     @Override
@@ -49,6 +53,8 @@
         dest.writeCharSequence(mGroupLabel);
         dest.writeCharSequence(mParentChannelLabel);
         dest.writeParcelable(mShortcutInfo, flags);
+        dest.writeStringNoHelper(mPkg);
+        dest.writeInt(mUid);
     }
 
     @Override
@@ -103,6 +109,22 @@
         mShortcutInfo = shortcutInfo;
     }
 
+    public String getPkg() {
+        return mPkg;
+    }
+
+    public void setPkg(String pkg) {
+        mPkg = pkg;
+    }
+
+    public int getUid() {
+        return mUid;
+    }
+
+    public void setUid(int uid) {
+        mUid = uid;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
@@ -111,12 +133,14 @@
         return Objects.equals(getNotificationChannel(), that.getNotificationChannel()) &&
                 Objects.equals(getGroupLabel(), that.getGroupLabel()) &&
                 Objects.equals(getParentChannelLabel(), that.getParentChannelLabel()) &&
-                Objects.equals(getShortcutInfo(), that.getShortcutInfo());
+                Objects.equals(getShortcutInfo(), that.getShortcutInfo()) &&
+                Objects.equals(getPkg(), that.getPkg()) &&
+                getUid() == that.getUid();
     }
 
     @Override
     public int hashCode() {
         return Objects.hash(getNotificationChannel(), getGroupLabel(), getParentChannelLabel(),
-                getShortcutInfo());
+                getShortcutInfo(), getPkg(), getUid());
     }
 }
diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java
index 0ff2e03..6562572 100644
--- a/core/java/android/service/notification/NotificationListenerService.java
+++ b/core/java/android/service/notification/NotificationListenerService.java
@@ -86,8 +86,8 @@
  * or after {@link #onListenerDisconnected()}.
  * </p>
  * <p> Notification listeners cannot get notification access or be bound by the system on
- * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices. The system also ignores
- * notification listeners running in a work profile. A
+ * {@linkplain ActivityManager#isLowRamDevice() low-RAM} devices running Android Q (and below).
+ * The system also ignores notification listeners running in a work profile. A
  * {@link android.app.admin.DevicePolicyManager} might block notifications originating from a work
  * profile.</p>
  * <p>
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index c9dc05b..ead4e46 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -16,6 +16,8 @@
 
 package android.util;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.annotation.SystemApi;
 import android.compat.annotation.UnsupportedAppUsage;
 
@@ -62,7 +64,7 @@
         private Exception mLastWtf;
 
         // Layout of event log entry received from Android logger.
-        //  see system/core/include/log/log.h
+        //  see system/core/liblog/include/log/log_read.h
         private static final int LENGTH_OFFSET = 0;
         private static final int HEADER_SIZE_OFFSET = 2;
         private static final int PROCESS_OFFSET = 4;
@@ -73,7 +75,7 @@
 
         // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET
         private static final int V1_PAYLOAD_START = 20;
-        private static final int DATA_OFFSET = 4;
+        private static final int TAG_LENGTH = 4;
 
         // Value types
         private static final byte INT_TYPE    = 0;
@@ -121,26 +123,26 @@
 
         /** @return the type tag code of the entry */
         public int getTag() {
-            int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
-            if (offset == 0) {
-                offset = V1_PAYLOAD_START;
-            }
-            return mBuffer.getInt(offset);
+            return mBuffer.getInt(getHeaderSize());
         }
 
+        private int getHeaderSize() {
+            int length = mBuffer.getShort(HEADER_SIZE_OFFSET);
+            if (length != 0) {
+                return length;
+            }
+            return V1_PAYLOAD_START;
+        }
         /** @return one of Integer, Long, Float, String, null, or Object[] of same. */
         public synchronized Object getData() {
             try {
-                int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
-                if (offset == 0) {
-                    offset = V1_PAYLOAD_START;
-                }
+                int offset = getHeaderSize();
                 mBuffer.limit(offset + mBuffer.getShort(LENGTH_OFFSET));
-                if ((offset + DATA_OFFSET) >= mBuffer.limit()) {
+                if ((offset + TAG_LENGTH) >= mBuffer.limit()) {
                     // no payload
                     return null;
                 }
-                mBuffer.position(offset + DATA_OFFSET); // Just after the tag.
+                mBuffer.position(offset + TAG_LENGTH); // Just after the tag.
                 return decodeObject();
             } catch (IllegalArgumentException e) {
                 Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e);
@@ -153,6 +155,28 @@
             }
         }
 
+        /**
+         * Construct a new EventLog object from the current object, copying all log metadata
+         * but replacing the actual payload with the content provided.
+         * @hide
+         */
+        public Event withNewData(@Nullable Object object) {
+            byte[] payload = encodeObject(object);
+            if (payload.length > 65535 - TAG_LENGTH) {
+                throw new IllegalArgumentException("Payload too long");
+            }
+            int headerLength = getHeaderSize();
+            byte[] newBytes = new byte[headerLength + TAG_LENGTH + payload.length];
+            // Copy header (including the 4 bytes of tag integer at the beginning of payload)
+            System.arraycopy(mBuffer.array(), 0, newBytes, 0, headerLength + TAG_LENGTH);
+            // Fill in encoded objects
+            System.arraycopy(payload, 0, newBytes, headerLength + TAG_LENGTH, payload.length);
+            Event result = new Event(newBytes);
+            // Patch payload length in header
+            result.mBuffer.putShort(LENGTH_OFFSET, (short) (payload.length + TAG_LENGTH));
+            return result;
+        }
+
         /** @return the loggable item at the current position in mBuffer. */
         private Object decodeObject() {
             byte type = mBuffer.get();
@@ -190,6 +214,66 @@
             }
         }
 
+        private static @NonNull byte[] encodeObject(@Nullable Object object) {
+            if (object == null) {
+                return new byte[0];
+            }
+            if (object instanceof Integer) {
+                return ByteBuffer.allocate(1 + 4)
+                        .order(ByteOrder.nativeOrder())
+                        .put(INT_TYPE)
+                        .putInt((Integer) object)
+                        .array();
+            } else if (object instanceof Long) {
+                return ByteBuffer.allocate(1 + 8)
+                        .order(ByteOrder.nativeOrder())
+                        .put(LONG_TYPE)
+                        .putLong((Long) object)
+                        .array();
+            } else if (object instanceof Float) {
+                return ByteBuffer.allocate(1 + 4)
+                        .order(ByteOrder.nativeOrder())
+                        .put(FLOAT_TYPE)
+                        .putFloat((Float) object)
+                        .array();
+            } else if (object instanceof String) {
+                String string = (String) object;
+                byte[] bytes;
+                try {
+                    bytes = string.getBytes("UTF-8");
+                } catch (UnsupportedEncodingException e) {
+                    bytes = new byte[0];
+                }
+                return ByteBuffer.allocate(1 + 4 + bytes.length)
+                         .order(ByteOrder.nativeOrder())
+                         .put(STRING_TYPE)
+                         .putInt(bytes.length)
+                         .put(bytes)
+                         .array();
+            } else if (object instanceof Object[]) {
+                Object[] objects = (Object[]) object;
+                if (objects.length > 255) {
+                    throw new IllegalArgumentException("Object array too long");
+                }
+                byte[][] bytes = new byte[objects.length][];
+                int totalLength = 0;
+                for (int i = 0; i < objects.length; i++) {
+                    bytes[i] = encodeObject(objects[i]);
+                    totalLength += bytes[i].length;
+                }
+                ByteBuffer buffer = ByteBuffer.allocate(1 + 1 + totalLength)
+                        .order(ByteOrder.nativeOrder())
+                        .put(LIST_TYPE)
+                        .put((byte) objects.length);
+                for (int i = 0; i < objects.length; i++) {
+                    buffer.put(bytes[i]);
+                }
+                return buffer.array();
+            } else {
+                throw new IllegalArgumentException("Unknown object type " + object);
+            }
+        }
+
         /** @hide */
         public static Event fromBytes(byte[] data) {
             return new Event(data);
diff --git a/core/java/android/util/LongSparseArray.java b/core/java/android/util/LongSparseArray.java
index 73e17a6..55542d8 100644
--- a/core/java/android/util/LongSparseArray.java
+++ b/core/java/android/util/LongSparseArray.java
@@ -16,15 +16,18 @@
 
 package android.util;
 
+import android.annotation.NonNull;
 import android.os.Parcel;
 
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.GrowingArrayUtils;
 import com.android.internal.util.Preconditions;
+import com.android.internal.util.function.LongObjPredicate;
 
 import libcore.util.EmptyArray;
 
 import java.util.Arrays;
+import java.util.Objects;
 
 /**
  * SparseArray mapping longs to Objects.  Unlike a normal array of Objects,
@@ -145,6 +148,18 @@
         delete(key);
     }
 
+    /** @hide */
+    @SuppressWarnings("unchecked")
+    public void removeIf(@NonNull LongObjPredicate<? super E> filter) {
+        Objects.requireNonNull(filter);
+        for (int i = 0; i < mSize; ++i) {
+            if (mValues[i] != DELETED && filter.test(mKeys[i], (E) mValues[i])) {
+                mValues[i] = DELETED;
+                mGarbage = true;
+            }
+        }
+    }
+
     /**
      * Removes the mapping at the specified index.
      *
diff --git a/core/java/android/view/AccessibilityEmbeddedConnection.java b/core/java/android/view/AccessibilityEmbeddedConnection.java
index cc1e501..5d34669 100644
--- a/core/java/android/view/AccessibilityEmbeddedConnection.java
+++ b/core/java/android/view/AccessibilityEmbeddedConnection.java
@@ -33,6 +33,7 @@
  */
 final class AccessibilityEmbeddedConnection extends IAccessibilityEmbeddedConnection.Stub {
     private final WeakReference<ViewRootImpl> mViewRootImpl;
+    private final Matrix mTmpScreenMatrix = new Matrix();
 
     AccessibilityEmbeddedConnection(ViewRootImpl viewRootImpl) {
         mViewRootImpl = new WeakReference<>(viewRootImpl);
@@ -73,9 +74,11 @@
     public void setScreenMatrix(float[] matrixValues) {
         final ViewRootImpl viewRootImpl = mViewRootImpl.get();
         if (viewRootImpl != null) {
-            // TODO(b/148821260): Implement the rest of matrix values.
-            viewRootImpl.mAttachInfo.mLocationInParentDisplay.set(
-                    (int) matrixValues[Matrix.MTRANS_X], (int) matrixValues[Matrix.MTRANS_Y]);
+            mTmpScreenMatrix.setValues(matrixValues);
+            if (viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy == null) {
+                viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy = new Matrix();
+            }
+            viewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy.set(mTmpScreenMatrix);
         }
     }
 }
diff --git a/core/java/android/view/AccessibilityInteractionController.java b/core/java/android/view/AccessibilityInteractionController.java
index 3ca84c1..6d4ac0e 100644
--- a/core/java/android/view/AccessibilityInteractionController.java
+++ b/core/java/android/view/AccessibilityInteractionController.java
@@ -21,6 +21,7 @@
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_REQUESTED_KEY;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
 
+import android.graphics.Matrix;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -109,6 +110,7 @@
     private final Rect mTempRect = new Rect();
     private final Rect mTempRect1 = new Rect();
     private final Rect mTempRect2 = new Rect();
+    private final RectF mTempRectF = new RectF();
 
     private AddNodeInfosForViewId mAddNodeInfosForViewId;
 
@@ -855,6 +857,38 @@
         return mViewRootImpl.mAttachInfo.mLocationInParentDisplay.equals(0, 0);
     }
 
+    private void applyScreenMatrixIfNeeded(List<AccessibilityNodeInfo> infos) {
+        if (infos == null || shouldBypassApplyScreenMatrix()) {
+            return;
+        }
+        final int infoCount = infos.size();
+        for (int i = 0; i < infoCount; i++) {
+            final AccessibilityNodeInfo info = infos.get(i);
+            applyScreenMatrixIfNeeded(info);
+        }
+    }
+
+    private void applyScreenMatrixIfNeeded(AccessibilityNodeInfo info) {
+        if (info == null || shouldBypassApplyScreenMatrix()) {
+            return;
+        }
+        final Rect boundsInScreen = mTempRect;
+        final RectF transformedBounds = mTempRectF;
+        final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy;
+
+        info.getBoundsInScreen(boundsInScreen);
+        transformedBounds.set(boundsInScreen);
+        screenMatrix.mapRect(transformedBounds);
+        boundsInScreen.set((int) transformedBounds.left, (int) transformedBounds.top,
+                (int) transformedBounds.right, (int) transformedBounds.bottom);
+        info.setBoundsInScreen(boundsInScreen);
+    }
+
+    private boolean shouldBypassApplyScreenMatrix() {
+        final Matrix screenMatrix = mViewRootImpl.mAttachInfo.mScreenMatrixInEmbeddedHierarchy;
+        return screenMatrix == null || screenMatrix.isIdentity();
+    }
+
     private void associateLeashedParentIfNeeded(List<AccessibilityNodeInfo> infos) {
         if (infos == null || shouldBypassAssociateLeashedParent()) {
             return;
@@ -945,6 +979,7 @@
         try {
             mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             associateLeashedParentIfNeeded(infos);
+            applyScreenMatrixIfNeeded(infos);
             adjustBoundsInScreenIfNeeded(infos);
             // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
             // then impact the visibility result, we need to adjust visibility before apply scale.
@@ -967,6 +1002,7 @@
         try {
             mViewRootImpl.mAttachInfo.mAccessibilityFetchFlags = 0;
             associateLeashedParentIfNeeded(info);
+            applyScreenMatrixIfNeeded(info);
             adjustBoundsInScreenIfNeeded(info);
             // To avoid applyAppScaleAndMagnificationSpecIfNeeded changing the bounds of node,
             // then impact the visibility result, we need to adjust visibility before apply scale.
diff --git a/core/java/android/view/CutoutSpecification.java b/core/java/android/view/CutoutSpecification.java
index d21a952..850e9fc 100644
--- a/core/java/android/view/CutoutSpecification.java
+++ b/core/java/android/view/CutoutSpecification.java
@@ -406,9 +406,7 @@
                     }
                     currentIndex += RIGHT_MARKER.length();
                 } else if (specWithoutDp.startsWith(BOTTOM_MARKER, currentIndex)) {
-                    if (!mPositionFromCenterVertical) {
-                        parseSvgPathSpec(region, sb.toString());
-                    }
+                    parseSvgPathSpec(region, sb.toString());
                     currentIndex += BOTTOM_MARKER.length();
 
                     /* prepare to parse the rest path */
@@ -416,9 +414,7 @@
                     mBindBottomCutout = true;
                     mPositionFromBottom = true;
                 } else if (specWithoutDp.startsWith(CENTER_VERTICAL_MARKER, currentIndex)) {
-                    if (!mPositionFromBottom) {
-                        parseSvgPathSpec(region, sb.toString());
-                    }
+                    parseSvgPathSpec(region, sb.toString());
                     currentIndex += CENTER_VERTICAL_MARKER.length();
 
                     /* prepare to parse the rest path */
@@ -431,14 +427,16 @@
                     /* prepare to parse the rest path */
                     resetStatus(sb);
                 } else if (specWithoutDp.startsWith(BIND_LEFT_CUTOUT_MARKER, currentIndex)) {
-                    if (!mBindBottomCutout && !mBindRightCutout) {
-                        mBindLeftCutout = true;
-                    }
+                    mBindBottomCutout = false;
+                    mBindRightCutout = false;
+                    mBindLeftCutout = true;
+
                     currentIndex += BIND_LEFT_CUTOUT_MARKER.length();
                 } else if (specWithoutDp.startsWith(BIND_RIGHT_CUTOUT_MARKER, currentIndex)) {
-                    if (!mBindBottomCutout && !mBindLeftCutout) {
-                        mBindRightCutout = true;
-                    }
+                    mBindBottomCutout = false;
+                    mBindLeftCutout = false;
+                    mBindRightCutout = true;
+
                     currentIndex += BIND_RIGHT_CUTOUT_MARKER.length();
                 } else {
                     currentIndex += 1;
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index b9868a7..3047385 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -28,6 +28,7 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
+import android.hardware.display.DeviceProductInfo;
 import android.os.Build;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -70,6 +71,13 @@
     public DisplayAddress address;
 
     /**
+     * Product-specific information about the display or the directly connected device on the
+     * display chain. For example, if the display is transitively connected, this field may contain
+     * product information about the intermediate device.
+     */
+    public DeviceProductInfo deviceProductInfo;
+
+    /**
      * The human-readable name of the display.
      */
     public String name;
@@ -297,6 +305,7 @@
                 && type == other.type
                 && displayId == other.displayId
                 && Objects.equals(address, other.address)
+                && Objects.equals(deviceProductInfo, other.deviceProductInfo)
                 && Objects.equals(uniqueId, other.uniqueId)
                 && appWidth == other.appWidth
                 && appHeight == other.appHeight
@@ -336,6 +345,7 @@
         type = other.type;
         displayId = other.displayId;
         address = other.address;
+        deviceProductInfo = other.deviceProductInfo;
         name = other.name;
         uniqueId = other.uniqueId;
         appWidth = other.appWidth;
@@ -373,6 +383,7 @@
         type = source.readInt();
         displayId = source.readInt();
         address = source.readParcelable(null);
+        deviceProductInfo = source.readParcelable(null);
         name = source.readString();
         appWidth = source.readInt();
         appHeight = source.readInt();
@@ -418,6 +429,7 @@
         dest.writeInt(type);
         dest.writeInt(displayId);
         dest.writeParcelable(address, flags);
+        dest.writeParcelable(deviceProductInfo, flags);
         dest.writeString(name);
         dest.writeInt(appWidth);
         dest.writeInt(appHeight);
@@ -645,6 +657,8 @@
         if (address != null) {
             sb.append(", address ").append(address);
         }
+        sb.append(", deviceProductInfo ");
+        sb.append(deviceProductInfo);
         sb.append(", state ");
         sb.append(Display.stateToString(state));
         if (ownerUid != 0 || ownerPackageName != null) {
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index 360dedd..58e5b2d 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -16,6 +16,7 @@
 
 package android.view;
 
+import android.annotation.IntDef;
 import android.annotation.RequiresPermission;
 import android.annotation.TestApi;
 import android.compat.annotation.UnsupportedAppUsage;
@@ -28,6 +29,8 @@
 import android.os.Parcelable;
 import android.os.Vibrator;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -138,6 +141,19 @@
      */
     public static final int SOURCE_CLASS_JOYSTICK = 0x00000010;
 
+    /** @hide */
+    @IntDef(flag = true, prefix = { "SOURCE_CLASS_" }, value = {
+            SOURCE_CLASS_NONE,
+            SOURCE_CLASS_BUTTON,
+            SOURCE_CLASS_POINTER,
+            SOURCE_CLASS_POINTER,
+            SOURCE_CLASS_TRACKBALL,
+            SOURCE_CLASS_POSITION,
+            SOURCE_CLASS_JOYSTICK
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface InputSourceClass {}
+
     /**
      * The input source is unknown.
      */
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 4ac6a66..13d6dd6 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import static android.system.OsConstants.EINVAL;
+
 import android.annotation.FloatRange;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
@@ -89,7 +91,8 @@
     private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
     private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
 
-    private static native int nativeSetFrameRate(long nativeObject, float frameRate);
+    private static native int nativeSetFrameRate(
+            long nativeObject, float frameRate, int compatibility);
 
     public static final @android.annotation.NonNull Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
@@ -184,6 +187,28 @@
      */
     public static final int ROTATION_270 = 3;
 
+    /** @hide */
+    @Retention(RetentionPolicy.SOURCE)
+    @IntDef(prefix = {"FRAME_RATE_COMPATIBILITY_"},
+            value = {FRAME_RATE_COMPATIBILITY_DEFAULT, FRAME_RATE_COMPATIBILITY_FIXED_SOURCE})
+    public @interface FrameRateCompatibility {}
+
+    // From native_window.h. Keep these in sync.
+    /**
+     * There are no inherent restrictions on the frame rate of this surface.
+     */
+    public static final int FRAME_RATE_COMPATIBILITY_DEFAULT = 0;
+
+    /**
+     * This surface is being used to display content with an inherently fixed frame rate,
+     * e.g. a video that has a specific frame rate. When the system selects a frame rate
+     * other than what the app requested, the app will need to do pull down or use some
+     * other technique to adapt to the system's frame rate. The user experience is likely
+     * to be worse (e.g. more frame stuttering) than it would be if the system had chosen
+     * the app's requested frame rate.
+     */
+    public static final int FRAME_RATE_COMPATIBILITY_FIXED_SOURCE = 1;
+
     /**
      * Create an empty surface, which will later be filled in by readFromParcel().
      * @hide
@@ -864,11 +889,23 @@
      * called. The frameRate param does *not* need to be a valid refresh rate for this
      * device's display - e.g., it's fine to pass 30fps to a device that can only run the
      * display at 60fps.
+     *
+     * @param compatibility The frame rate compatibility of this surface. The
+     * compatibility value may influence the system's choice of display frame rate. See
+     * the FRAME_RATE_COMPATIBILITY_* values for more info.
+     *
+     * @throws IllegalArgumentException If frameRate or compatibility are invalid.
      */
-    public void setFrameRate(@FloatRange(from = 0.0) float frameRate) {
-        int error = nativeSetFrameRate(mNativeObject, frameRate);
-        if (error != 0) {
-            throw new RuntimeException("Failed to set frame rate on Surface");
+    public void setFrameRate(
+            @FloatRange(from = 0.0) float frameRate, @FrameRateCompatibility int compatibility) {
+        synchronized (mLock) {
+            checkNotReleasedLocked();
+            int error = nativeSetFrameRate(mNativeObject, frameRate, compatibility);
+            if (error == -EINVAL) {
+                throw new IllegalArgumentException("Invalid argument to Surface.setFrameRate()");
+            } else if (error != 0) {
+                throw new RuntimeException("Failed to set frame rate on Surface");
+            }
         }
     }
 
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index cf48c52..0816e84 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -41,6 +41,7 @@
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.hardware.display.DeviceProductInfo;
 import android.hardware.display.DisplayedContentSample;
 import android.hardware.display.DisplayedContentSamplingAttributes;
 import android.os.Build;
@@ -213,7 +214,7 @@
             @Size(4) float[] spotColor, float lightPosY, float lightPosZ, float lightRadius);
 
     private static native void nativeSetFrameRate(
-            long transactionObj, long nativeObject, float frameRate);
+            long transactionObj, long nativeObject, float frameRate, int compatibility);
 
     private final CloseGuard mCloseGuard = CloseGuard.get();
     private String mName;
@@ -1286,12 +1287,14 @@
         public boolean isInternal;
         public float density;
         public boolean secure;
+        public DeviceProductInfo deviceProductInfo;
 
         @Override
         public String toString() {
             return "DisplayInfo{isInternal=" + isInternal
                     + ", density=" + density
-                    + ", secure=" + secure + "}";
+                    + ", secure=" + secure
+                    + ", deviceProductInfo=" + deviceProductInfo + "}";
         }
     }
 
@@ -2735,13 +2738,17 @@
          *                  isn't called. The frameRate param does *not* need to be a valid refresh
          *                  rate for this device's display - e.g., it's fine to pass 30fps to a
          *                  device that can only run the display at 60fps.
+         * @param compatibility The frame rate compatibility of this surface. The compatibility
+         *                      value may influence the system's choice of display frame rate. See
+         *                      the Surface.FRAME_RATE_COMPATIBILITY_* values for more info.
          * @return This transaction object.
          */
         @NonNull
-        public Transaction setFrameRate(
-                @NonNull SurfaceControl sc, @FloatRange(from = 0.0) float frameRate) {
+        public Transaction setFrameRate(@NonNull SurfaceControl sc,
+                @FloatRange(from = 0.0) float frameRate,
+                @Surface.FrameRateCompatibility int compatibility) {
             checkPreconditions(sc);
-            nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate);
+            nativeSetFrameRate(mNativeObject, sc.mNativeObject, frameRate, compatibility);
             return this;
         }
 
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 5566e0e..73707ca 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -788,9 +788,16 @@
         final boolean sizeChanged = mSurfaceWidth != myWidth || mSurfaceHeight != myHeight;
         final boolean windowVisibleChanged = mWindowVisibility != mLastWindowVisibility;
         boolean redrawNeeded = false;
+        getLocationInSurface(mLocation);
+        final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
+            || mWindowSpaceTop != mLocation[1];
+        final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
+            || getHeight() != mScreenRect.height();
 
-        if (creating || formatChanged || sizeChanged || visibleChanged || (mUseAlpha
-                && alphaChanged) || windowVisibleChanged) {
+
+        if (creating || formatChanged || sizeChanged || visibleChanged ||
+                (mUseAlpha && alphaChanged) || windowVisibleChanged ||
+                positionChanged || layoutSizeChanged) {
             getLocationInWindow(mLocation);
 
             if (DEBUG) Log.i(TAG, System.identityHashCode(this) + " "
@@ -922,6 +929,9 @@
                             mTmpTransaction.setWindowCrop(mSurfaceControl, mSurfaceWidth,
                                     mSurfaceHeight);
                         }
+                    } else if ((layoutSizeChanged || positionChanged) &&
+                            WindowManagerGlobal.useBLAST()) {
+                        viewRoot.setUseBLASTSyncTransaction();
                     }
                     mTmpTransaction.setCornerRadius(mSurfaceControl, mCornerRadius);
                     if (sizeChanged && !creating) {
@@ -1058,11 +1068,6 @@
         } else {
             // Calculate the window position in case RT loses the window
             // and we need to fallback to a UI-thread driven position update
-            getLocationInSurface(mLocation);
-            final boolean positionChanged = mWindowSpaceLeft != mLocation[0]
-                    || mWindowSpaceTop != mLocation[1];
-            final boolean layoutSizeChanged = getWidth() != mScreenRect.width()
-                    || getHeight() != mScreenRect.height();
             if (positionChanged || layoutSizeChanged) { // Only the position has changed
                 mWindowSpaceLeft = mLocation[0];
                 mWindowSpaceTop = mLocation[1];
@@ -1540,21 +1545,6 @@
     }
 
     /**
-     * @hide
-     * Note: Base class method is @UnsupportedAppUsage
-     */
-    @Override
-    public void invalidate(boolean invalidateCache) {
-        super.invalidate(invalidateCache);
-        if (!WindowManagerGlobal.useBLAST()) {
-            return;
-        }
-        final ViewRootImpl viewRoot = getViewRootImpl();
-        if (viewRoot == null) return;
-        viewRoot.setUseBLASTSyncTransaction();
-    }
-
-    /**
      * Display the view-hierarchy embedded within a {@link SurfaceControlViewHost.SurfacePackage}
      * within this SurfaceView. If this SurfaceView is above it's host Surface (see
      * {@link #setZOrderOnTop} then the embedded Surface hierarchy will be able to receive
@@ -1596,6 +1586,19 @@
         info.addChild(wrapper.getLeashToken());
     }
 
+    @Override
+    public int getImportantForAccessibility() {
+        final int mode = super.getImportantForAccessibility();
+        // If developers explicitly set the important mode for it, don't change the mode.
+        // Only change the mode to important when this SurfaceView isn't explicitly set and has
+        // an embedded hierarchy.
+        if (mRemoteAccessibilityEmbeddedConnection == null
+                || mode != IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
+            return mode;
+        }
+        return IMPORTANT_FOR_ACCESSIBILITY_YES;
+    }
+
     private void initEmbeddedHierarchyForAccessibility(SurfaceControlViewHost.SurfacePackage p) {
         final IAccessibilityEmbeddedConnection connection = p.getAccessibilityEmbeddedConnection();
         final RemoteAccessibilityEmbeddedConnection wrapper =
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c7f850a..11ab572 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -110,6 +110,7 @@
 import android.view.AccessibilityIterators.TextSegmentIterator;
 import android.view.AccessibilityIterators.WordTextSegmentIterator;
 import android.view.ContextMenu.ContextMenuInfo;
+import android.view.InputDevice.InputSourceClass;
 import android.view.Window.OnContentApplyWindowInsetsListener;
 import android.view.WindowInsets.Type;
 import android.view.WindowInsetsAnimation.Bounds;
@@ -5205,6 +5206,14 @@
     private int mExplicitStyle;
 
     /**
+     * Specifies which input source classes should provide unbuffered input events to this view
+     *
+     * @see View#requestUnbufferedDispatch(int)
+     */
+    @InputSourceClass
+    int mUnbufferedInputSource = InputDevice.SOURCE_CLASS_NONE;
+
+    /**
      * Simple constructor to use when creating a view from code.
      *
      * @param context The Context the view is running in, through which it can
@@ -8013,6 +8022,10 @@
             mAttachInfo.mKeyDispatchState.reset(this);
         }
 
+        if (mParent != null) {
+            mParent.onDescendantUnbufferedRequested();
+        }
+
         notifyEnterOrExitForAutoFillIfNeeded(gainFocus);
     }
 
@@ -13429,8 +13442,7 @@
      * @see #getImportantForAccessibility()
      */
     public boolean isImportantForAccessibility() {
-        final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
-                >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
+        final int mode = getImportantForAccessibility();
         if (mode == IMPORTANT_FOR_ACCESSIBILITY_NO
                 || mode == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
             return false;
@@ -15820,12 +15832,17 @@
      * system not batch {@link MotionEvent}s but instead deliver them as soon as they're
      * available. This method should only be called for touch events.
      *
-     * <p class="note">This api is not intended for most applications. Buffered dispatch
+     * <p class="note">This API is not intended for most applications. Buffered dispatch
      * provides many of benefits, and just requesting unbuffered dispatch on most MotionEvent
      * streams will not improve your input latency. Side effects include: increased latency,
      * jittery scrolls and inability to take advantage of system resampling. Talk to your input
      * professional to see if {@link #requestUnbufferedDispatch(MotionEvent)} is right for
      * you.</p>
+     *
+     * To receive unbuffered events for arbitrary input device source classes, use
+     * {@link #requestUnbufferedDispatch(int)},
+     *
+     * @see View#requestUnbufferedDispatch(int)
      */
     public final void requestUnbufferedDispatch(MotionEvent event) {
         final int action = event.getAction();
@@ -15837,6 +15854,27 @@
         mAttachInfo.mUnbufferedDispatchRequested = true;
     }
 
+    /**
+     * Request unbuffered dispatch of the given event source class to this view.
+     * This is similar to {@link View#requestUnbufferedDispatch(MotionEvent)}, but does not
+     * automatically terminate, and allows the specification of arbitrary input source classes.
+     *
+     * @param source The combined input source class to request unbuffered dispatch for. All
+     *               events coming from these source classes will not be buffered. Set to
+     *               {@link InputDevice#SOURCE_CLASS_NONE} in order to return to default behaviour.
+     *
+     * @see View#requestUnbufferedDispatch(MotionEvent)
+     */
+    public final void requestUnbufferedDispatch(@InputSourceClass int source) {
+        if (mUnbufferedInputSource == source) {
+            return;
+        }
+        mUnbufferedInputSource = source;
+        if (mParent != null) {
+            mParent.onDescendantUnbufferedRequested();
+        }
+    }
+
     private boolean hasSize() {
         return (mBottom > mTop) && (mRight > mLeft);
     }
@@ -28820,6 +28858,12 @@
         final Point mLocationInParentDisplay = new Point();
 
         /**
+         * The screen matrix of this view when it's on a {@link SurfaceControlViewHost} that is
+         * embedded within a SurfaceView.
+         */
+        Matrix mScreenMatrixInEmbeddedHierarchy;
+
+        /**
          * Global to the view hierarchy used as a temporary for dealing with
          * x/y points in the transparent region computations.
          */
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 0367536..b6c46be 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3692,6 +3692,31 @@
             }
             childrenForAccessibility.clear();
         }
+        info.setAvailableExtraData(Collections.singletonList(
+                AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY));
+    }
+
+    /**
+     * {@inheritDoc}
+     *
+     * @param info The info to which to add the extra data. Never {@code null}.
+     * @param extraDataKey A key specifying the type of extra data to add to the info. The
+     *                     extra data should be added to the {@link Bundle} returned by
+     *                     the info's {@link AccessibilityNodeInfo#getExtras} method. Never
+     *                     {@code null}.
+     * @param arguments A {@link Bundle} holding any arguments relevant for this request. May be
+     *                  {@code null} if the service provided no arguments.
+     *
+     */
+    @Override
+    public void addExtraDataToAccessibilityNodeInfo(@NonNull AccessibilityNodeInfo info,
+            @NonNull String extraDataKey, @Nullable Bundle arguments) {
+        if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
+            final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
+                    AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
+            extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
+            info.setExtraRenderingInfo(extraRenderingInfo);
+        }
     }
 
     @Override
@@ -9004,4 +9029,30 @@
             getChildAt(i).encode(encoder);
         }
     }
+
+    /** @hide */
+    @Override
+    public final void onDescendantUnbufferedRequested() {
+        // First look at the focused child for focused events
+        int focusedChildNonPointerSource = InputDevice.SOURCE_CLASS_NONE;
+        if (mFocused != null) {
+            focusedChildNonPointerSource = mFocused.mUnbufferedInputSource
+                    & (~InputDevice.SOURCE_CLASS_POINTER);
+        }
+        mUnbufferedInputSource = focusedChildNonPointerSource;
+
+        // Request unbuffered dispatch for pointer events for this view if any child requested
+        // unbuffered dispatch for pointer events. This is because we can't expect that the pointer
+        // source would dispatch to the focused view.
+        for (int i = 0; i < mChildrenCount; i++) {
+            final View child = mChildren[i];
+            if ((child.mUnbufferedInputSource & InputDevice.SOURCE_CLASS_POINTER) != 0) {
+                mUnbufferedInputSource |= InputDevice.SOURCE_CLASS_POINTER;
+                break;
+            }
+        }
+        if (mParent != null) {
+            mParent.onDescendantUnbufferedRequested();
+        }
+    }
 }
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index f25206d..775c15e 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -675,4 +675,18 @@
      */
     default void subtractObscuredTouchableRegion(Region touchableRegion, View view) {
     }
+
+    /**
+     * Unbuffered dispatch has been requested by a child of this view parent.
+     * This method is called by the View hierarchy to signal ancestors that a View needs to
+     * request unbuffered dispatch.
+     *
+     * @see View#requestUnbufferedDispatch(int)
+     * @hide
+     */
+    default void onDescendantUnbufferedRequested() {
+        if (getParent() != null) {
+            getParent().onDescendantUnbufferedRequested();
+        }
+    }
 }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 44ab596..204d2c8 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -18,6 +18,7 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
+import static android.view.InputDevice.SOURCE_CLASS_NONE;
 import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
 import static android.view.InsetsState.ITYPE_STATUS_BAR;
 import static android.view.View.PFLAG_DRAW_ANIMATION;
@@ -116,6 +117,7 @@
 import android.util.SparseArray;
 import android.util.TimeUtils;
 import android.util.TypedValue;
+import android.view.InputDevice.InputSourceClass;
 import android.view.InsetsState.InternalInsetsType;
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl.Transaction;
@@ -499,6 +501,10 @@
     int mPendingInputEventCount;
     boolean mProcessInputEventsScheduled;
     boolean mUnbufferedInputDispatch;
+    boolean mUnbufferedInputDispatchBySource;
+    @InputSourceClass
+    int mUnbufferedInputSource = SOURCE_CLASS_NONE;
+
     String mPendingInputEventQueueLengthCounterName = "pq";
 
     InputStage mFirstInputStage;
@@ -666,7 +672,22 @@
         int localChanges;
     }
 
+    // If set, ViewRootImpl will call BLASTBufferQueue::setNextTransaction with
+    // mRtBLASTSyncTransaction, prior to invoking draw. This provides a way
+    // to redirect the buffers in to transactions.
     private boolean mNextDrawUseBLASTSyncTransaction;
+    // Set when calling setNextTransaction, we can't just reuse mNextDrawUseBLASTSyncTransaction
+    // because, imagine this scenario:
+    //     1. First draw is using BLAST, mNextDrawUseBLAST = true
+    //     2. We call perform draw and are waiting on the callback
+    //     3. After the first perform draw but before the first callback and the
+    //        second perform draw, a second draw sets mNextDrawUseBLAST = true (it already was)
+    //     4. At this point the callback fires and we set mNextDrawUseBLAST = false;
+    //     5. We get to performDraw and fail to sync as we intended because mNextDrawUseBLAST
+    //        is now false.
+    // This is why we use a two-step latch with the two booleans, one consumed from
+    // performDraw and one consumed from finishBLASTSync()
+    private boolean mNextReportConsumeBLAST;
     // Be very careful with the threading here. This is used from the render thread while
     // the UI thread is paused and then applied and cleared from the UI thread right after
     // draw returns.
@@ -1834,7 +1855,7 @@
             mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
             mChoreographer.postCallback(
                     Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
-            if (!mUnbufferedInputDispatch) {
+            if (!mUnbufferedInputDispatch && !mUnbufferedInputDispatchBySource) {
                 scheduleConsumeBatchedInput();
             }
             notifyRendererOfFramePending();
@@ -2206,8 +2227,9 @@
         return insets;
     }
 
-    void dispatchApplyInsets(View host) {
+    public void dispatchApplyInsets(View host) {
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "dispatchApplyInsets");
+        mApplyInsetsRequested = false;
         WindowInsets insets = getWindowInsets(true /* forceConstruct */);
         final boolean dispatchCutout = (mWindowAttributes.layoutInDisplayCutoutMode
                 == LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS);
@@ -2444,7 +2466,6 @@
         }
 
         if (mApplyInsetsRequested) {
-            mApplyInsetsRequested = false;
             updateVisibleInsets();
             dispatchApplyInsets(host);
             if (mLayoutRequested) {
@@ -2621,7 +2642,6 @@
                 if (contentInsetsChanged || mLastSystemUiVisibility !=
                         mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
                     mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
-                    mApplyInsetsRequested = false;
                     dispatchApplyInsets(host);
                     // We applied insets so force contentInsetsChanged to ensure the
                     // hierarchy is measured below.
@@ -3719,9 +3739,9 @@
             usingAsyncReport = mReportNextDraw;
             if (needFrameCompleteCallback) {
                 final Handler handler = mAttachInfo.mHandler;
-                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) ->
+                mAttachInfo.mThreadedRenderer.setFrameCompleteCallback((long frameNr) -> {
+                        finishBLASTSync();
                         handler.postAtFrontOfQueue(() -> {
-                            finishBLASTSync();
                             if (reportNextDraw) {
                                 // TODO: Use the frame number
                                 pendingDrawFinished();
@@ -3731,12 +3751,23 @@
                                     commitCallbacks.get(i).run();
                                 }
                             }
-                        }));
+                        });});
             }
         }
 
         try {
             if (mNextDrawUseBLASTSyncTransaction) {
+                // TODO(b/149747443)
+                // We aren't prepared to handle overlapping use of mRtBLASTSyncTransaction
+                // so if we are BLAST syncing we make sure the previous draw has
+                // totally finished.
+                if (mAttachInfo.mThreadedRenderer != null) {
+                    mAttachInfo.mThreadedRenderer.fence();
+                }
+
+                mNextReportConsumeBLAST = true;
+                mNextDrawUseBLASTSyncTransaction = false;
+
                 mBlastBufferQueue.setNextTransaction(mRtBLASTSyncTransaction);
             }
             boolean canUseAsync = draw(fullRedrawNeeded);
@@ -7480,6 +7511,9 @@
                 writer.print(mTraversalScheduled);
         writer.print(innerPrefix); writer.print("mIsAmbientMode=");
                 writer.print(mIsAmbientMode);
+        writer.print(innerPrefix); writer.print("mUnbufferedInputSource=");
+        writer.print(Integer.toHexString(mUnbufferedInputSource));
+
         if (mTraversalScheduled) {
             writer.print(" (barrier="); writer.print(mTraversalBarrier); writer.println(")");
         } else {
@@ -8084,6 +8118,7 @@
         @Override
         public void onInputEvent(InputEvent event) {
             Trace.traceBegin(Trace.TRACE_TAG_VIEW, "processInputEventForCompatibility");
+            processUnbufferedRequest(event);
             List<InputEvent> processedEvents;
             try {
                 processedEvents =
@@ -8109,7 +8144,7 @@
 
         @Override
         public void onBatchedInputEventPending() {
-            if (mUnbufferedInputDispatch) {
+            if (mUnbufferedInputDispatch || mUnbufferedInputDispatchBySource) {
                 super.onBatchedInputEventPending();
             } else {
                 scheduleConsumeBatchedInput();
@@ -8126,6 +8161,17 @@
             unscheduleConsumeBatchedInput();
             super.dispose();
         }
+
+        private void processUnbufferedRequest(InputEvent event) {
+            if (!(event instanceof MotionEvent)) {
+                return;
+            }
+            mUnbufferedInputDispatchBySource =
+                    (event.getSource() & mUnbufferedInputSource) != SOURCE_CLASS_NONE;
+            if (mUnbufferedInputDispatchBySource && mConsumeBatchedInputScheduled) {
+                scheduleConsumeBatchedInputImmediately();
+            }
+        }
     }
     WindowInputEventReceiver mInputEventReceiver;
 
@@ -9556,8 +9602,8 @@
     }
 
     private void finishBLASTSync() {
-        if (mNextDrawUseBLASTSyncTransaction) {
-            mNextDrawUseBLASTSyncTransaction = false;
+        if (mNextReportConsumeBLAST) {
+            mNextReportConsumeBLAST = false;
             mRtBLASTSyncTransaction.apply();
         }
     }
@@ -9566,11 +9612,19 @@
         return mRtBLASTSyncTransaction;
     }
 
-    SurfaceControl getRenderSurfaceControl() {
+    /**
+     * @hide
+     */
+    public SurfaceControl getRenderSurfaceControl() {
         if (mUseBLASTAdapter) {
             return mBlastSurfaceControl;
         } else {
             return mSurfaceControl;
         }
     }
+
+    @Override
+    public void onDescendantUnbufferedRequested() {
+        mUnbufferedInputSource = mView.mUnbufferedInputSource;
+    }
 }
diff --git a/core/java/android/view/WindowContainerTransaction.java b/core/java/android/view/WindowContainerTransaction.java
index cf34b0b..f406be9 100644
--- a/core/java/android/view/WindowContainerTransaction.java
+++ b/core/java/android/view/WindowContainerTransaction.java
@@ -26,6 +26,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
+import android.view.SurfaceControl;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -77,8 +78,28 @@
     public WindowContainerTransaction scheduleFinishEnterPip(IWindowContainer container,
             Rect bounds) {
         Change chg = getOrCreateChange(container.asBinder());
-        chg.mSchedulePipCallback = true;
         chg.mPinnedBounds = new Rect(bounds);
+        chg.mChangeMask |= Change.CHANGE_PIP_CALLBACK;
+
+        return this;
+    }
+
+    /**
+     * Send a SurfaceControl transaction to the server, which the server will apply in sync with
+     * the next bounds change. As this uses deferred transaction and not BLAST it is only
+     * able to sync with a single window, and the first visible window in this hierarchy of type
+     * BASE_APPLICATION to resize will be used. If there are bound changes included in this
+     * WindowContainer transaction (from setBounds or scheduleFinishEnterPip), the SurfaceControl
+     * transaction will be synced with those bounds. If there are no changes, then
+     * the SurfaceControl transaction will be synced with the next bounds change. This means
+     * that you can call this, apply the WindowContainer transaction, and then later call
+     * dismissPip() to achieve synchronization.
+     */
+    public WindowContainerTransaction setBoundsChangeTransaction(IWindowContainer container,
+            SurfaceControl.Transaction t) {
+        Change chg = getOrCreateChange(container.asBinder());
+        chg.mBoundsChangeTransaction = t;
+        chg.mChangeMask |= Change.CHANGE_BOUNDS_TRANSACTION;
         return this;
     }
 
@@ -174,6 +195,8 @@
      */
     public static class Change implements Parcelable {
         public static final int CHANGE_FOCUSABLE = 1;
+        public static final int CHANGE_BOUNDS_TRANSACTION = 1 << 1;
+        public static final int CHANGE_PIP_CALLBACK = 1 << 2;
 
         private final Configuration mConfiguration = new Configuration();
         private boolean mFocusable = true;
@@ -181,8 +204,8 @@
         private @ActivityInfo.Config int mConfigSetMask = 0;
         private @WindowConfiguration.WindowConfig int mWindowSetMask = 0;
 
-        private boolean mSchedulePipCallback = false;
         private Rect mPinnedBounds = null;
+        private SurfaceControl.Transaction mBoundsChangeTransaction = null;
 
         public Change() {}
 
@@ -192,11 +215,14 @@
             mChangeMask = in.readInt();
             mConfigSetMask = in.readInt();
             mWindowSetMask = in.readInt();
-            mSchedulePipCallback = (in.readInt() != 0);
-            if (mSchedulePipCallback ) {
+            if ((mChangeMask & Change.CHANGE_PIP_CALLBACK) != 0) {
                 mPinnedBounds = new Rect();
                 mPinnedBounds.readFromParcel(in);
             }
+            if ((mChangeMask & Change.CHANGE_BOUNDS_TRANSACTION) != 0) {
+                mBoundsChangeTransaction =
+                    SurfaceControl.Transaction.CREATOR.createFromParcel(in);
+            }
         }
 
         public Configuration getConfiguration() {
@@ -233,6 +259,10 @@
             return mPinnedBounds;
         }
 
+        public SurfaceControl.Transaction getBoundsChangeTransaction() {
+            return mBoundsChangeTransaction;
+        }
+
         @Override
         public String toString() {
             final boolean changesBounds =
@@ -264,10 +294,12 @@
             dest.writeInt(mConfigSetMask);
             dest.writeInt(mWindowSetMask);
 
-            dest.writeInt(mSchedulePipCallback ? 1 : 0);
-            if (mSchedulePipCallback ) {
+            if (mPinnedBounds != null) {
                 mPinnedBounds.writeToParcel(dest, flags);
             }
+            if (mBoundsChangeTransaction != null) {
+                mBoundsChangeTransaction.writeToParcel(dest, flags);
+            }
         }
 
         @Override
diff --git a/core/java/android/view/WindowManagerImpl.java b/core/java/android/view/WindowManagerImpl.java
index 56683dd..d40f505 100644
--- a/core/java/android/view/WindowManagerImpl.java
+++ b/core/java/android/view/WindowManagerImpl.java
@@ -101,7 +101,7 @@
     @Override
     public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
         applyDefaultToken(params);
-        mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
+        mGlobal.addView(view, params, mContext.getDisplayNoVerify(), mParentWindow);
         mIsViewAdded = true;
         mLastView = view;
         mLastParams = (WindowManager.LayoutParams) params;
@@ -158,7 +158,7 @@
 
     @Override
     public Display getDefaultDisplay() {
-        return mContext.getDisplay();
+        return mContext.getDisplayNoVerify();
     }
 
     @Override
@@ -240,7 +240,7 @@
     private Rect getMaximumBounds() {
         // TODO(b/128338354): Current maximum bound is display size, but it should be displayArea
         //  bound after displayArea feature is finished.
-        final Display display = mContext.getDisplay();
+        final Display display = mContext.getDisplayNoVerify();
         final Point displaySize = new Point();
         display.getRealSize(displaySize);
         return new Rect(0, 0, displaySize.x, displaySize.y);
diff --git a/core/java/android/view/WindowlessWindowManager.java b/core/java/android/view/WindowlessWindowManager.java
index 62f3fa4..87dcba0 100644
--- a/core/java/android/view/WindowlessWindowManager.java
+++ b/core/java/android/view/WindowlessWindowManager.java
@@ -163,6 +163,15 @@
         return !PixelFormat.formatHasAlpha(attrs.format);
     }
 
+    /** @hide */
+    protected SurfaceControl getSurfaceControl(View rootView) {
+        final State s = mStateForWindow.get(rootView.getViewRootImpl().mWindow.asBinder());
+        if (s == null) {
+            return null;
+        }
+        return s.mSurfaceControl;
+    }
+
     @Override
     public int relayout(IWindow window, int seq, WindowManager.LayoutParams inAttrs,
             int requestedWidth, int requestedHeight, int viewFlags, int flags, long frameNumber,
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index bf2de14..eb4f9db 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -50,8 +50,12 @@
 import android.util.Log;
 import android.util.LongArray;
 import android.util.Pools.SynchronizedPool;
+import android.util.Size;
+import android.util.TypedValue;
 import android.view.TouchDelegate;
 import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
 
 import com.android.internal.R;
 import com.android.internal.util.CollectionUtils;
@@ -634,6 +638,25 @@
     public static final String EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH =
             "android.view.accessibility.extra.DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH";
 
+    /**
+     * Key used to request extra data for accessibility scanning tool's purposes.
+     * The key requests that a {@link AccessibilityNodeInfo.ExtraRenderingInfo} be added to this
+     * info. This request is made with {@link #refreshWithExtraData(String, Bundle)} without
+     * argument.
+     * <p>
+     * The data can be retrieved from the {@link ExtraRenderingInfo} returned by
+     * {@link #getExtraRenderingInfo()} using {@link ExtraRenderingInfo#getLayoutParams},
+     * {@link ExtraRenderingInfo#getTextSizeInPx()} and
+     * {@link ExtraRenderingInfo#getTextSizeUnit()}. For layout params, it is supported by both
+     * {@link TextView} and {@link ViewGroup}. For text size and unit, it is only supported by
+     * {@link TextView}.
+     *
+     * @see #refreshWithExtraData(String, Bundle)
+     */
+
+    public static final String EXTRA_DATA_RENDERING_INFO_KEY =
+            "android.view.accessibility.extra.DATA_RENDERING_INFO_KEY";
+
     /** @hide */
     public static final String EXTRA_DATA_REQUESTED_KEY =
             "android.view.accessibility.AccessibilityNodeInfo.extra_data_requested";
@@ -804,6 +827,8 @@
 
     private TouchDelegateInfo mTouchDelegateInfo;
 
+    private ExtraRenderingInfo mExtraRenderingInfo;
+
     private IBinder mLeashedChild;
     private IBinder mLeashedParent;
     private long mLeashedParentNodeId = UNDEFINED_NODE_ID;
@@ -991,6 +1016,7 @@
      * @param extraDataKey The extra data requested. Data that must be requested
      *                     with this mechanism is generally expensive to retrieve, so should only be
      *                     requested when needed. See
+     *                     {@link #EXTRA_DATA_RENDERING_INFO_KEY},
      *                     {@link #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY} and
      *                     {@link #getAvailableExtraData()}.
      * @param args A bundle of arguments for the request. These depend on the particular request.
@@ -1547,6 +1573,7 @@
      * {@link #refreshWithExtraData(String, Bundle)}.
      *
      * @return An unmodifiable list of keys corresponding to extra data that can be requested.
+     * @see #EXTRA_DATA_RENDERING_INFO_KEY
      * @see #EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
      */
     public List<String> getAvailableExtraData() {
@@ -2375,6 +2402,32 @@
     }
 
     /**
+     * Gets the conformance info if the node is meant to be refreshed with extra data.
+     *
+     * @return The conformance info.
+     */
+    @Nullable
+    public ExtraRenderingInfo getExtraRenderingInfo() {
+        return mExtraRenderingInfo;
+    }
+
+    /**
+     * Sets the conformance info if the node is meant to be refreshed with extra data.
+     * <p>
+     *   <strong>Note:</strong> Cannot be called from an
+     *   {@link android.accessibilityservice.AccessibilityService}.
+     *   This class is made immutable before being delivered to an AccessibilityService.
+     * </p>
+     *
+     * @param extraRenderingInfo The conformance info.
+     * @hide
+     */
+    public void setExtraRenderingInfo(@NonNull ExtraRenderingInfo extraRenderingInfo) {
+        enforceNotSealed();
+        mExtraRenderingInfo = extraRenderingInfo;
+    }
+
+    /**
      * Gets if the content of this node is invalid. For example,
      * a date is not well-formed.
      *
@@ -3695,6 +3748,10 @@
             nonDefaultFields |= bitAt(fieldIndex);
         }
         fieldIndex++;
+        if (!Objects.equals(mExtraRenderingInfo, DEFAULT.mExtraRenderingInfo)) {
+            nonDefaultFields |= bitAt(fieldIndex);
+        }
+        fieldIndex++;
         if (mLeashedChild != DEFAULT.mLeashedChild) {
             nonDefaultFields |= bitAt(fieldIndex);
         }
@@ -3833,6 +3890,12 @@
         }
 
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
+            parcel.writeValue(mExtraRenderingInfo.getLayoutParams());
+            parcel.writeFloat(mExtraRenderingInfo.getTextSizeInPx());
+            parcel.writeInt(mExtraRenderingInfo.getTextSizeUnit());
+        }
+
+        if (isBitSet(nonDefaultFields, fieldIndex++)) {
             parcel.writeStrongBinder(mLeashedChild);
         }
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
@@ -3941,6 +4004,9 @@
         if (mCollectionItemInfo != null) mCollectionItemInfo.recycle();
         mCollectionItemInfo =  (other.mCollectionItemInfo != null)
                 ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
+        if (mExtraRenderingInfo != null) mExtraRenderingInfo.recycle();
+        mExtraRenderingInfo = (other.mExtraRenderingInfo != null)
+                ? ExtraRenderingInfo.obtain(other.mExtraRenderingInfo) : null;
     }
 
     private void initCopyInfos(AccessibilityNodeInfo other) {
@@ -3955,6 +4021,9 @@
         mCollectionItemInfo = (cii == null)  ? null
                 : new CollectionItemInfo(cii.mRowIndex, cii.mRowSpan, cii.mColumnIndex,
                                          cii.mColumnSpan, cii.mHeading, cii.mSelected);
+        ExtraRenderingInfo ti = other.mExtraRenderingInfo;
+        mExtraRenderingInfo = (ti == null) ? null
+                : new ExtraRenderingInfo(ti);
     }
 
     /**
@@ -4083,6 +4152,14 @@
         }
 
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
+            if (mExtraRenderingInfo != null) mExtraRenderingInfo.recycle();
+            mExtraRenderingInfo = ExtraRenderingInfo.obtain();
+            mExtraRenderingInfo.mLayoutParams = (Size) parcel.readValue(null);
+            mExtraRenderingInfo.mTextSizeInPx = parcel.readFloat();
+            mExtraRenderingInfo.mTextSizeUnit = parcel.readInt();
+        }
+
+        if (isBitSet(nonDefaultFields, fieldIndex++)) {
             mLeashedChild = parcel.readStrongBinder();
         }
         if (isBitSet(nonDefaultFields, fieldIndex++)) {
@@ -5679,6 +5756,134 @@
     }
 
     /**
+     * Class with information of a view useful to evaluate accessibility needs. Developers can
+     * refresh the node with the key {@link #EXTRA_DATA_RENDERING_INFO_KEY} to fetch the text size
+     * and unit if it is {@link TextView} and the height and the width of layout params from
+     * {@link ViewGroup} or {@link TextView}.
+     *
+     * @see #EXTRA_DATA_RENDERING_INFO_KEY
+     * @see #refreshWithExtraData(String, Bundle)
+     */
+    public static final class ExtraRenderingInfo {
+        private static final int UNDEFINED_VALUE = -1;
+        private static final int MAX_POOL_SIZE = 20;
+        private static final SynchronizedPool<ExtraRenderingInfo> sPool =
+                new SynchronizedPool<>(MAX_POOL_SIZE);
+
+        private Size mLayoutParams;
+        private float mTextSizeInPx = UNDEFINED_VALUE;
+        private int mTextSizeUnit = UNDEFINED_VALUE;
+
+        /**
+         * Obtains a pooled instance.
+         * @hide
+         */
+        @NonNull
+        public static ExtraRenderingInfo obtain() {
+            final ExtraRenderingInfo info = sPool.acquire();
+            if (info == null) {
+                return new ExtraRenderingInfo(null);
+            }
+            return info;
+        }
+
+        /** Obtains a pooled instance that is a clone of another one. */
+        private static ExtraRenderingInfo obtain(ExtraRenderingInfo other) {
+            ExtraRenderingInfo extraRenderingInfo = ExtraRenderingInfo.obtain();
+            extraRenderingInfo.mLayoutParams = other.mLayoutParams;
+            extraRenderingInfo.mTextSizeInPx = other.mTextSizeInPx;
+            extraRenderingInfo.mTextSizeUnit = other.mTextSizeUnit;
+            return extraRenderingInfo;
+        }
+
+        /**
+         * Creates a new conformance info of a view, and this new instance is initialized from
+         * the given <code>other</code>.
+         *
+         * @param other The instance to clone.
+         */
+        private ExtraRenderingInfo(@Nullable ExtraRenderingInfo other) {
+            if (other != null) {
+                mLayoutParams = other.mLayoutParams;
+                mTextSizeInPx = other.mTextSizeInPx;
+                mTextSizeUnit = other.mTextSizeUnit;
+            }
+        }
+
+        /**
+         * @return a {@link Size} stores layout height and layout width of the view,
+         *         or null otherwise.
+         */
+        public @Nullable Size getLayoutParams() {
+            return mLayoutParams;
+        }
+
+        /**
+         * Sets layout width and layout height of the view.
+         *
+         * @param width The layout width.
+         * @param height The layout height.
+         * @hide
+         */
+        public void setLayoutParams(int width, int height) {
+            mLayoutParams = new Size(width, height);
+        }
+
+        /**
+         * @return the text size of a {@code TextView}, or -1 otherwise.
+         */
+        public float getTextSizeInPx() {
+            return mTextSizeInPx;
+        }
+
+        /**
+         * Sets text size of the view.
+         *
+         * @param textSizeInPx The text size in pixels.
+         * @hide
+         */
+        public void setTextSizeInPx(float textSizeInPx) {
+            mTextSizeInPx = textSizeInPx;
+        }
+
+        /**
+         * @return the text size unit which type is {@link TypedValue#TYPE_DIMENSION} of a
+         *         {@code TextView}, or -1 otherwise.
+         *
+         * @see TypedValue#TYPE_DIMENSION
+         */
+        public int getTextSizeUnit() {
+            return mTextSizeUnit;
+        }
+
+        /**
+         * Sets text size unit of the view.
+         *
+         * @param textSizeUnit The text size unit.
+         * @hide
+         */
+        public void setTextSizeUnit(int textSizeUnit) {
+            mTextSizeUnit = textSizeUnit;
+        }
+
+        /**
+         * Recycles this instance.
+         *
+         * <p>In most situations object pooling is not beneficial, and recycling is not necessary.
+         */
+        void recycle() {
+            clear();
+            sPool.release(this);
+        }
+
+        private void clear() {
+            mLayoutParams = null;
+            mTextSizeInPx = UNDEFINED_VALUE;
+            mTextSizeUnit = UNDEFINED_VALUE;
+        }
+    }
+
+    /**
      * @see android.os.Parcelable.Creator
      */
     public static final @android.annotation.NonNull Parcelable.Creator<AccessibilityNodeInfo> CREATOR =
diff --git a/core/java/android/view/accessibility/OWNERS b/core/java/android/view/accessibility/OWNERS
index 265674a..c6f42f7 100644
--- a/core/java/android/view/accessibility/OWNERS
+++ b/core/java/android/view/accessibility/OWNERS
@@ -1,3 +1,4 @@
 svetoslavganov@google.com
 pweaver@google.com
 rhedjao@google.com
+qasid@google.com
diff --git a/core/java/android/view/autofill/AutofillManager.java b/core/java/android/view/autofill/AutofillManager.java
index 54bdb88..ce7cfa7 100644
--- a/core/java/android/view/autofill/AutofillManager.java
+++ b/core/java/android/view/autofill/AutofillManager.java
@@ -1794,6 +1794,9 @@
             client.autofillClientResetableStateAvailable();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
+        } catch (SyncResultReceiver.TimeoutException e) {
+            // no-op, just log the error message.
+            Log.w(TAG, "Exception getting result from SyncResultReceiver: " + e);
         }
     }
 
diff --git a/core/java/android/view/inline/InlinePresentationSpec.java b/core/java/android/view/inline/InlinePresentationSpec.java
index 8bda339..3cc04b8 100644
--- a/core/java/android/view/inline/InlinePresentationSpec.java
+++ b/core/java/android/view/inline/InlinePresentationSpec.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Size;
 
@@ -40,15 +41,13 @@
     private final Size mMaxSize;
 
     /**
-     * The fully qualified resource name of the UI style resource identifier, defaults to {@code
-     * null}.
-     *
-     * <p> The value can be obtained by calling {@code Resources#getResourceName(int)}.
+     * The extras encoding the UI style information. Defaults to {@code null} in which case the
+     * default system UI style will be used.
      */
     @Nullable
-    private final String mStyle;
+    private final Bundle mStyle;
 
-    private static String defaultStyle() {
+    private static Bundle defaultStyle() {
         return null;
     }
 
@@ -76,7 +75,7 @@
     /* package-private */ InlinePresentationSpec(
             @NonNull Size minSize,
             @NonNull Size maxSize,
-            @Nullable String style) {
+            @Nullable Bundle style) {
         this.mMinSize = minSize;
         com.android.internal.util.AnnotationValidations.validate(
                 NonNull.class, null, mMinSize);
@@ -105,13 +104,11 @@
     }
 
     /**
-     * The fully qualified resource name of the UI style resource identifier, defaults to {@code
-     * null}.
-     *
-     * <p> The value can be obtained by calling {@code Resources#getResourceName(int)}.
+     * The extras encoding the UI style information. Defaults to null in which case the default
+     * system UI style will be used.
      */
     @DataClass.Generated.Member
-    public @Nullable String getStyle() {
+    public @Nullable Bundle getStyle() {
         return mStyle;
     }
 
@@ -170,7 +167,7 @@
         dest.writeByte(flg);
         dest.writeSize(mMinSize);
         dest.writeSize(mMaxSize);
-        if (mStyle != null) dest.writeString(mStyle);
+        if (mStyle != null) dest.writeBundle(mStyle);
     }
 
     @Override
@@ -187,7 +184,7 @@
         byte flg = in.readByte();
         Size minSize = (Size) in.readSize();
         Size maxSize = (Size) in.readSize();
-        String style = (flg & 0x4) == 0 ? null : in.readString();
+        Bundle style = (flg & 0x4) == 0 ? null : in.readBundle();
 
         this.mMinSize = minSize;
         com.android.internal.util.AnnotationValidations.validate(
@@ -223,7 +220,7 @@
 
         private @NonNull Size mMinSize;
         private @NonNull Size mMaxSize;
-        private @Nullable String mStyle;
+        private @Nullable Bundle mStyle;
 
         private long mBuilderFieldsSet = 0L;
 
@@ -247,13 +244,11 @@
         }
 
         /**
-         * The fully qualified resource name of the UI style resource identifier, defaults to {@code
-         * null}.
-         *
-         * <p> The value can be obtained by calling {@code Resources#getResourceName(int)}.
+         * The extras encoding the UI style information. Defaults to null in which case the default
+         * system UI style will be used.
          */
         @DataClass.Generated.Member
-        public @NonNull Builder setStyle(@Nullable String value) {
+        public @NonNull Builder setStyle(@Nullable Bundle value) {
             checkNotUsed();
             mBuilderFieldsSet |= 0x4;
             mStyle = value;
@@ -284,10 +279,10 @@
     }
 
     @DataClass.Generated(
-            time = 1581736227796L,
+            time = 1582078731418L,
             codegenVersion = "1.0.14",
             sourceFile = "frameworks/base/core/java/android/view/inline/InlinePresentationSpec.java",
-            inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.Nullable java.lang.String mStyle\nprivate static  java.lang.String defaultStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
+            inputSignatures = "private final @android.annotation.NonNull android.util.Size mMinSize\nprivate final @android.annotation.NonNull android.util.Size mMaxSize\nprivate final @android.annotation.Nullable android.os.Bundle mStyle\nprivate static  android.os.Bundle defaultStyle()\nclass InlinePresentationSpec extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true, genToString=true, genBuilder=true)\nclass BaseBuilder extends java.lang.Object implements []")
     @Deprecated
     private void __metadata() {}
 
diff --git a/core/java/android/view/inputmethod/InputMethod.java b/core/java/android/view/inputmethod/InputMethod.java
index 91e15c1..71c9e33 100644
--- a/core/java/android/view/inputmethod/InputMethod.java
+++ b/core/java/android/view/inputmethod/InputMethod.java
@@ -21,17 +21,16 @@
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
-import android.content.ComponentName;
 import android.inputmethodservice.InputMethodService;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.util.Log;
 import android.view.View;
-import android.view.autofill.AutofillId;
 
 import com.android.internal.inputmethod.IInputMethodPrivilegedOperations;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 
 /**
  * The InputMethod interface represents an input method which can generate key
@@ -114,14 +113,13 @@
     /**
      * Called to notify the IME that Autofill Frameworks requested an inline suggestions request.
      *
-     * @param componentName {@link ComponentName} of current app/activity.
-     * @param autofillId {@link AutofillId} of currently focused field.
+     * @param requestInfo information needed to create an {@link InlineSuggestionsRequest}.
      * @param cb {@link IInlineSuggestionsRequestCallback} used to pass back the request object.
      *
      * @hide
      */
-    default void onCreateInlineSuggestionsRequest(ComponentName componentName,
-            AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
+    default void onCreateInlineSuggestionsRequest(InlineSuggestionsRequestInfo requestInfo,
+            IInlineSuggestionsRequestCallback cb) {
         try {
             cb.onInlineSuggestionsUnsupported();
         } catch (RemoteException e) {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index dbab81b1..39d5f5c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -93,12 +93,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.concurrent.CancellationException;
 import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 
@@ -415,16 +410,6 @@
     int mCursorCandEnd;
 
     /**
-     * Initial startInput with {@link StartInputReason.WINDOW_FOCUS_GAIN} is executed
-     * in a background thread. Later, if there is an actual startInput it will wait on
-     * main thread till the background thread completes.
-     */
-    private Future<?> mWindowFocusGainFuture;
-
-    private ExecutorService mStartInputWorker = Executors.newSingleThreadExecutor(
-            new ImeThreadFactory("StartInputWorker"));
-
-    /**
      * The instance that has previously been sent to the input method.
      */
     private CursorAnchorInfo mCursorAnchorInfo = null;
@@ -612,41 +597,36 @@
             final boolean forceNewFocus1 = forceNewFocus;
             final int startInputFlags = getStartInputFlags(focusedView, 0);
 
-            if (mWindowFocusGainFuture != null) {
-                mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
+            final ImeFocusController controller = getFocusController();
+            if (controller == null) {
+                return;
             }
-            mWindowFocusGainFuture = mStartInputWorker.submit(() -> {
-                final ImeFocusController controller = getFocusController();
-                if (controller == null) {
+            if (controller.checkFocus(forceNewFocus1, false)) {
+                // We need to restart input on the current focus view.  This
+                // should be done in conjunction with telling the system service
+                // about the window gaining focus, to help make the transition
+                // smooth.
+                if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
+                        focusedView, startInputFlags, softInputMode, windowFlags)) {
                     return;
                 }
-                if (controller.checkFocus(forceNewFocus1, false)) {
-                    // We need to restart input on the current focus view.  This
-                    // should be done in conjunction with telling the system service
-                    // about the window gaining focus, to help make the transition
-                    // smooth.
-                    if (startInput(StartInputReason.WINDOW_FOCUS_GAIN,
-                            focusedView, startInputFlags, softInputMode, windowFlags)) {
-                        return;
-                    }
-                }
+            }
 
-                synchronized (mH) {
-                    // For some reason we didn't do a startInput + windowFocusGain, so
-                    // we'll just do a window focus gain and call it a day.
-                    try {
-                        if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
-                        mService.startInputOrWindowGainedFocus(
-                                StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
-                                focusedView.getWindowToken(), startInputFlags, softInputMode,
-                                windowFlags,
-                                null, null, 0 /* missingMethodFlags */,
-                                mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
-                    } catch (RemoteException e) {
-                        throw e.rethrowFromSystemServer();
-                    }
+            synchronized (mH) {
+                // For some reason we didn't do a startInput + windowFocusGain, so
+                // we'll just do a window focus gain and call it a day.
+                try {
+                    if (DEBUG) Log.v(TAG, "Reporting focus gain, without startInput");
+                    mService.startInputOrWindowGainedFocus(
+                            StartInputReason.WINDOW_FOCUS_GAIN_REPORT_ONLY, mClient,
+                            focusedView.getWindowToken(), startInputFlags, softInputMode,
+                            windowFlags,
+                            null, null, 0 /* missingMethodFlags */,
+                            mCurRootView.mContext.getApplicationInfo().targetSdkVersion);
+                } catch (RemoteException e) {
+                    throw e.rethrowFromSystemServer();
                 }
-            });
+            }
         }
 
         /**
@@ -664,10 +644,6 @@
          */
         @Override
         public void setCurrentRootView(ViewRootImpl rootView) {
-            if (mWindowFocusGainFuture != null) {
-                mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
-                mWindowFocusGainFuture = null;
-            }
             synchronized (mH) {
                 if (mCurRootView != null) {
                     // Reset the last served view and restart window focus state of the root view.
@@ -845,19 +821,16 @@
                             } catch (RemoteException e) {
                             }
                         }
-                    }
-                    // Check focus again in case that "onWindowFocus" is called before
-                    // handling this message.
-                    final View servedView;
-                    synchronized (mH) {
-                        servedView = getServedViewLocked();
-                    }
-                    if (servedView != null && canStartInput(servedView)) {
-                        if (mCurRootView != null && mCurRootView.getImeFocusController()
-                                .checkFocus(mRestartOnNextWindowFocus, false)) {
-                            final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
-                                    : StartInputReason.DEACTIVATED_BY_IMMS;
-                            mDelegate.startInput(reason, null, 0, 0, 0);
+                        // Check focus again in case that "onWindowFocus" is called before
+                        // handling this message.
+                        final View servedView = getServedViewLocked();
+                        if (servedView != null && canStartInput(servedView)) {
+                            if (mCurRootView != null && mCurRootView.getImeFocusController()
+                                    .checkFocus(mRestartOnNextWindowFocus, false)) {
+                                final int reason = active ? StartInputReason.ACTIVATED_BY_IMMS
+                                        : StartInputReason.DEACTIVATED_BY_IMMS;
+                                mDelegate.startInput(reason, null, 0, 0, 0);
+                            }
                         }
                     }
                     return;
@@ -1035,6 +1008,13 @@
         }
 
         @Override
+        public void scheduleStartInputIfNecessary(boolean fullscreen) {
+            // TODO(b/149859205): See if we can optimize this by having a fused dedicated operation.
+            mH.obtainMessage(MSG_SET_ACTIVE, 0 /* active */, fullscreen ? 1 : 0).sendToTarget();
+            mH.obtainMessage(MSG_SET_ACTIVE, 1 /* active */, fullscreen ? 1 : 0).sendToTarget();
+        }
+
+        @Override
         public void reportFullscreenMode(boolean fullscreen) {
             mH.obtainMessage(MSG_REPORT_FULLSCREEN_MODE, fullscreen ? 1 : 0, 0)
                     .sendToTarget();
@@ -1430,10 +1410,6 @@
      */
     void clearBindingLocked() {
         if (DEBUG) Log.v(TAG, "Clearing binding!");
-        if (mWindowFocusGainFuture != null) {
-            mWindowFocusGainFuture.cancel(false /* mayInterruptIfRunning */);
-            mWindowFocusGainFuture = null;
-        }
         clearConnectionLocked();
         setInputChannelLocked(null);
         mBindSequence = -1;
@@ -1826,18 +1802,6 @@
     boolean startInputInner(@StartInputReason int startInputReason,
             @Nullable IBinder windowGainingFocus, @StartInputFlags int startInputFlags,
             @SoftInputModeFlags int softInputMode, int windowFlags) {
-        if (startInputReason != StartInputReason.WINDOW_FOCUS_GAIN
-                && mWindowFocusGainFuture != null) {
-            try {
-                mWindowFocusGainFuture.get();
-            } catch (ExecutionException | InterruptedException e) {
-                // do nothing
-            } catch (CancellationException e) {
-                // window no longer has focus.
-                return true;
-            }
-        }
-
         final View view;
         synchronized (mH) {
             view = getServedViewLocked();
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 12f245e..13c1f67 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -83,6 +83,7 @@
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.TypedValue;
 import android.view.ActionMode;
 import android.view.ActionMode.Callback;
 import android.view.ContextMenu;
@@ -151,9 +152,6 @@
     private static final String TAG = "Editor";
     private static final boolean DEBUG_UNDO = false;
 
-    // Specifies whether to allow starting a cursor drag by dragging anywhere over the text.
-    @VisibleForTesting
-    public static boolean FLAG_ENABLE_CURSOR_DRAG = true;
     // Specifies whether to use the magnifier when pressing the insertion or selection handles.
     private static final boolean FLAG_USE_MAGNIFIER = true;
 
@@ -387,13 +385,25 @@
 
     private final SuggestionHelper mSuggestionHelper = new SuggestionHelper();
 
-    // Specifies whether the cursor control feature set is enabled.
-    // This can only be true if the text view is editable.
-    private boolean mCursorControlEnabled;
+    private boolean mFlagCursorDragFromAnywhereEnabled;
+    private boolean mFlagInsertionHandleGesturesEnabled;
 
     // Specifies whether the new magnifier (with fish-eye effect) is enabled.
     private final boolean mNewMagnifierEnabled;
 
+    // Line height range in DP for the new magnifier.
+    static private final int MIN_LINE_HEIGHT_FOR_MAGNIFIER = 20;
+    static private final int MAX_LINE_HEIGHT_FOR_MAGNIFIER = 32;
+    // Line height range in pixels for the new magnifier.
+    //  - If the line height is bigger than the max, magnifier should be dismissed.
+    //  - If the line height is smaller than the min, magnifier should apply a bigger zoom factor
+    //    to make sure the text can be seen clearly.
+    private int mMinLineHeightForMagnifier;
+    private int mMaxLineHeightForMagnifier;
+    // The zoom factor initially configured.
+    // The actual zoom value may changes based on this initial zoom value.
+    private float mInitialZoom = 1f;
+
     Editor(TextView textView) {
         mTextView = textView;
         // Synchronize the filter list, which places the undo input filter at the end.
@@ -402,26 +412,43 @@
         mHapticTextHandleEnabled = mTextView.getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_enableHapticTextHandle);
 
-        mCursorControlEnabled = AppGlobals.getIntCoreSetting(
-                WidgetFlags.KEY_ENABLE_CURSOR_CONTROL , 0) != 0;
+        mFlagCursorDragFromAnywhereEnabled = AppGlobals.getIntCoreSetting(
+                WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE,
+                WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE_DEFAULT ? 1 : 0) != 0;
+        mFlagInsertionHandleGesturesEnabled = AppGlobals.getIntCoreSetting(
+                WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES,
+                WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES_DEFAULT ? 1 : 0) != 0;
         mNewMagnifierEnabled = AppGlobals.getIntCoreSetting(
-                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, 0) != 0;
+                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER,
+                WidgetFlags.ENABLE_NEW_MAGNIFIER_DEFAULT ? 1 : 0) != 0;
         if (TextView.DEBUG_CURSOR) {
-            logCursor("Editor", "Cursor control is %s.",
-                    mCursorControlEnabled ? "enabled" : "disabled");
+            logCursor("Editor", "Cursor drag from anywhere is %s.",
+                    mFlagCursorDragFromAnywhereEnabled ? "enabled" : "disabled");
+            logCursor("Editor", "Insertion handle gestures is %s.",
+                    mFlagInsertionHandleGesturesEnabled ? "enabled" : "disabled");
             logCursor("Editor", "New magnifier is %s.",
                     mNewMagnifierEnabled ? "enabled" : "disabled");
         }
     }
 
     @VisibleForTesting
-    public void setCursorControlEnabled(boolean enabled) {
-        mCursorControlEnabled = enabled;
+    public boolean getFlagCursorDragFromAnywhereEnabled() {
+        return mFlagCursorDragFromAnywhereEnabled;
     }
 
     @VisibleForTesting
-    public boolean getCursorControlEnabled() {
-        return mCursorControlEnabled;
+    public void setFlagCursorDragFromAnywhereEnabled(boolean enabled) {
+        mFlagCursorDragFromAnywhereEnabled = enabled;
+    }
+
+    @VisibleForTesting
+    public boolean getFlagInsertionHandleGesturesEnabled() {
+        return mFlagInsertionHandleGesturesEnabled;
+    }
+
+    @VisibleForTesting
+    public void setFlagInsertionHandleGesturesEnabled(boolean enabled) {
+        mFlagInsertionHandleGesturesEnabled = enabled;
     }
 
     // Lazy creates the magnifier animator.
@@ -440,12 +467,12 @@
     private Magnifier.Builder createBuilderWithInlineMagnifierDefaults() {
         final Magnifier.Builder params = new Magnifier.Builder(mTextView);
 
-        // TODO: supports changing the height/width dynamically because the text height can be
-        // dynamically changed.
         float zoom = AppGlobals.getFloatCoreSetting(
-                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, 1.5f);
+                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR,
+                WidgetFlags.MAGNIFIER_ZOOM_FACTOR_DEFAULT);
         float aspectRatio = AppGlobals.getFloatCoreSetting(
-                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, 5.5f);
+                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO,
+                WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT);
         // Avoid invalid/unsupported values.
         if (zoom < 1.2f || zoom > 1.8f) {
             zoom = 1.5f;
@@ -454,13 +481,20 @@
             aspectRatio = 5.5f;
         }
 
+        mInitialZoom = zoom;
+        mMinLineHeightForMagnifier = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, MIN_LINE_HEIGHT_FOR_MAGNIFIER,
+                mTextView.getContext().getResources().getDisplayMetrics());
+        mMaxLineHeightForMagnifier = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, MAX_LINE_HEIGHT_FOR_MAGNIFIER,
+                mTextView.getContext().getResources().getDisplayMetrics());
+
         final Layout layout = mTextView.getLayout();
         final int line = layout.getLineForOffset(mTextView.getSelectionStart());
         final int sourceHeight =
             layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
-        // Slightly increase the height to avoid tooLargeTextForMagnifier() returns true.
-        int height = (int)(sourceHeight * zoom) + 2;
-        int width = (int)(aspectRatio * height);
+        final int height = (int)(sourceHeight * zoom);
+        final int width = (int)(aspectRatio * Math.max(sourceHeight, mMinLineHeightForMagnifier));
 
         params.setFishEyeStyle()
                 .setSize(width, height)
@@ -4902,6 +4936,12 @@
         }
 
         private boolean tooLargeTextForMagnifier() {
+            if (mNewMagnifierEnabled) {
+                Layout layout = mTextView.getLayout();
+                final int line = layout.getLineForOffset(getCurrentCursorOffset());
+                return layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line)
+                        >= mMaxLineHeightForMagnifier;
+            }
             final float magnifierContentHeight = Math.round(
                     mMagnifierAnimator.mMagnifier.getHeight()
                             / mMagnifierAnimator.mMagnifier.getZoom());
@@ -5111,9 +5151,16 @@
                     int lineRight = (int) layout.getLineRight(line);
                     lineRight += mTextView.getTotalPaddingLeft() - mTextView.getScrollX();
                     mMagnifierAnimator.mMagnifier.setSourceHorizontalBounds(lineLeft, lineRight);
+                    final int lineHeight =
+                            layout.getLineBottomWithoutSpacing(line) - layout.getLineTop(line);
+                    float zoom = mInitialZoom;
+                    if (lineHeight < mMinLineHeightForMagnifier) {
+                        zoom = zoom * mMinLineHeightForMagnifier / lineHeight;
+                    }
+                    mMagnifierAnimator.mMagnifier.updateSourceFactors(lineHeight, zoom);
                     mMagnifierAnimator.mMagnifier.show(showPosInView.x, showPosInView.y);
                 } else {
-                  mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
+                    mMagnifierAnimator.show(showPosInView.x, showPosInView.y);
                 }
                 updateHandlesVisibility();
             } else {
@@ -5259,11 +5306,13 @@
 
             int deltaHeight = 0;
             int opacity = 255;
-            if (mCursorControlEnabled) {
+            if (mFlagInsertionHandleGesturesEnabled) {
                 deltaHeight = AppGlobals.getIntCoreSetting(
-                        WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, 25);
+                        WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT,
+                        WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT_DEFAULT);
                 opacity = AppGlobals.getIntCoreSetting(
-                        WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, 50);
+                        WidgetFlags.KEY_INSERTION_HANDLE_OPACITY,
+                        WidgetFlags.INSERTION_HANDLE_OPACITY_DEFAULT);
                 // Avoid invalid/unsupported values.
                 if (deltaHeight < -25 || deltaHeight > 50) {
                     deltaHeight = 25;
@@ -5329,7 +5378,7 @@
 
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            if (mCursorControlEnabled) {
+            if (mFlagInsertionHandleGesturesEnabled) {
                 final int height = Math.max(
                         getPreferredHeight() + mDeltaHeight, mDrawable.getIntrinsicHeight());
                 setMeasuredDimension(getPreferredWidth(), height);
@@ -5340,7 +5389,7 @@
 
         @Override
         public boolean onTouchEvent(MotionEvent ev) {
-            if (mCursorControlEnabled && FLAG_ENABLE_CURSOR_DRAG) {
+            if (mFlagInsertionHandleGesturesEnabled && mFlagCursorDragFromAnywhereEnabled) {
                 // Should only enable touch through when cursor drag is enabled.
                 // Otherwise the insertion handle view cannot be moved.
                 return touchThrough(ev);
@@ -6012,7 +6061,13 @@
     @VisibleForTesting
     public class InsertionPointCursorController implements CursorController {
         private InsertionHandleView mHandle;
+        // Tracks whether the cursor is currently being dragged.
         private boolean mIsDraggingCursor;
+        // During a drag, tracks whether the user's finger has adjusted to be over the handle rather
+        // than the cursor bar.
+        private boolean mIsTouchSnappedToHandleDuringDrag;
+        // During a drag, tracks the line of text where the cursor was last positioned.
+        private int mPrevLineDuringDrag;
 
         public void onTouchEvent(MotionEvent event) {
             if (hasSelectionController() && getSelectionController().isCursorBeingModified()) {
@@ -6025,7 +6080,7 @@
                     }
                     if (mIsDraggingCursor) {
                         performCursorDrag(event);
-                    } else if (FLAG_ENABLE_CURSOR_DRAG
+                    } else if (mFlagCursorDragFromAnywhereEnabled
                                 && mTextView.getLayout() != null
                                 && mTextView.isFocused()
                                 && mTouchState.isMovedEnoughForDrag()
@@ -6043,8 +6098,8 @@
         }
 
         private void positionCursorDuringDrag(MotionEvent event) {
-            int line = mTextView.getLineAtCoordinate(event.getY());
-            int offset = mTextView.getOffsetAtCoordinate(line, event.getX());
+            mPrevLineDuringDrag = getLineDuringDrag(event);
+            int offset = mTextView.getOffsetAtCoordinate(mPrevLineDuringDrag, event.getX());
             int oldSelectionStart = mTextView.getSelectionStart();
             int oldSelectionEnd = mTextView.getSelectionEnd();
             if (offset == oldSelectionStart && offset == oldSelectionEnd) {
@@ -6057,11 +6112,58 @@
             }
         }
 
+        /**
+         * Returns the line where the cursor should be positioned during a cursor drag. Rather than
+         * simply returning the line directly at the touch position, this function has the following
+         * additional logic:
+         * 1) Apply some slop to avoid switching lines if the touch moves just slightly off the
+         * current line.
+         * 2) Allow the user's finger to slide down and "snap" to the handle to provide better
+         * visibility of the cursor and text.
+         */
+        private int getLineDuringDrag(MotionEvent event) {
+            final Layout layout = mTextView.getLayout();
+            if (mTouchState.isOnHandle()) {
+                // The drag was initiated from the handle, so no need to apply the snap logic. See
+                // InsertionHandleView.touchThrough().
+                return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
+            }
+            if (mIsTouchSnappedToHandleDuringDrag) {
+                float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
+                return getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
+            }
+            int line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, event.getY());
+            if (mPrevLineDuringDrag == UNSET_LINE || line <= mPrevLineDuringDrag) {
+                // User's finger is on the same line or moving up; continue positioning the cursor
+                // directly at the touch location.
+                return line;
+            }
+            // User's finger is moving downwards; delay jumping to the lower line to allow the
+            // touch to move to the handle.
+            float cursorY = event.getY() - getHandle().getIdealVerticalOffset();
+            line = getCurrentLineAdjustedForSlop(layout, mPrevLineDuringDrag, cursorY);
+            if (line < mPrevLineDuringDrag) {
+                return mPrevLineDuringDrag;
+            }
+            // User's finger is now over the handle, at the ideal offset from the cursor. From now
+            // on, position the cursor higher up from the actual touch location so that the user's
+            // finger stays "snapped" to the handle. This provides better visibility of the text.
+            mIsTouchSnappedToHandleDuringDrag = true;
+            if (TextView.DEBUG_CURSOR) {
+                logCursor("InsertionPointCursorController",
+                        "snapped touch to handle: eventY=%d, cursorY=%d, mLastLine=%d, line=%d",
+                        (int) event.getY(), (int) cursorY, mPrevLineDuringDrag, line);
+            }
+            return line;
+        }
+
         private void startCursorDrag(MotionEvent event) {
             if (TextView.DEBUG_CURSOR) {
                 logCursor("InsertionPointCursorController", "start cursor drag");
             }
             mIsDraggingCursor = true;
+            mIsTouchSnappedToHandleDuringDrag = false;
+            mPrevLineDuringDrag = UNSET_LINE;
             // We don't want the parent scroll/long-press handlers to take over while dragging.
             mTextView.getParent().requestDisallowInterceptTouchEvent(true);
             mTextView.cancelLongPress();
@@ -6084,6 +6186,8 @@
                 logCursor("InsertionPointCursorController", "end cursor drag");
             }
             mIsDraggingCursor = false;
+            mIsTouchSnappedToHandleDuringDrag = false;
+            mPrevLineDuringDrag = UNSET_LINE;
             // Hide the magnifier and set the handle to be hidden after a delay.
             getHandle().dismissMagnifier();
             getHandle().hideAfterDelay();
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index a6a5ec5..a299b01 100644
--- a/core/java/android/widget/Magnifier.java
+++ b/core/java/android/widget/Magnifier.java
@@ -89,7 +89,7 @@
     // The width of the window containing the magnifier.
     private final int mWindowWidth;
     // The height of the window containing the magnifier.
-    private final int mWindowHeight;
+    private int mWindowHeight;
     // The zoom applied to the view region copied to the magnifier view.
     private float mZoom;
     // The width of the content that will be copied to the magnifier.
@@ -485,6 +485,21 @@
     }
 
     /**
+     * Updates the factors of source which may impact the magnifier's size.
+     * This can be called while the magnifier is showing and moving.
+     * @param sourceHeight the new source height.
+     * @param zoom the new zoom factor.
+     */
+    void updateSourceFactors(final int sourceHeight, final float zoom) {
+        mZoom = zoom;
+        mSourceHeight = sourceHeight;
+        mWindowHeight = (int) (sourceHeight * zoom);
+        if (mWindow != null) {
+            mWindow.updateContentFactors(mWindowHeight, zoom);
+        }
+    }
+
+    /**
      * Returns the zoom to be applied to the magnified view region copied to the magnifier.
      * If the zoom is x and the magnifier window size is (width, height), the original size
      * of the content being magnified will be (width / x, height / x).
@@ -904,7 +919,7 @@
         private final Display mDisplay;
         // The size of the content of the magnifier.
         private final int mContentWidth;
-        private final int mContentHeight;
+        private int mContentHeight;
         // The insets of the content inside the allocated surface.
         private final int mOffsetX;
         private final int mOffsetY;
@@ -947,7 +962,7 @@
         // The current content of the magnifier. It is mBitmap + mOverlay, only used for testing.
         private Bitmap mCurrentContent;
 
-        private final float mZoom;
+        private float mZoom;
         // The width of the ramp region in pixels on the left & right sides of the fish-eye effect.
         private final int mRamp;
         // Whether is in the new magnifier style.
@@ -1009,11 +1024,11 @@
 
             final RecordingCanvas canvas = mRenderer.getRootNode().beginRecording(width, height);
             try {
-                canvas.insertReorderBarrier();
+                canvas.enableZ();
                 canvas.drawRenderNode(mBitmapRenderNode);
-                canvas.insertInorderBarrier();
+                canvas.disableZ();
                 canvas.drawRenderNode(mOverlayRenderNode);
-                canvas.insertInorderBarrier();
+                canvas.disableZ();
             } finally {
                 mRenderer.getRootNode().endRecording();
             }
@@ -1034,15 +1049,66 @@
             }
         }
 
+        /**
+         * Updates the factors of content which may resize the window.
+         * @param contentHeight the new height of content.
+         * @param zoom the new zoom factor.
+         */
+        private void updateContentFactors(final int contentHeight, final float zoom) {
+            if (mContentHeight == contentHeight && mZoom == zoom) {
+              return;
+            }
+            if (mContentHeight < contentHeight) {
+                // Grows the surface height as necessary.
+                new SurfaceControl.Transaction().setBufferSize(
+                        mSurfaceControl, mContentWidth, contentHeight).apply();
+                mSurface.copyFrom(mSurfaceControl);
+                mRenderer.setSurface(mSurface);
+
+                final Outline outline = new Outline();
+                outline.setRoundRect(0, 0, mContentWidth, contentHeight, 0);
+                outline.setAlpha(1.0f);
+
+                mBitmapRenderNode.setLeftTopRightBottom(mOffsetX, mOffsetY,
+                        mOffsetX + mContentWidth, mOffsetY + contentHeight);
+                mBitmapRenderNode.setOutline(outline);
+
+                mOverlayRenderNode.setLeftTopRightBottom(mOffsetX, mOffsetY,
+                        mOffsetX + mContentWidth, mOffsetY + contentHeight);
+                mOverlayRenderNode.setOutline(outline);
+
+                final RecordingCanvas canvas =
+                        mRenderer.getRootNode().beginRecording(mContentWidth, contentHeight);
+                try {
+                    canvas.enableZ();
+                    canvas.drawRenderNode(mBitmapRenderNode);
+                    canvas.disableZ();
+                    canvas.drawRenderNode(mOverlayRenderNode);
+                    canvas.disableZ();
+                } finally {
+                    mRenderer.getRootNode().endRecording();
+                }
+            }
+            mContentHeight = contentHeight;
+            mZoom = zoom;
+            fillMeshMatrix();
+        }
+
         private void createMeshMatrixForFishEyeEffect() {
             mMeshWidth = 1;
             mMeshHeight = 6;
+            mMeshLeft = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
+            mMeshRight = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
+            fillMeshMatrix();
+        }
+
+        private void fillMeshMatrix() {
+            mMeshWidth = 1;
+            mMeshHeight = 6;
             final float w = mContentWidth;
             final float h = mContentHeight;
             final float h0 = h / mZoom;
             final float dh = h - h0;
-            mMeshLeft = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
-            mMeshRight = new float[2 * (mMeshWidth + 1) * (mMeshHeight + 1)];
             for (int i = 0; i < 2 * (mMeshWidth + 1) * (mMeshHeight + 1); i += 2) {
                 // Calculates X value.
                 final int colIndex = i % (2 * (mMeshWidth + 1)) / 2;
@@ -1197,6 +1263,7 @@
             if (mBitmap != null) {
                 mBitmap.recycle();
             }
+            mOverlay.setCallback(null);
         }
 
         private void doDraw() {
@@ -1257,7 +1324,8 @@
                             return;
                         }
                         // Show or move the window at the content draw frame.
-                        mTransaction.deferTransactionUntilSurface(mSurfaceControl, mSurface, frame);
+                        mTransaction.deferTransactionUntil(mSurfaceControl, mSurfaceControl,
+                                frame);
                         if (updateWindowPosition) {
                             mTransaction.setPosition(mSurfaceControl, pendingX, pendingY);
                         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 0182975..815cc5c 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import static android.Manifest.permission.INTERACT_ACROSS_USERS_FULL;
+import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_LENGTH;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX;
 import static android.view.accessibility.AccessibilityNodeInfo.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY;
@@ -727,6 +728,7 @@
     @UnsupportedAppUsage
     private Layout mLayout;
     private boolean mLocalesChanged = false;
+    private int mTextSizeUnit = -1;
 
     // True if setKeyListener() has been explicitly called
     private boolean mListenerChanged = false;
@@ -3842,6 +3844,7 @@
         ColorStateList mTextColorHint = null;
         ColorStateList mTextColorLink = null;
         int mTextSize = -1;
+        int mTextSizeUnit = -1;
         LocaleList mTextLocales = null;
         String mFontFamily = null;
         Typeface mFontTypeface = null;
@@ -3869,6 +3872,7 @@
                     + "    mTextColorHint:" + mTextColorHint + "\n"
                     + "    mTextColorLink:" + mTextColorLink + "\n"
                     + "    mTextSize:" + mTextSize + "\n"
+                    + "    mTextSizeUnit:" + mTextSizeUnit + "\n"
                     + "    mTextLocales:" + mTextLocales + "\n"
                     + "    mFontFamily:" + mFontFamily + "\n"
                     + "    mFontTypeface:" + mFontTypeface + "\n"
@@ -3980,6 +3984,7 @@
                 case com.android.internal.R.styleable.TextAppearance_textSize:
                     attributes.mTextSize =
                             appearance.getDimensionPixelSize(attr, attributes.mTextSize);
+                    attributes.mTextSizeUnit = appearance.peekValue(attr).getComplexUnit();
                     break;
                 case com.android.internal.R.styleable.TextAppearance_textLocale:
                     final String localeString = appearance.getString(attr);
@@ -4073,6 +4078,7 @@
         }
 
         if (attributes.mTextSize != -1) {
+            mTextSizeUnit = attributes.mTextSizeUnit;
             setRawTextSize(attributes.mTextSize, true /* shouldRequestLayout */);
         }
 
@@ -4295,6 +4301,7 @@
             r = c.getResources();
         }
 
+        mTextSizeUnit = unit;
         setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),
                 shouldRequestLayout);
     }
@@ -4315,6 +4322,17 @@
     }
 
     /**
+     * Gets the text size unit defined by the developer. It may be specified in resources or be
+     * passed as the unit argument of {@link #setTextSize(int, float)} at runtime.
+     *
+     * @return the dimension type of the text size unit originally defined.
+     * @see TypedValue#TYPE_DIMENSION
+     */
+    public int getTextSizeUnit() {
+        return mTextSizeUnit;
+    }
+
+    /**
      * Gets the extent by which text should be stretched horizontally.
      * This will usually be 1.0.
      * @return The horizontal scale factor.
@@ -11769,8 +11787,14 @@
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH
                     | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PAGE);
             info.addAction(AccessibilityNodeInfo.ACTION_SET_SELECTION);
-            info.setAvailableExtraData(
-                    Arrays.asList(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY));
+            info.setAvailableExtraData(Arrays.asList(
+                    EXTRA_DATA_RENDERING_INFO_KEY,
+                    EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY
+            ));
+        } else {
+            info.setAvailableExtraData(Arrays.asList(
+                    EXTRA_DATA_RENDERING_INFO_KEY
+            ));
         }
 
         if (isFocused()) {
@@ -11824,11 +11848,7 @@
     @Override
     public void addExtraDataToAccessibilityNodeInfo(
             AccessibilityNodeInfo info, String extraDataKey, Bundle arguments) {
-        // The only extra data we support requires arguments.
-        if (arguments == null) {
-            return;
-        }
-        if (extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) {
+        if (arguments != null && extraDataKey.equals(EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY)) {
             int positionInfoStartIndex = arguments.getInt(
                     EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX, -1);
             int positionInfoLength = arguments.getInt(
@@ -11856,6 +11876,15 @@
                 }
             }
             info.getExtras().putParcelableArray(extraDataKey, boundingRects);
+            return;
+        }
+        if (extraDataKey.equals(AccessibilityNodeInfo.EXTRA_DATA_RENDERING_INFO_KEY)) {
+            final AccessibilityNodeInfo.ExtraRenderingInfo extraRenderingInfo =
+                    AccessibilityNodeInfo.ExtraRenderingInfo.obtain();
+            extraRenderingInfo.setLayoutParams(getLayoutParams().width, getLayoutParams().height);
+            extraRenderingInfo.setTextSizeInPx(getTextSize());
+            extraRenderingInfo.setTextSizeUnit(getTextSizeUnit());
+            info.setExtraRenderingInfo(extraRenderingInfo);
         }
     }
 
diff --git a/core/java/android/widget/WidgetFlags.java b/core/java/android/widget/WidgetFlags.java
index 1a8e7a7..bce5497 100644
--- a/core/java/android/widget/WidgetFlags.java
+++ b/core/java/android/widget/WidgetFlags.java
@@ -17,27 +17,49 @@
 package android.widget;
 
 /**
- * Keeps the flags related to the Widget namespace in {@link DeviceConfig}.
+ * Flags in the {@link android.provider.DeviceConfig#NAMESPACE_WIDGET "widget" namespace}.
  *
  * @hide
  */
 public final class WidgetFlags {
 
     /**
-     * Whether the cursor control feature set is enabled.
-     * TODO: Makes this flag key visible to webview/chrome.
+     * Whether starting a cursor drag from anywhere in the text should be enabled.
      */
-    public static final String ENABLE_CURSOR_CONTROL =
-            "CursorControlFeature__enable_cursor_control";
+    public static final String ENABLE_CURSOR_DRAG_FROM_ANYWHERE =
+            "CursorControlFeature__enable_cursor_drag_from_anywhere";
 
     /**
-     * The key name used in app core settings for enable cursor control.
+     * The key used in app core settings for the flag {@link #ENABLE_CURSOR_DRAG_FROM_ANYWHERE}.
      */
-    public static final String KEY_ENABLE_CURSOR_CONTROL = "widget__enable_cursor_control";
+    public static final String KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE =
+            "widget__enable_cursor_drag_from_anywhere";
+
+    /**
+     * Default value for the flag {@link #ENABLE_CURSOR_DRAG_FROM_ANYWHERE}.
+     */
+    public static final boolean ENABLE_CURSOR_DRAG_FROM_ANYWHERE_DEFAULT = true;
+
+    /**
+     * Whether additional gestures should be enabled for the insertion cursor handle (e.g.
+     * long-press or double-tap on the handle to trigger selection).
+     */
+    public static final String ENABLE_INSERTION_HANDLE_GESTURES =
+            "CursorControlFeature__enable_insertion_handle_gestures";
+
+    /**
+     * The key used in app core settings for the flag {@link #ENABLE_INSERTION_HANDLE_GESTURES}.
+     */
+    public static final String KEY_ENABLE_INSERTION_HANDLE_GESTURES =
+            "widget__enable_insertion_handle_gestures";
+
+    /**
+     * Default value for the flag {@link #ENABLE_INSERTION_HANDLE_GESTURES}.
+     */
+    public static final boolean ENABLE_INSERTION_HANDLE_GESTURES_DEFAULT = false;
 
     /**
      * The flag of delta height applies to the insertion handle when cursor control flag is enabled.
-     * The default value is 25.
      */
     public static final String INSERTION_HANDLE_DELTA_HEIGHT =
             "CursorControlFeature__insertion_handle_delta_height";
@@ -49,8 +71,13 @@
             "widget__insertion_handle_delta_height";
 
     /**
+     * Default value for the flag {@link #INSERTION_HANDLE_DELTA_HEIGHT}.
+     */
+    public static final int INSERTION_HANDLE_DELTA_HEIGHT_DEFAULT = 25;
+
+    /**
      * The flag of opacity applies to the insertion handle when cursor control flag is enabled.
-     * The opacity value is in the range of {0..100}. The default value is 50.
+     * The opacity value is in the range of {0..100}.
      */
     public static final String INSERTION_HANDLE_OPACITY =
             "CursorControlFeature__insertion_handle_opacity";
@@ -62,6 +89,11 @@
             "widget__insertion_handle_opacity";
 
     /**
+     * Default value for the flag {@link #INSERTION_HANDLE_OPACITY}.
+     */
+    public static final int INSERTION_HANDLE_OPACITY_DEFAULT = 50;
+
+    /**
      * The flag of enabling the new magnifier.
      */
     public static final String ENABLE_NEW_MAGNIFIER = "CursorControlFeature__enable_new_magnifier";
@@ -72,8 +104,12 @@
     public static final String KEY_ENABLE_NEW_MAGNIFIER = "widget__enable_new_magnifier";
 
     /**
+     * Default value for the flag {@link #ENABLE_NEW_MAGNIFIER}.
+     */
+    public static final boolean ENABLE_NEW_MAGNIFIER_DEFAULT = false;
+
+    /**
      * The flag of zoom factor applies to the new magnifier.
-     * The default value is 1.5f.
      */
     public static final String MAGNIFIER_ZOOM_FACTOR =
             "CursorControlFeature__magnifier_zoom_factor";
@@ -84,8 +120,12 @@
     public static final String KEY_MAGNIFIER_ZOOM_FACTOR = "widget__magnifier_zoom_factor";
 
     /**
+     * Default value for the flag {@link #MAGNIFIER_ZOOM_FACTOR}.
+     */
+    public static final float MAGNIFIER_ZOOM_FACTOR_DEFAULT = 1.5f;
+
+    /**
      * The flag of aspect ratio (width/height) applies to the new magnifier.
-     * The default value is 5.5f.
      */
     public static final String MAGNIFIER_ASPECT_RATIO =
             "CursorControlFeature__magnifier_aspect_ratio";
@@ -95,6 +135,11 @@
      */
     public static final String KEY_MAGNIFIER_ASPECT_RATIO = "widget__magnifier_aspect_ratio";
 
+    /**
+     * Default value for the flag {@link #MAGNIFIER_ASPECT_RATIO}.
+     */
+    public static final float MAGNIFIER_ASPECT_RATIO_DEFAULT = 5.5f;
+
     private WidgetFlags() {
     }
 }
diff --git a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
index e8f84aa..b4a0208 100644
--- a/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/AbstractMultiProfilePagerAdapter.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.annotation.StringRes;
 import android.app.AppGlobals;
+import android.app.admin.DevicePolicyEventLogger;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -27,6 +28,7 @@
 import android.content.pm.ResolveInfo;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.stats.devicepolicy.DevicePolicyEnums;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.Button;
@@ -251,6 +253,8 @@
 
     abstract @Nullable ViewGroup getInactiveAdapterView();
 
+    abstract String getMetricsCategory();
+
     /**
      * Rebuilds the tab that is currently visible to the user.
      * <p>Returns {@code true} if rebuild has completed.
@@ -282,6 +286,10 @@
         UserHandle listUserHandle = activeListAdapter.getUserHandle();
         if (listUserHandle == mWorkProfileUserHandle
                 && mInjector.isQuietModeEnabled(mWorkProfileUserHandle)) {
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED)
+                    .setStrings(getMetricsCategory())
+                    .write();
             showEmptyState(activeListAdapter,
                     R.drawable.ic_work_apps_off,
                     R.string.resolver_turn_on_work_apps,
@@ -294,11 +302,19 @@
             if (!mInjector.hasCrossProfileIntents(activeListAdapter.getIntents(),
                     UserHandle.myUserId(), listUserHandle.getIdentifier())) {
                 if (listUserHandle == mPersonalProfileUserHandle) {
+                    DevicePolicyEventLogger.createEvent(
+                                DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL)
+                            .setStrings(getMetricsCategory())
+                            .write();
                     showEmptyState(activeListAdapter,
                             R.drawable.ic_sharing_disabled,
                             R.string.resolver_cant_share_with_personal_apps,
                             R.string.resolver_cant_share_cross_profile_explanation);
                 } else {
+                    DevicePolicyEventLogger.createEvent(
+                            DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK)
+                            .setStrings(getMetricsCategory())
+                            .write();
                     showEmptyState(activeListAdapter,
                             R.drawable.ic_sharing_disabled,
                             R.string.resolver_cant_share_with_work_apps,
@@ -315,6 +331,12 @@
         UserHandle listUserHandle = listAdapter.getUserHandle();
         if (UserHandle.myUserId() == listUserHandle.getIdentifier()
                 || !hasAppsInOtherProfile(listAdapter)) {
+            if (mWorkProfileUserHandle != null) {
+                DevicePolicyEventLogger.createEvent(
+                        DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_APPS_RESOLVED)
+                        .setStrings(getMetricsCategory())
+                        .write();
+            }
             showEmptyState(listAdapter,
                     R.drawable.ic_no_apps,
                     R.string.resolver_no_apps_available,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index dc801a9..250b1ea 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -373,7 +373,7 @@
                 Log.i(TAG, "Hiding image preview area. Timed out waiting for preview to load"
                         + " within " + mImageLoadTimeoutMillis + "ms.");
                 collapseParentView();
-                if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+                if (shouldShowTabs()) {
                     hideStickyContentPreview();
                 } else if (mChooserMultiProfilePagerAdapter.getCurrentRootAdapter() != null) {
                     mChooserMultiProfilePagerAdapter.getCurrentRootAdapter().hideContentPreview();
@@ -773,7 +773,7 @@
             Intent[] initialIntents,
             List<ResolveInfo> rList,
             boolean filterLastUsed) {
-        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+        if (shouldShowTabs()) {
             mChooserMultiProfilePagerAdapter = createChooserMultiProfilePagerAdapterForTwoProfiles(
                     initialIntents, rList, filterLastUsed);
         } else {
@@ -1805,6 +1805,10 @@
             if (!TextUtils.isEmpty(dataString)) {
                 return new IntentFilter(intent.getAction(), dataString);
             }
+            if (intent.getType() == null) {
+                Log.e(TAG, "Failed to get target intent filter: intent data and type are null");
+                return null;
+            }
             IntentFilter intentFilter = new IntentFilter(intent.getAction(), intent.getType());
             List<Uri> contentUris = new ArrayList<>();
             if (Intent.ACTION_SEND.equals(intent.getAction())) {
@@ -1825,7 +1829,7 @@
             }
             return intentFilter;
         } catch (Exception e) {
-            Log.e(TAG, "failed to get target intent filter", e);
+            Log.e(TAG, "Failed to get target intent filter", e);
             return null;
         }
     }
@@ -2434,7 +2438,7 @@
                     offset += findViewById(R.id.content_preview_container).getHeight();
                 }
 
-                if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+                if (shouldShowTabs()) {
                     offset += findViewById(R.id.tabs).getHeight();
                 }
 
@@ -2562,7 +2566,7 @@
     }
 
     private void setupScrollListener() {
-        if (mResolverDrawerLayout == null || (hasWorkProfile() && ENABLE_TABBED_VIEW)) {
+        if (mResolverDrawerLayout == null || shouldShowTabs()) {
             return;
         }
         final View chooserHeader = mResolverDrawerLayout.findViewById(R.id.chooser_header);
@@ -2613,8 +2617,7 @@
      * we instead show the content preview as a regular list item.
      */
     private boolean shouldShowStickyContentPreview() {
-        return hasWorkProfile()
-                && ENABLE_TABBED_VIEW
+        return shouldShowTabs()
                 && mMultiProfilePagerAdapter.getListAdapterForUserHandle(
                         UserHandle.of(UserHandle.myUserId())).getCount() > 0
                 && isSendAction(getTargetIntent())
@@ -2699,6 +2702,11 @@
     @Override
     protected void resetButtonBar() {}
 
+    @Override
+    protected String getMetricsCategory() {
+        return METRICS_CATEGORY_CHOOSER;
+    }
+
     /**
      * Adapter for all types of items and targets in ShareSheet.
      * Note that ranked sections like Direct Share - while appearing grid-like - are handled on the
@@ -2824,7 +2832,7 @@
         public int getContentPreviewRowCount() {
             // For the tabbed case we show the sticky content preview above the tabs,
             // please refer to shouldShowStickyContentPreview
-            if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            if (shouldShowTabs()) {
                 return 0;
             }
             if (!isSendAction(getTargetIntent())) {
@@ -2840,7 +2848,7 @@
         }
 
         public int getProfileRowCount() {
-            if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            if (shouldShowTabs()) {
                 return 0;
             }
             return mChooserListAdapter.getOtherProfile() == null ? 0 : 1;
@@ -3096,7 +3104,7 @@
             final ViewGroup viewGroup = (ViewGroup) holder.itemView;
             int start = getListPosition(position);
             int startType = getRowType(start);
-            if (viewGroup.getForeground() == null) {
+            if (viewGroup.getForeground() == null && position > 0) {
                 viewGroup.setForeground(
                         getResources().getDrawable(R.drawable.chooser_row_layer_list, null));
             }
diff --git a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
index e350142..d440402 100644
--- a/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ChooserMultiProfilePagerAdapter.java
@@ -165,6 +165,11 @@
         return getListViewForIndex(1 - getCurrentPage());
     }
 
+    @Override
+    String getMetricsCategory() {
+        return ResolverActivity.METRICS_CATEGORY_CHOOSER;
+    }
+
     class ChooserProfileDescriptor extends ProfileDescriptor {
         private ChooserActivity.ChooserGridAdapter chooserGridAdapter;
         private RecyclerView recyclerView;
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 2f1a15f..dc6942c 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -133,7 +133,7 @@
     void noteNetworkStatsEnabled();
     void noteDeviceIdleMode(int mode, String activeReason, int activeUid);
     void setBatteryState(int status, int health, int plugType, int level, int temp, int volt,
-            int chargeUAh, int chargeFullUAh);
+            int chargeUAh, int chargeFullUAh, long chargeTimeToFullSeconds);
     @UnsupportedAppUsage
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 5dc8b0b..96bfe73 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -33,6 +33,7 @@
 import android.app.VoiceInteractor.PickOptionRequest;
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.app.VoiceInteractor.Prompt;
+import android.app.admin.DevicePolicyEventLogger;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
@@ -60,6 +61,7 @@
 import android.os.UserManager;
 import android.provider.MediaStore;
 import android.provider.Settings;
+import android.stats.devicepolicy.DevicePolicyEnums;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Slog;
@@ -84,6 +86,7 @@
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.AbstractMultiProfilePagerAdapter.Profile;
+import com.android.internal.app.chooser.ChooserTargetInfo;
 import com.android.internal.app.chooser.DisplayResolveInfo;
 import com.android.internal.app.chooser.TargetInfo;
 import com.android.internal.content.PackageMonitor;
@@ -99,6 +102,7 @@
 import java.util.Objects;
 import java.util.Set;
 
+
 /**
  * This activity is displayed when the system attempts to start an Intent for
  * which there is more than one matching activity, allowing the user to decide
@@ -152,6 +156,8 @@
     private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
     private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
     private static final String OPEN_LINKS_COMPONENT_KEY = "app_link_state";
+    protected static final String METRICS_CATEGORY_RESOLVER = "intent_resolver";
+    protected static final String METRICS_CATEGORY_CHOOSER = "intent_chooser";
 
     /**
      * TODO(arangelov): Remove a couple of weeks after work/personal tabs are finalized.
@@ -362,7 +368,7 @@
                 mMultiProfilePagerAdapter.getPersonalListAdapter());
         mPersonalPackageMonitor.register(
                 this, getMainLooper(), getPersonalProfileUserHandle(), false);
-        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+        if (shouldShowTabs()) {
             mWorkPackageMonitor = createPackageMonitor(
                     mMultiProfilePagerAdapter.getWorkListAdapter());
             mWorkPackageMonitor.register(this, getMainLooper(), getWorkProfileUserHandle(), false);
@@ -390,7 +396,7 @@
                     | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
             rdl.setOnApplyWindowInsetsListener(this::onApplyWindowInsets);
 
-            if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            if (shouldShowTabs()) {
                 rdl.setMaxCollapsedHeight(getResources().getDimensionPixelSize(
                         R.dimen.resolver_empty_state_height_with_tabs));
                 findViewById(R.id.profile_pager).setMinimumHeight(
@@ -419,7 +425,7 @@
             List<ResolveInfo> rList,
             boolean filterLastUsed) {
         AbstractMultiProfilePagerAdapter resolverMultiProfilePagerAdapter = null;
-        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+        if (shouldShowTabs()) {
             resolverMultiProfilePagerAdapter =
                     createResolverMultiProfilePagerAdapterForTwoProfiles(
                             initialIntents, rList, filterLastUsed);
@@ -500,10 +506,14 @@
         return null;
     }
 
-    protected boolean hasWorkProfile() {
+    private boolean hasWorkProfile() {
         return getWorkProfileUserHandle() != null;
     }
 
+    protected boolean shouldShowTabs() {
+        return hasWorkProfile() && ENABLE_TABBED_VIEW;
+    }
+
     protected void onProfileClick(View v) {
         final DisplayResolveInfo dri =
                 mMultiProfilePagerAdapter.getActiveListAdapter().getOtherProfile();
@@ -728,7 +738,7 @@
         if (!mRegistered) {
             mPersonalPackageMonitor.register(this, getMainLooper(),
                     getPersonalProfileUserHandle(), false);
-            if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            if (shouldShowTabs()) {
                 if (mWorkPackageMonitor == null) {
                     mWorkPackageMonitor = createPackageMonitor(
                             mMultiProfilePagerAdapter.getWorkListAdapter());
@@ -745,7 +755,7 @@
     @Override
     protected void onStart() {
         super.onStart();
-        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+        if (shouldShowTabs()) {
             mWorkProfileStateReceiver = createWorkProfileStateReceiver();
             registerWorkProfileStateReceiver();
         }
@@ -1197,12 +1207,14 @@
         if (!mSafeForwardingMode) {
             if (cti.startAsUser(this, null, currentUserHandle)) {
                 onActivityStarted(cti);
+                maybeLogCrossProfileTargetLaunch(cti, currentUserHandle);
             }
             return;
         }
         try {
             if (cti.startAsCaller(this, null, currentUserHandle.getIdentifier())) {
                 onActivityStarted(cti);
+                maybeLogCrossProfileTargetLaunch(cti, currentUserHandle);
             }
         } catch (RuntimeException e) {
             String launchedFromPackage;
@@ -1218,6 +1230,18 @@
         }
     }
 
+    private void maybeLogCrossProfileTargetLaunch(TargetInfo cti, UserHandle currentUserHandle) {
+        if (!hasWorkProfile() || currentUserHandle == getUser()) {
+            return;
+        }
+        DevicePolicyEventLogger
+                .createEvent(DevicePolicyEnums.RESOLVER_CROSS_PROFILE_TARGET_OPENED)
+                .setBoolean(currentUserHandle == getPersonalProfileUserHandle())
+                .setStrings(getMetricsCategory(),
+                        cti instanceof ChooserTargetInfo ? "direct_share" : "other_target")
+                .write();
+    }
+
 
     public boolean startAsCallerImpl(Intent intent, Bundle options, boolean ignoreTargetSecurity,
             int userId) {
@@ -1304,8 +1328,11 @@
                     + "cannot be null.");
         }
         // We partially rebuild the inactive adapter to determine if we should auto launch
-        boolean rebuildActiveCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true);
-        boolean rebuildInactiveCompleted = mMultiProfilePagerAdapter.rebuildInactiveTab(false);
+        boolean rebuildCompleted = mMultiProfilePagerAdapter.rebuildActiveTab(true);
+        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+            boolean rebuildInactiveCompleted = mMultiProfilePagerAdapter.rebuildInactiveTab(false);
+            rebuildCompleted = rebuildCompleted && rebuildInactiveCompleted;
+        }
 
         if (useLayoutWithDefault()) {
             mLayoutId = R.layout.resolver_list_with_default;
@@ -1314,7 +1341,7 @@
         }
         setContentView(mLayoutId);
         mMultiProfilePagerAdapter.setupViewPager(findViewById(R.id.profile_pager));
-        return postRebuildList(rebuildActiveCompleted && rebuildInactiveCompleted);
+        return postRebuildList(rebuildCompleted);
     }
 
     /**
@@ -1343,7 +1370,7 @@
 
         setupViewVisibilities();
 
-        if (hasWorkProfile() && ENABLE_TABBED_VIEW) {
+        if (shouldShowTabs()) {
             setupProfileTabs();
         }
 
@@ -1378,6 +1405,10 @@
             return false;
         }
 
+        if (mMultiProfilePagerAdapter.getActiveListAdapter().getOtherProfile() != null) {
+            return false;
+        }
+
         // Only one target, so we're a candidate to auto-launch!
         final TargetInfo target = mMultiProfilePagerAdapter.getActiveListAdapter()
                 .targetInfoForPosition(0, false);
@@ -1414,7 +1445,8 @@
      * - The target app has declared it supports cross-profile communication via manifest metadata
      */
     private boolean maybeAutolaunchIfCrossProfileSupported() {
-        int count = mMultiProfilePagerAdapter.getActiveListAdapter().getUnfilteredCount();
+        ResolverListAdapter activeListAdapter = mMultiProfilePagerAdapter.getActiveListAdapter();
+        int count = activeListAdapter.getUnfilteredCount();
         if (count != 1) {
             return false;
         }
@@ -1423,7 +1455,7 @@
         if (inactiveListAdapter.getUnfilteredCount() != 1) {
             return false;
         }
-        TargetInfo activeProfileTarget = mMultiProfilePagerAdapter.getActiveListAdapter()
+        TargetInfo activeProfileTarget = activeListAdapter
                 .targetInfoForPosition(0, false);
         TargetInfo inactiveProfileTarget = inactiveListAdapter.targetInfoForPosition(0, false);
         if (!Objects.equals(activeProfileTarget.getResolvedComponentName(),
@@ -1438,6 +1470,11 @@
             return false;
         }
 
+        DevicePolicyEventLogger
+                .createEvent(DevicePolicyEnums.RESOLVER_AUTOLAUNCH_CROSS_PROFILE_TARGET)
+                .setBoolean(activeListAdapter.getUserHandle() == getPersonalProfileUserHandle())
+                .setStrings(getMetricsCategory())
+                .write();
         safelyStartActivity(activeProfileTarget);
         finish();
         return true;
@@ -1519,11 +1556,17 @@
                 viewPager.setCurrentItem(1);
             }
             setupViewVisibilities();
+            DevicePolicyEventLogger
+                    .createEvent(DevicePolicyEnums.RESOLVER_SWITCH_TABS)
+                    .setInt(viewPager.getCurrentItem())
+                    .setStrings(getMetricsCategory())
+                    .write();
         });
 
         viewPager.setVisibility(View.VISIBLE);
         tabHost.setCurrentTab(mMultiProfilePagerAdapter.getCurrentPage());
         mMultiProfilePagerAdapter.setOnProfileSelectedListener(tabHost::setCurrentTab);
+        findViewById(R.id.resolver_tab_divider).setVisibility(View.VISIBLE);
     }
 
     private void resetTabsHeaderStyle(TabWidget tabWidget) {
@@ -1562,7 +1605,7 @@
             stub.setVisibility(View.VISIBLE);
             TextView textView = (TextView) LayoutInflater.from(this).inflate(
                     R.layout.resolver_different_item_header, null, false);
-            if (ENABLE_TABBED_VIEW) {
+            if (shouldShowTabs()) {
                 textView.setGravity(Gravity.CENTER);
             }
             stub.addView(textView);
@@ -1686,6 +1729,10 @@
                 && Objects.equals(lhs.activityInfo.packageName, rhs.activityInfo.packageName);
     }
 
+    protected String getMetricsCategory() {
+        return METRICS_CATEGORY_RESOLVER;
+    }
+
     @Override // ResolverListCommunicator
     public void onHandlePackagesChanged(ResolverListAdapter listAdapter) {
         if (listAdapter == mMultiProfilePagerAdapter.getActiveListAdapter()) {
diff --git a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
index 96dc83a..21e7fd9 100644
--- a/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
+++ b/core/java/com/android/internal/app/ResolverMultiProfilePagerAdapter.java
@@ -150,6 +150,11 @@
         return getListViewForIndex(1 - getCurrentPage());
     }
 
+    @Override
+    String getMetricsCategory() {
+        return ResolverActivity.METRICS_CATEGORY_RESOLVER;
+    }
+
     class ResolverProfileDescriptor extends ProfileDescriptor {
         private ResolverListAdapter resolverListAdapter;
         final ListView listView;
diff --git a/core/java/com/android/internal/app/ResolverViewPager.java b/core/java/com/android/internal/app/ResolverViewPager.java
index 84fed9c..8239018 100644
--- a/core/java/com/android/internal/app/ResolverViewPager.java
+++ b/core/java/com/android/internal/app/ResolverViewPager.java
@@ -24,10 +24,10 @@
 import com.android.internal.widget.ViewPager;
 
 /**
- * A {@link ViewPager} which wraps around its first child's height and has swiping disabled.
+ * A {@link ViewPager} which wraps around its first child's height.
  * <p>Normally {@link ViewPager} instances expand their height to cover all remaining space in
  * the layout.
- * <p>This class is used for the intent resolver and share sheet's tabbed view.
+ * <p>This class is used for the intent resolver's tabbed view.
  */
 public class ResolverViewPager extends ViewPager {
 
@@ -70,14 +70,4 @@
         heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        return false;
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        return false;
-    }
 }
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 0ccc45e..04bf915 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -31,7 +31,6 @@
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Build;
 import android.os.IBinder;
 import android.os.SELinux;
@@ -95,20 +94,12 @@
             }
         }
 
-        public static Handle create(AndroidPackage pkg) throws IOException {
-            return create(
-                    pkg.makeListAllCodePaths(),
-                    (pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) != 0,
-                    (pkg.getFlags() & ApplicationInfo.FLAG_EXTRACT_NATIVE_LIBS) != 0,
-                    (pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
-        }
-
         public static Handle create(PackageLite lite) throws IOException {
             return create(lite.getAllCodePaths(), lite.multiArch, lite.extractNativeLibs,
                     lite.debuggable);
         }
 
-        private static Handle create(List<String> codePaths, boolean multiArch,
+        public static Handle create(List<String> codePaths, boolean multiArch,
                 boolean extractNativeLibs, boolean debuggable) throws IOException {
             final int size = codePaths.size();
             final String[] apkPaths = new String[size];
diff --git a/core/java/com/android/internal/content/om/OverlayConfig.java b/core/java/com/android/internal/content/om/OverlayConfig.java
new file mode 100644
index 0000000..72f16e4
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -0,0 +1,401 @@
+/*
+ * 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.internal.content.om;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackagePartitions;
+import android.content.pm.parsing.ParsingPackageRead;
+import android.os.Build;
+import android.os.Process;
+import android.os.Trace;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.om.OverlayConfigParser.OverlayPartition;
+import com.android.internal.content.om.OverlayConfigParser.ParsedConfiguration;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+import com.android.internal.util.Preconditions;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+/**
+ * Responsible for reading overlay configuration files and handling queries of overlay mutability,
+ * default-enabled state, and priority.
+ *
+ * @see OverlayConfigParser
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class OverlayConfig {
+    static final String TAG = "OverlayConfig";
+
+    // The default priority of an overlay that has not been configured. Overlays with default
+    // priority have a higher precedence than configured overlays.
+    @VisibleForTesting
+    public static final int DEFAULT_PRIORITY = Integer.MAX_VALUE;
+
+    @VisibleForTesting
+    public static final class Configuration {
+        @Nullable
+        public final ParsedConfiguration parsedConfig;
+
+        public final int configIndex;
+
+        public Configuration(@Nullable ParsedConfiguration parsedConfig, int configIndex) {
+            this.parsedConfig = parsedConfig;
+            this.configIndex = configIndex;
+        }
+    }
+
+    /**
+     * Interface for providing information on scanned packages.
+     * TODO(147840005): Remove this when android:isStatic and android:priority are fully deprecated
+     */
+    public interface PackageProvider {
+
+        /** Performs the given action for each package. */
+        void forEachPackage(BiConsumer<ParsingPackageRead, Boolean> p);
+    }
+
+    private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
+        final ParsedOverlayInfo o1 = c1.parsedInfo;
+        final ParsedOverlayInfo o2 = c2.parsedInfo;
+        Preconditions.checkArgument(o1.isStatic && o2.isStatic,
+                "attempted to sort non-static overlay");
+
+        if (!o1.targetPackageName.equals(o2.targetPackageName)) {
+            return o1.targetPackageName.compareTo(o2.targetPackageName);
+        }
+
+        final int comparedPriority = o1.priority - o2.priority;
+        return comparedPriority == 0 ? o1.path.compareTo(o2.path) : comparedPriority;
+    };
+
+    // Map of overlay package name to configured overlay settings
+    private final ArrayMap<String, Configuration> mConfigurations = new ArrayMap<>();
+
+    // Singleton instance only assigned in system server
+    private static OverlayConfig sInstance;
+
+    @VisibleForTesting
+    public OverlayConfig(@Nullable File rootDirectory,
+            @Nullable Supplier<OverlayScanner> scannerFactory,
+            @Nullable PackageProvider packageProvider) {
+        Preconditions.checkArgument((scannerFactory == null) != (packageProvider == null),
+                "scannerFactory and packageProvider cannot be both null or both non-null");
+
+        final ArrayList<OverlayPartition> partitions;
+        if (rootDirectory == null) {
+            partitions = new ArrayList<>(
+                    PackagePartitions.getOrderedPartitions(OverlayPartition::new));
+        } else {
+            // Rebase the system partitions and settings file on the specified root directory.
+            partitions = new ArrayList<>(PackagePartitions.getOrderedPartitions(
+                    p -> new OverlayPartition(new File(rootDirectory, p.folder.getPath()), p)));
+        }
+
+        boolean foundConfigFile = false;
+        ArrayList<ParsedOverlayInfo> packageManagerOverlayInfos = null;
+
+        final ArrayList<ParsedConfiguration> overlays = new ArrayList<>();
+        for (int i = 0, n = partitions.size(); i < n; i++) {
+            final OverlayPartition partition = partitions.get(i);
+            final OverlayScanner scanner = (scannerFactory == null) ? null : scannerFactory.get();
+            final ArrayList<ParsedConfiguration> partitionOverlays =
+                    OverlayConfigParser.getConfigurations(partition, scanner);
+            if (partitionOverlays != null) {
+                foundConfigFile = true;
+                overlays.addAll(partitionOverlays);
+                continue;
+            }
+
+            // If the configuration file is not present, then use android:isStatic and
+            // android:priority to configure the overlays in the partition.
+            // TODO(147840005): Remove converting static overlays to immutable, default-enabled
+            //  overlays when android:siStatic and android:priority are fully deprecated.
+            final ArrayList<ParsedOverlayInfo> partitionOverlayInfos;
+            if (scannerFactory != null) {
+                partitionOverlayInfos = new ArrayList<>(scanner.getAllParsedInfos());
+            } else {
+                if (packageManagerOverlayInfos == null) {
+                    packageManagerOverlayInfos = getOverlayPackageInfos(packageProvider);
+                }
+
+                // Filter out overlays not present in the partition.
+                partitionOverlayInfos = new ArrayList<>(packageManagerOverlayInfos);
+                for (int j = partitionOverlayInfos.size() - 1; j >= 0; j--) {
+                    if (!partition.containsPath(partitionOverlayInfos.get(j).path.getPath())) {
+                        partitionOverlayInfos.remove(j);
+                    }
+                }
+            }
+
+            // Static overlays are configured as immutable, default-enabled overlays.
+            final ArrayList<ParsedConfiguration> partitionConfigs = new ArrayList<>();
+            for (int j = 0, m = partitionOverlayInfos.size(); j < m; j++) {
+                final ParsedOverlayInfo p = partitionOverlayInfos.get(j);
+                if (p.isStatic) {
+                    partitionConfigs.add(new ParsedConfiguration(p.packageName,
+                            true /* enabled */, false /* mutable */, partition.policy, p));
+                }
+            }
+
+            partitionConfigs.sort(sStaticOverlayComparator);
+            overlays.addAll(partitionConfigs);
+        }
+
+        if (!foundConfigFile) {
+            // If no overlay configuration files exist, disregard partition precedence and allow
+            // android:priority to reorder overlays across partition boundaries.
+            overlays.sort(sStaticOverlayComparator);
+        }
+
+        for (int i = 0, n = overlays.size(); i < n; i++) {
+            // Add the configurations to a map so definitions of an overlay in an earlier
+            // partition can be replaced by an overlay with the same package name in a later
+            // partition.
+            final ParsedConfiguration config = overlays.get(i);
+            mConfigurations.put(config.packageName, new Configuration(config, i));
+        }
+    }
+
+    /**
+     * Creates an instance of OverlayConfig for use in the zygote process.
+     * This instance will not include information of static overlays existing outside of a partition
+     * overlay directory.
+     */
+    @NonNull
+    public static OverlayConfig getZygoteInstance() {
+        Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#getZygoteInstance");
+        try {
+            return new OverlayConfig(null /* rootDirectory */, OverlayScanner::new,
+                    null /* packageProvider */);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_RRO);
+        }
+    }
+
+    /**
+     * Initializes a singleton instance for use in the system process.
+     * Can only be called once. This instance is cached so future invocations of
+     * {@link #getSystemInstance()} will return the initialized instance.
+     */
+    @NonNull
+    public static OverlayConfig initializeSystemInstance(PackageProvider packageProvider) {
+        Trace.traceBegin(Trace.TRACE_TAG_RRO, "OverlayConfig#initializeSystemInstance");
+        try {
+            sInstance = new OverlayConfig(null, null, packageProvider);
+        } finally {
+            Trace.traceEnd(Trace.TRACE_TAG_RRO);
+        }
+        return sInstance;
+    }
+
+    /**
+     * Retrieves the singleton instance initialized by
+     * {@link #initializeSystemInstance(PackageProvider)}.
+     */
+    @NonNull
+    public static OverlayConfig getSystemInstance() {
+        if (sInstance == null) {
+            throw new IllegalStateException("System instance not initialized");
+        }
+
+        return sInstance;
+    }
+
+    @VisibleForTesting
+    @Nullable
+    public Configuration getConfiguration(@NonNull String packageName) {
+        return mConfigurations.get(packageName);
+    }
+
+    /**
+     * Returns whether the overlay is enabled by default.
+     * Overlays that are not configured are disabled by default mutable.
+     */
+    public boolean isEnabled(String packageName) {
+        final Configuration config = mConfigurations.get(packageName);
+
+        // STOPSHIP(149499802): Enabling a mutable overlay currently has no effect. Either implement
+        // some behavior for default-enabled, mutable overlays or prevent parsing of the enabled
+        // attribute on overlays that are mutable.
+        if (config != null && config.parsedConfig.mutable) {
+            Log.w(TAG, "Default-enabled configuration for mutable overlay "
+                    + config.parsedConfig.packageName + " has no effect");
+            return OverlayConfigParser.DEFAULT_ENABLED_STATE;
+        }
+
+        return config == null? OverlayConfigParser.DEFAULT_ENABLED_STATE
+                : config.parsedConfig.enabled;
+    }
+
+    /**
+     * Returns whether the overlay is mutable and can have its enabled state changed dynamically.
+     * Overlays that are not configured are mutable.
+     */
+    public boolean isMutable(String packageName) {
+        final Configuration config = mConfigurations.get(packageName);
+        return config == null ? OverlayConfigParser.DEFAULT_MUTABILITY
+                : config.parsedConfig.mutable;
+    }
+
+    /**
+     * Returns an integer corresponding to the priority of the overlay.
+     * When multiple overlays override the same resource, the overlay with the highest priority will
+     * will have its value chosen. Overlays that are not configured have a priority of
+     * {@link Integer#MAX_VALUE}.
+     */
+    public int getPriority(String packageName) {
+        final Configuration config = mConfigurations.get(packageName);
+        return config == null ? DEFAULT_PRIORITY : config.configIndex;
+    }
+
+    @NonNull
+    private ArrayList<Configuration> getSortedOverlays() {
+        final ArrayList<Configuration> sortedOverlays = new ArrayList<>();
+        for (int i = 0, n = mConfigurations.size(); i < n; i++) {
+            sortedOverlays.add(mConfigurations.valueAt(i));
+        }
+        sortedOverlays.sort(Comparator.comparingInt(o -> o.configIndex));
+        return sortedOverlays;
+    }
+
+    @NonNull
+    private static ArrayList<ParsedOverlayInfo> getOverlayPackageInfos(
+            @NonNull PackageProvider packageManager) {
+        final ArrayList<ParsedOverlayInfo> overlays = new ArrayList<>();
+        packageManager.forEachPackage((ParsingPackageRead p, Boolean isSystem) -> {
+            if (p.getOverlayTarget() != null && isSystem) {
+                overlays.add(new ParsedOverlayInfo(p.getPackageName(), p.getOverlayTarget(),
+                        p.getTargetSdkVersion(), p.isOverlayIsStatic(), p.getOverlayPriority(),
+                        new File(p.getBaseCodePath())));
+            }
+        });
+        return overlays;
+    }
+
+    /** Represents a single call to idmap create-multiple. */
+    @VisibleForTesting
+    public static class IdmapInvocation {
+        public final boolean enforceOverlayable;
+        public final String policy;
+        public final ArrayList<String> overlayPaths = new ArrayList<>();
+
+        IdmapInvocation(boolean enforceOverlayable, @NonNull String policy) {
+            this.enforceOverlayable = enforceOverlayable;
+            this.policy = policy;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getSimpleName() + String.format("{enforceOverlayable=%s, policy=%s"
+                            + ", overlayPaths=[%s]}", enforceOverlayable, policy,
+                    String.join(", ", overlayPaths));
+        }
+    }
+
+    /**
+     * Retrieves a list of immutable framework overlays in order of least precedence to greatest
+     * precedence.
+     */
+    @VisibleForTesting
+    public ArrayList<IdmapInvocation> getImmutableFrameworkOverlayIdmapInvocations() {
+        final ArrayList<IdmapInvocation> idmapInvocations = new ArrayList<>();
+        final ArrayList<Configuration> sortedConfigs = getSortedOverlays();
+        for (int i = 0, n = sortedConfigs.size(); i < n; i++) {
+            final Configuration overlay = sortedConfigs.get(i);
+            if (overlay.parsedConfig.mutable || !overlay.parsedConfig.enabled
+                    || !"android".equals(overlay.parsedConfig.parsedInfo.targetPackageName)) {
+                continue;
+            }
+
+            // Only enforce that overlays targeting packages with overlayable declarations abide by
+            // those declarations if the target sdk of the overlay is at least Q (when overlayable
+            // was introduced).
+            final boolean enforceOverlayable = overlay.parsedConfig.parsedInfo.targetSdkVersion
+                    >= Build.VERSION_CODES.Q;
+
+            // Determine if the idmap for the current overlay can be generated in the last idmap
+            // create-multiple invocation.
+            IdmapInvocation invocation = null;
+            if (!idmapInvocations.isEmpty()) {
+                final IdmapInvocation last = idmapInvocations.get(idmapInvocations.size() - 1);
+                if (last.enforceOverlayable == enforceOverlayable
+                        && last.policy.equals(overlay.parsedConfig.policy)) {
+                    invocation = last;
+                }
+            }
+
+            if (invocation == null) {
+                invocation = new IdmapInvocation(enforceOverlayable, overlay.parsedConfig.policy);
+                idmapInvocations.add(invocation);
+            }
+
+            invocation.overlayPaths.add(overlay.parsedConfig.parsedInfo.path.getAbsolutePath());
+        }
+        return idmapInvocations;
+    }
+
+    /**
+     * Creates idmap files for immutable overlays targeting the framework packages. Currently the
+     * android package is the only preloaded system package. Only the zygote can invoke this method.
+     *
+     * @return the paths of the created idmap files
+     */
+    @NonNull
+    public String[] createImmutableFrameworkIdmapsInZygote() {
+        final String targetPath = "/system/framework/framework-res.apk";
+        final ArrayList<String> idmapPaths = new ArrayList<>();
+        final ArrayList<IdmapInvocation> idmapInvocations =
+                getImmutableFrameworkOverlayIdmapInvocations();
+
+        for (int i = 0, n = idmapInvocations.size(); i < n; i++) {
+            final IdmapInvocation invocation = idmapInvocations.get(i);
+            final String[] idmaps = createIdmap(targetPath,
+                    invocation.overlayPaths.toArray(new String[0]),
+                    new String[]{OverlayConfigParser.OverlayPartition.POLICY_PUBLIC,
+                            invocation.policy},
+                    invocation.enforceOverlayable);
+
+            if (idmaps == null) {
+                Log.w(TAG, "'idmap2 create-multiple' failed: no mutable=\"false\" overlays"
+                        + " targeting \"android\" will be loaded");
+                return new String[0];
+            }
+
+            idmapPaths.addAll(Arrays.asList(idmaps));
+        }
+
+        return idmapPaths.toArray(new String[0]);
+    }
+
+    /**
+     * For each overlay APK, this creates the idmap file that allows the overlay to override the
+     * target package.
+     *
+     * @return the paths of the created idmap
+     */
+    private static native String[] createIdmap(@NonNull String targetPath,
+            @NonNull String[] overlayPath, @NonNull String[] policies, boolean enforceOverlayable);
+}
diff --git a/core/java/com/android/internal/content/om/OverlayConfigParser.java b/core/java/com/android/internal/content/om/OverlayConfigParser.java
new file mode 100644
index 0000000..139607f
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayConfigParser.java
@@ -0,0 +1,391 @@
+/*
+ * 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.internal.content.om;
+
+import static com.android.internal.content.om.OverlayConfig.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackagePartitions;
+import android.content.pm.PackagePartitions.SystemPartition;
+import android.os.FileUtils;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.Xml;
+
+import com.android.internal.util.XmlUtils;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Responsible for parsing configurations of Runtime Resource Overlays that control mutability,
+ * default enable state, and priority. To configure an overlay, create or modify the file located
+ * at {@code partition}/overlay/config/config.xml where {@code partition} is the partition of the
+ * overlay to be configured. In order to be configured, an overlay must reside in the overlay
+ * directory of the partition in which the overlay is configured.
+ *
+ * @see #parseOverlay(File, XmlPullParser, OverlayScanner, ParsingContext)
+ * @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
+ **/
+final class OverlayConfigParser {
+
+    // Default values for overlay configurations.
+    static final boolean DEFAULT_ENABLED_STATE = false;
+    static final boolean DEFAULT_MUTABILITY = true;
+
+    // Maximum recursive depth of processing merge tags.
+    private static final int MAXIMUM_MERGE_DEPTH = 5;
+
+    // The subdirectory within a partition's overlay directory that contains the configuration files
+    // for the partition.
+    private static final String CONFIG_DIRECTORY = "config";
+
+    /**
+     * The name of the configuration file to parse for overlay configurations. This class does not
+     * scan for overlay configuration files within the {@link #CONFIG_DIRECTORY}; rather, other
+     * files can be included at a particular position within this file using the <merge> tag.
+     *
+     * @see #parseMerge(File, XmlPullParser, OverlayScanner, ParsingContext)
+     */
+    private static final String CONFIG_DEFAULT_FILENAME = CONFIG_DIRECTORY + "/config.xml";
+
+    /** Represents the configurations of a particular overlay. */
+    public static class ParsedConfiguration {
+        @NonNull
+        public final String packageName;
+
+        /** Whether or not the overlay is enabled by default. */
+        public final boolean enabled;
+
+        /**
+         * Whether or not the overlay is mutable and can have its enabled state changed dynamically
+         * using the {@code OverlayManagerService}.
+         **/
+        public final boolean mutable;
+
+        /** The policy granted to overlays on the partition in which the overlay is located. */
+        @NonNull
+        public final String policy;
+
+        /** Information extracted from the manifest of the overlay. */
+        @NonNull
+        public final ParsedOverlayInfo parsedInfo;
+
+        ParsedConfiguration(@NonNull String packageName, boolean enabled, boolean mutable,
+                @NonNull String policy, @NonNull ParsedOverlayInfo parsedInfo) {
+            this.packageName = packageName;
+            this.enabled = enabled;
+            this.mutable = mutable;
+            this.policy = policy;
+            this.parsedInfo = parsedInfo;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getSimpleName() + String.format("{packageName=%s, enabled=%s"
+                            + ", mutable=%s, policy=%s, parsedInfo=%s}", packageName, enabled,
+                    mutable, policy, parsedInfo);
+        }
+    }
+
+    static class OverlayPartition extends SystemPartition {
+        // Policies passed to idmap2 during idmap creation.
+        // Keep partition policy constants in sync with f/b/cmds/idmap2/include/idmap2/Policies.h.
+        static final String POLICY_ODM = "odm";
+        static final String POLICY_OEM = "oem";
+        static final String POLICY_PRODUCT = "product";
+        static final String POLICY_PUBLIC = "public";
+        static final String POLICY_SYSTEM = "system";
+        static final String POLICY_VENDOR = "vendor";
+
+        @NonNull
+        public final String policy;
+
+        OverlayPartition(@NonNull SystemPartition partition) {
+            super(partition);
+            this.policy = policyForPartition(partition);
+        }
+
+        /**
+         * Creates a partition containing the same folders as the original partition but with a
+         * different root folder.
+         */
+        OverlayPartition(@NonNull File folder, @NonNull SystemPartition original) {
+            super(folder, original);
+            this.policy = policyForPartition(original);
+        }
+
+        private static String policyForPartition(SystemPartition partition) {
+            switch (partition.type) {
+                case PackagePartitions.PARTITION_SYSTEM:
+                case PackagePartitions.PARTITION_SYSTEM_EXT:
+                    return POLICY_SYSTEM;
+                case PackagePartitions.PARTITION_VENDOR:
+                    return POLICY_VENDOR;
+                case PackagePartitions.PARTITION_ODM:
+                    return POLICY_ODM;
+                case PackagePartitions.PARTITION_OEM:
+                    return POLICY_OEM;
+                case PackagePartitions.PARTITION_PRODUCT:
+                    return POLICY_PRODUCT;
+                default:
+                    throw new IllegalStateException("Unable to determine policy for "
+                            + partition.folder);
+            }
+        }
+    }
+
+    /** This class holds state related to parsing the configurations of a partition. */
+    private static class ParsingContext {
+        // The overlay directory of the partition
+        private final OverlayPartition mPartition;
+
+        // The ordered list of configured overlays
+        private final ArrayList<ParsedConfiguration> mOrderedConfigurations = new ArrayList<>();
+
+        // The packages configured in the partition
+        private final ArraySet<String> mConfiguredOverlays = new ArraySet<>();
+
+        // Whether an mutable overlay has been configured in the partition
+        private boolean mFoundMutableOverlay;
+
+        // The current recursive depth of merging configuration files
+        private int mMergeDepth;
+
+        private ParsingContext(OverlayPartition partition) {
+            mPartition = partition;
+        }
+    }
+
+    /**
+     * Retrieves overlays configured within the partition in increasing priority order.
+     *
+     * If {@code scanner} is null, then the {@link ParsedConfiguration#parsedInfo} fields of the
+     * added configured overlays will be null and the parsing logic will not assert that the
+     * configured overlays exist within the partition.
+     *
+     * @return list of configured overlays if configuration file exists; otherwise, null
+     */
+    @Nullable
+    static ArrayList<ParsedConfiguration> getConfigurations(
+            @NonNull OverlayPartition partition, @Nullable OverlayScanner scanner) {
+        if (partition.getOverlayFolder() == null) {
+            return null;
+        }
+
+        if (scanner != null) {
+            scanner.scanDir(partition.getOverlayFolder());
+        }
+
+        final File configFile = new File(partition.getOverlayFolder(), CONFIG_DEFAULT_FILENAME);
+        if (!configFile.exists()) {
+            return null;
+        }
+
+        final ParsingContext parsingContext = new ParsingContext(partition);
+        readConfigFile(configFile, scanner, parsingContext);
+        return parsingContext.mOrderedConfigurations;
+    }
+
+    private static void readConfigFile(@NonNull File configFile, @Nullable OverlayScanner scanner,
+            @NonNull ParsingContext parsingContext) {
+        FileReader configReader;
+        try {
+            configReader = new FileReader(configFile);
+        } catch (FileNotFoundException e) {
+            Log.w(TAG, "Couldn't find or open overlay configuration file " + configFile);
+            return;
+        }
+
+        try {
+            final XmlPullParser parser = Xml.newPullParser();
+            parser.setInput(configReader);
+            XmlUtils.beginDocument(parser, "config");
+
+            int depth = parser.getDepth();
+            while (XmlUtils.nextElementWithin(parser, depth)) {
+                final String name = parser.getName();
+                switch (name) {
+                    case "merge":
+                        parseMerge(configFile, parser, scanner, parsingContext);
+                        break;
+                    case "overlay":
+                        parseOverlay(configFile, parser, scanner, parsingContext);
+                        break;
+                    default:
+                        Log.w(TAG, String.format("Tag %s is unknown in %s at %s",
+                                name, configFile, parser.getPositionDescription()));
+                        break;
+                }
+            }
+        } catch (XmlPullParserException | IOException e) {
+            Log.w(TAG, "Got exception parsing overlay configuration.", e);
+        } finally {
+            IoUtils.closeQuietly(configReader);
+        }
+    }
+
+    /**
+     * Parses a <merge> tag within an overlay configuration file.
+     *
+     * Merge tags allow for other configuration files to be "merged" at the current parsing
+     * position into the current configuration file being parsed. The {@code path} attribute of the
+     * tag represents the path of the file to merge relative to the directory containing overlay
+     * configuration files.
+     */
+    private static void parseMerge(@NonNull File configFile, @NonNull XmlPullParser parser,
+            @Nullable OverlayScanner scanner, @NonNull ParsingContext parsingContext) {
+        final String path = parser.getAttributeValue(null, "path");
+        if (path == null) {
+            throw new IllegalStateException(String.format("<merge> without path in %s at %s"
+                    + configFile, parser.getPositionDescription()));
+        }
+
+        if (path.startsWith("/")) {
+            throw new IllegalStateException(String.format(
+                    "Path %s must be relative to the directory containing overlay configurations "
+                            + " files in %s at %s ", path, configFile,
+                    parser.getPositionDescription()));
+        }
+
+        if (parsingContext.mMergeDepth++ == MAXIMUM_MERGE_DEPTH) {
+            throw new IllegalStateException(String.format(
+                    "Maximum <merge> depth exceeded in %s at %s", configFile,
+                    parser.getPositionDescription()));
+        }
+
+        final File configDirectory;
+        final File includedConfigFile;
+        try {
+            configDirectory = new File(parsingContext.mPartition.getOverlayFolder(),
+                    CONFIG_DIRECTORY).getCanonicalFile();
+            includedConfigFile = new File(configDirectory, path).getCanonicalFile();
+        } catch (IOException e) {
+            throw new IllegalStateException(
+                    String.format("Couldn't find or open merged configuration file %s in %s at %s",
+                            path, configFile, parser.getPositionDescription()), e);
+        }
+
+        if (!includedConfigFile.exists()) {
+            throw new IllegalStateException(
+                    String.format("Merged configuration file %s does not exist in %s at %s",
+                            path, configFile, parser.getPositionDescription()));
+        }
+
+        if (!FileUtils.contains(configDirectory, includedConfigFile)) {
+            throw new IllegalStateException(
+                    String.format(
+                            "Merged file %s outside of configuration directory in %s at %s",
+                            includedConfigFile.getAbsolutePath(), includedConfigFile,
+                            parser.getPositionDescription()));
+        }
+
+        readConfigFile(includedConfigFile, scanner, parsingContext);
+        parsingContext.mMergeDepth--;
+    }
+
+    /**
+     * Parses an <overlay> tag within an overlay configuration file.
+     *
+     * Requires a {@code package} attribute that indicates which package is being configured.
+     * The optional {@code enabled} attribute controls whether or not the overlay is enabled by
+     * default (default is false). The optional {@code mutable} attribute controls whether or
+     * not the overlay is mutable and can have its enabled state changed at runtime (default is
+     * true).
+     *
+     * The order in which overlays that override the same resources are configured matters. An
+     * overlay will have a greater priority than overlays with configurations preceding its own
+     * configuration.
+     *
+     * Configurations of immutable overlays must precede configurations of mutable overlays.
+     * An overlay cannot be configured in multiple locations. All configured overlay must exist
+     * within the partition of the configuration file. An overlay cannot be configured multiple
+     * times in a single partition.
+     *
+     * Overlays not listed within a configuration file will be mutable and disabled by default. The
+     * order of non-configured overlays when enabled by the OverlayManagerService is undefined.
+     */
+    private static void parseOverlay(@NonNull File configFile, @NonNull XmlPullParser parser,
+            @Nullable OverlayScanner scanner, @NonNull ParsingContext parsingContext) {
+        final String packageName = parser.getAttributeValue(null, "package");
+        if (packageName == null) {
+            throw new IllegalStateException(String.format("\"<overlay> without package in %s at %s",
+                    configFile, parser.getPositionDescription()));
+        }
+
+        // Ensure the overlay being configured is present in the partition during zygote
+        // initialization.
+        ParsedOverlayInfo info = null;
+        if (scanner != null) {
+            info = scanner.getParsedInfo(packageName);
+            if (info == null|| !parsingContext.mPartition.containsOverlay(info.path)) {
+                throw new IllegalStateException(
+                        String.format("overlay %s not present in partition %s in %s at %s",
+                                packageName, parsingContext.mPartition.getOverlayFolder(),
+                                configFile, parser.getPositionDescription()));
+            }
+        }
+
+        if (parsingContext.mConfiguredOverlays.contains(packageName)) {
+            throw new IllegalStateException(
+                    String.format("overlay %s configured multiple times in a single partition"
+                                    + " in %s at %s", packageName, configFile,
+                            parser.getPositionDescription()));
+        }
+
+        boolean isEnabled = DEFAULT_ENABLED_STATE;
+        final String enabled = parser.getAttributeValue(null, "enabled");
+        if (enabled != null) {
+            isEnabled = !"false".equals(enabled);
+        }
+
+        boolean isMutable = DEFAULT_MUTABILITY;
+        final String mutable = parser.getAttributeValue(null, "mutable");
+        if (mutable != null) {
+            isMutable = !"false".equals(mutable);
+            if (!isMutable && parsingContext.mFoundMutableOverlay) {
+                throw new IllegalStateException(String.format(
+                        "immutable overlays must precede mutable overlays:"
+                                + " found in %s at %s",
+                        configFile, parser.getPositionDescription()));
+            }
+        }
+
+        if (isMutable) {
+            parsingContext.mFoundMutableOverlay = true;
+        } else if (!isEnabled) {
+            // Default disabled, immutable overlays may be a misconfiguration of the system so warn
+            // developers.
+            Log.w(TAG, "found default-disabled immutable overlay " + packageName);
+        }
+
+        final ParsedConfiguration Config = new ParsedConfiguration(packageName, isEnabled,
+                isMutable, parsingContext.mPartition.policy, info);
+        parsingContext.mConfiguredOverlays.add(packageName);
+        parsingContext.mOrderedConfigurations.add(Config);
+    }
+}
diff --git a/core/java/com/android/internal/content/om/OverlayScanner.java b/core/java/com/android/internal/content/om/OverlayScanner.java
new file mode 100644
index 0000000..a85cf56
--- /dev/null
+++ b/core/java/com/android/internal/content/om/OverlayScanner.java
@@ -0,0 +1,138 @@
+/*
+ * 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.internal.content.om;
+
+import static com.android.internal.content.om.OverlayConfig.TAG;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageParser;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * This class scans a directory containing overlay APKs and extracts information from the overlay
+ * manifests by parsing the overlay manifests.
+ */
+@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+public class OverlayScanner {
+
+    /** Represents information parsed from the manifest of an overlay. */
+    public static class ParsedOverlayInfo {
+        public final String packageName;
+        public final String targetPackageName;
+        public final int targetSdkVersion;
+        public final boolean isStatic;
+        public final int priority;
+        public final File path;
+
+        public ParsedOverlayInfo(String packageName, String targetPackageName,
+                int targetSdkVersion, boolean isStatic, int priority, File path) {
+            this.packageName = packageName;
+            this.targetPackageName = targetPackageName;
+            this.targetSdkVersion = targetSdkVersion;
+            this.isStatic = isStatic;
+            this.priority = priority;
+            this.path = path;
+        }
+
+        @Override
+        public String toString() {
+            return getClass().getSimpleName() + String.format("{packageName=%s"
+                            + ", targetPackageName=%s, targetSdkVersion=%s, isStatic=%s"
+                            + ", priority=%s, path=%s}",
+                    packageName, targetPackageName, targetSdkVersion, isStatic, priority, path);
+        }
+    }
+
+    /**
+     * A map of overlay package name to the parsed manifest information of the latest version of
+     * the overlay.
+     */
+    private final ArrayMap<String, ParsedOverlayInfo> mParsedOverlayInfos = new ArrayMap<>();
+
+    /** Retrieves information parsed from the overlay with the package name. */
+    @Nullable
+    public final ParsedOverlayInfo getParsedInfo(String packageName) {
+        return mParsedOverlayInfos.get(packageName);
+    }
+
+    /** Retrieves all of the scanned overlays. */
+    @NonNull
+    final Collection<ParsedOverlayInfo> getAllParsedInfos() {
+        return mParsedOverlayInfos.values();
+    }
+
+    /**
+     * Recursively searches the directory for overlay APKs. If an overlay is found with the same
+     * package name as a previously scanned overlay, the info of the new overlay will replace the
+     * info of the previously scanned overlay.
+     */
+    public void scanDir(File partitionOverlayDir) {
+        if (!partitionOverlayDir.exists() || !partitionOverlayDir.isDirectory()) {
+            return;
+        }
+
+        if (!partitionOverlayDir.canRead()) {
+            Log.w(TAG, "Directory " + partitionOverlayDir + " cannot be read");
+            return;
+        }
+
+        final File[] files = partitionOverlayDir.listFiles();
+        if (files == null) {
+            return;
+        }
+
+        for (int i = 0; i < files.length; i++) {
+            final File f = files[i];
+            if (f.isDirectory()) {
+                scanDir(f);
+            }
+
+            if (!f.isFile() || !f.getPath().endsWith(".apk")) {
+                continue;
+            }
+
+            final ParsedOverlayInfo info = parseOverlayManifest(f);
+            if (info == null) {
+                continue;
+            }
+
+            mParsedOverlayInfos.put(info.packageName, info);
+        }
+    }
+
+    /** Extracts information about the overlay from its manifest. */
+    @VisibleForTesting
+    public ParsedOverlayInfo parseOverlayManifest(File overlayApk) {
+        try {
+            final PackageParser.ApkLite apkLite = PackageParser.parseApkLite(overlayApk, 0);
+            return apkLite.targetPackageName == null ? null :
+                    new ParsedOverlayInfo(apkLite.packageName, apkLite.targetPackageName,
+                            apkLite.targetSdkVersion, apkLite.overlayIsStatic,
+                            apkLite.overlayPriority, new File(apkLite.codePath));
+        } catch (PackageParser.PackageParserException e) {
+            Log.w(TAG, "Got exception loading overlay.", e);
+            return null;
+        }
+    }
+}
diff --git a/core/java/com/android/internal/content/om/TEST_MAPPING b/core/java/com/android/internal/content/om/TEST_MAPPING
new file mode 100644
index 0000000..4cb595b
--- /dev/null
+++ b/core/java/com/android/internal/content/om/TEST_MAPPING
@@ -0,0 +1,12 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.content."
+        }
+      ]
+    }
+  ]
+}
\ No newline at end of file
diff --git a/core/java/com/android/internal/net/VpnProfile.java b/core/java/com/android/internal/net/VpnProfile.java
index bbae027..23b1ab5 100644
--- a/core/java/com/android/internal/net/VpnProfile.java
+++ b/core/java/com/android/internal/net/VpnProfile.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.compat.annotation.UnsupportedAppUsage;
+import android.net.Ikev2VpnProfile;
 import android.net.ProxyInfo;
 import android.os.Build;
 import android.os.Parcel;
@@ -332,15 +333,38 @@
         return builder.toString().getBytes(StandardCharsets.UTF_8);
     }
 
+    /** Checks if this profile specifies a LegacyVpn type. */
+    public static boolean isLegacyType(int type) {
+        switch (type) {
+            case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS: // fall through
+            case VpnProfile.TYPE_IKEV2_IPSEC_RSA: // fall through
+            case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
+                return false;
+            default:
+                return true;
+        }
+    }
+
+    private boolean isValidLockdownLegacyVpnProfile() {
+        return isLegacyType(type) && isServerAddressNumeric() && hasDns()
+                && areDnsAddressesNumeric();
+    }
+
+    private boolean isValidLockdownPlatformVpnProfile() {
+        return Ikev2VpnProfile.isValidVpnProfile(this);
+    }
+
     /**
-     * Tests if profile is valid for lockdown, which requires IPv4 address for both server and DNS.
-     * Server hostnames would require using DNS before connection.
+     * Tests if profile is valid for lockdown.
+     *
+     * <p>For LegacyVpn profiles, this requires an IPv4 address for both the server and DNS.
+     *
+     * <p>For PlatformVpn profiles, this requires a server, an identifier and the relevant fields to
+     * be non-null.
      */
     public boolean isValidLockdownProfile() {
         return isTypeValidForLockdown()
-                && isServerAddressNumeric()
-                && hasDns()
-                && areDnsAddressesNumeric();
+                && (isValidLockdownLegacyVpnProfile() || isValidLockdownPlatformVpnProfile());
     }
 
     /** Returns {@code true} if the VPN type is valid for lockdown. */
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 18066dc..27c7cb6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -1000,6 +1000,8 @@
     private int mMinLearnedBatteryCapacity = -1;
     private int mMaxLearnedBatteryCapacity = -1;
 
+    private long mBatteryTimeToFullSeconds = -1;
+
     private long[] mCpuFreqs;
 
     @VisibleForTesting
@@ -12226,7 +12228,7 @@
     @GuardedBy("this")
     public void setBatteryStateLocked(final int status, final int health, final int plugType,
             final int level, /* not final */ int temp, final int volt, final int chargeUAh,
-            final int chargeFullUAh) {
+            final int chargeFullUAh, final long chargeTimeToFullSeconds) {
         // Temperature is encoded without the signed bit, so clamp any negative temperatures to 0.
         temp = Math.max(0, temp);
 
@@ -12429,6 +12431,8 @@
             mMinLearnedBatteryCapacity = Math.min(mMinLearnedBatteryCapacity, chargeFullUAh);
         }
         mMaxLearnedBatteryCapacity = Math.max(mMaxLearnedBatteryCapacity, chargeFullUAh);
+
+        mBatteryTimeToFullSeconds = chargeTimeToFullSeconds;
     }
 
     public static boolean isOnBattery(int plugType, int status) {
@@ -12578,19 +12582,10 @@
             // Not yet working.
             return -1;
         }
-        /* Broken
-        int curLevel = mCurrentBatteryLevel;
-        int plugLevel = mDischargePlugLevel;
-        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
-            return -1;
+        if (mBatteryTimeToFullSeconds >= 0) {
+            return mBatteryTimeToFullSeconds * (1000 * 1000); // s to us
         }
-        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
-        if (duration < 1000*1000) {
-            return -1;
-        }
-        long usPerLevel = duration/(curLevel-plugLevel);
-        return usPerLevel * (100-curLevel);
-        */
+        // Else use algorithmic approach
         if (mChargeStepTracker.mNumStepDurations < 1) {
             return -1;
         }
@@ -12598,7 +12593,7 @@
         if (msPerLevel <= 0) {
             return -1;
         }
-        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
+        return (msPerLevel * (100 - mCurrentBatteryLevel)) * 1000;
     }
 
     /*@hide */
diff --git a/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
new file mode 100644
index 0000000..26f81d9
--- /dev/null
+++ b/core/java/com/android/internal/os/KernelCpuUidBpfMapReader.java
@@ -0,0 +1,202 @@
+/*
+ * 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.internal.os;
+
+import android.os.StrictMode;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ * Reads cpu time bpf maps.
+ *
+ * It is implemented as singletons for each separate set of per-UID times. Get___Instance() method
+ * returns the corresponding reader instance. In order to prevent frequent GC, it reuses the same
+ * SparseArray to store data read from BPF maps.
+ *
+ * A KernelCpuUidBpfMapReader instance keeps an error counter. When the number of read errors within
+ * that instance accumulates to 5, this instance will reject all further read requests.
+ *
+ * Data fetched within last 500ms is considered fresh, since the reading lifecycle can take up to
+ * 25ms. KernelCpuUidBpfMapReader always tries to use cache if it is fresh and valid, but it can
+ * be disabled through a parameter.
+ *
+ * A KernelCpuUidBpfMapReader instance is thread-safe. It acquires a write lock when reading the bpf
+ * map, releases it right after, then acquires a read lock before returning a BpfMapIterator. Caller
+ * is responsible for closing BpfMapIterator (also auto-closable) after reading, otherwise deadlock
+ * will occur.
+ */
+public abstract class KernelCpuUidBpfMapReader {
+    private static final int ERROR_THRESHOLD = 5;
+    private static final long FRESHNESS_MS = 500L;
+
+    private static final KernelCpuUidBpfMapReader FREQ_TIME_READER =
+        new KernelCpuUidFreqTimeBpfMapReader();
+
+    private static final KernelCpuUidBpfMapReader ACTIVE_TIME_READER =
+        new KernelCpuUidActiveTimeBpfMapReader();
+
+    private static final KernelCpuUidBpfMapReader CLUSTER_TIME_READER =
+        new KernelCpuUidClusterTimeBpfMapReader();
+
+    static KernelCpuUidBpfMapReader getFreqTimeReaderInstance() {
+        return FREQ_TIME_READER;
+    }
+
+    static KernelCpuUidBpfMapReader getActiveTimeReaderInstance() {
+        return ACTIVE_TIME_READER;
+    }
+
+    static KernelCpuUidBpfMapReader getClusterTimeReaderInstance() {
+        return CLUSTER_TIME_READER;
+    }
+
+    final String mTag = this.getClass().getSimpleName();
+    private int mErrors = 0;
+    private boolean mTracking = false;
+    protected SparseArray<long[]> mData = new SparseArray<>();
+    private long mLastReadTime = 0;
+    protected final ReentrantReadWriteLock mLock = new ReentrantReadWriteLock();
+    protected final ReentrantReadWriteLock.ReadLock mReadLock = mLock.readLock();
+    protected final ReentrantReadWriteLock.WriteLock mWriteLock = mLock.writeLock();
+
+    public native boolean startTrackingBpfTimes();
+
+    protected abstract boolean readBpfData();
+
+    /**
+     * Returns an array of metadata used to inform the caller of 1) the size of array required by
+     * getNextUid and 2) how to interpret the raw data copied to that array.
+     */
+    public abstract long[] getDataDimensions();
+
+    public void removeUidsInRange(int startUid, int endUid) {
+        if (mErrors > ERROR_THRESHOLD) {
+            return;
+        }
+        mWriteLock.lock();
+        int firstIndex = mData.indexOfKey(startUid);
+        int lastIndex = mData.indexOfKey(endUid);
+        mData.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+        mWriteLock.unlock();
+    }
+
+    public BpfMapIterator open() {
+        return open(false);
+    }
+
+    public BpfMapIterator open(boolean ignoreCache) {
+        if (mErrors > ERROR_THRESHOLD) {
+            return null;
+        }
+        if (!mTracking && !startTrackingBpfTimes()) {
+            Slog.w(mTag, "Failed to start tracking");
+            mErrors++;
+            return null;
+        }
+        if (ignoreCache) {
+            mWriteLock.lock();
+        } else {
+            mReadLock.lock();
+            if (dataValid()) {
+                return new BpfMapIterator();
+            }
+            mReadLock.unlock();
+            mWriteLock.lock();
+            if (dataValid()) {
+                mReadLock.lock();
+                mWriteLock.unlock();
+                return new BpfMapIterator();
+            }
+        }
+        if (readBpfData()) {
+            mLastReadTime = SystemClock.elapsedRealtime();
+            mReadLock.lock();
+            mWriteLock.unlock();
+            return new BpfMapIterator();
+        }
+
+        mWriteLock.unlock();
+        mErrors++;
+        Slog.w(mTag, "Failed to read bpf times");
+        return null;
+    }
+
+    private boolean dataValid() {
+        return mData.size() > 0 && (SystemClock.elapsedRealtime() - mLastReadTime < FRESHNESS_MS);
+    }
+
+    public class BpfMapIterator implements AutoCloseable {
+        private int mPos;
+
+        public BpfMapIterator() {
+        };
+
+        public boolean getNextUid(long[] buf) {
+            if (mPos >= mData.size()) {
+                return false;
+            }
+            buf[0] = mData.keyAt(mPos);
+            System.arraycopy(mData.valueAt(mPos), 0, buf, 1, mData.valueAt(mPos).length);
+            mPos++;
+            return true;
+        }
+
+        public void close() {
+            mReadLock.unlock();
+        }
+    }
+
+    public static class KernelCpuUidFreqTimeBpfMapReader extends KernelCpuUidBpfMapReader {
+
+        private final native boolean removeUidRange(int startUid, int endUid);
+
+        @Override
+        protected final native boolean readBpfData();
+
+        @Override
+        public final native long[] getDataDimensions();
+
+        @Override
+        public void removeUidsInRange(int startUid, int endUid) {
+            mWriteLock.lock();
+            super.removeUidsInRange(startUid, endUid);
+            removeUidRange(startUid, endUid);
+            mWriteLock.unlock();
+        }
+    }
+
+    public static class KernelCpuUidActiveTimeBpfMapReader extends KernelCpuUidBpfMapReader {
+
+        @Override
+        protected final native boolean readBpfData();
+
+        @Override
+        public final native long[] getDataDimensions();
+    }
+
+    public static class KernelCpuUidClusterTimeBpfMapReader extends KernelCpuUidBpfMapReader {
+
+        @Override
+        protected final native boolean readBpfData();
+
+        @Override
+        public final native long[] getDataDimensions();
+    }
+}
diff --git a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
index f1eb2fb..f7fad2c 100644
--- a/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelCpuUidTimeReader.java
@@ -28,6 +28,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.KernelCpuProcStringReader.ProcFileIterator;
+import com.android.internal.os.KernelCpuUidBpfMapReader.BpfMapIterator;
 
 import java.io.BufferedReader;
 import java.io.FileWriter;
@@ -57,6 +58,8 @@
     final SparseArray<T> mLastTimes = new SparseArray<>();
     final KernelCpuProcStringReader mReader;
     final boolean mThrottle;
+    protected boolean mBpfTimesAvailable;
+    final KernelCpuUidBpfMapReader mBpfReader;
     private long mMinTimeBetweenRead = DEFAULT_MIN_TIME_BETWEEN_READ;
     private long mLastReadTimeMs = 0;
 
@@ -73,9 +76,15 @@
         void onUidCpuTime(int uid, T time);
     }
 
-    KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
+    KernelCpuUidTimeReader(KernelCpuProcStringReader reader, @Nullable KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
         mReader = reader;
         mThrottle = throttle;
+        mBpfReader = bpfReader;
+        mBpfTimesAvailable = (mBpfReader != null);
+    }
+
+    KernelCpuUidTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
+        this(reader, null, throttle);
     }
 
     /**
@@ -151,9 +160,13 @@
         }
         mLastTimes.put(startUid, null);
         mLastTimes.put(endUid, null);
-        final int firstIndex = mLastTimes.indexOfKey(startUid);
-        final int lastIndex = mLastTimes.indexOfKey(endUid);
+        int firstIndex = mLastTimes.indexOfKey(startUid);
+        int lastIndex = mLastTimes.indexOfKey(endUid);
         mLastTimes.removeAtRange(firstIndex, lastIndex - firstIndex + 1);
+
+        if (mBpfTimesAvailable) {
+            mBpfReader.removeUidsInRange(startUid, endUid);
+        }
     }
 
     /**
@@ -323,13 +336,13 @@
 
         public KernelCpuUidFreqTimeReader(boolean throttle) {
             this(UID_TIMES_PROC_FILE, KernelCpuProcStringReader.getFreqTimeReaderInstance(),
-                    throttle);
+                 KernelCpuUidBpfMapReader.getFreqTimeReaderInstance(), throttle);
         }
 
         @VisibleForTesting
         public KernelCpuUidFreqTimeReader(String procFile, KernelCpuProcStringReader reader,
-                boolean throttle) {
-            super(reader, throttle);
+                KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
+            super(reader, bpfReader, throttle);
             mProcFilePath = Paths.get(procFile);
         }
 
@@ -370,19 +383,24 @@
             if (!mAllUidTimesAvailable) {
                 return null;
             }
-            final int oldMask = StrictMode.allowThreadDiskReadsMask();
-            try (BufferedReader reader = Files.newBufferedReader(mProcFilePath)) {
-                if (readFreqs(reader.readLine()) == null) {
+            if (mBpfTimesAvailable) {
+                readFreqsThroughBpf();
+            }
+            if (mCpuFreqs == null) {
+                final int oldMask = StrictMode.allowThreadDiskReadsMask();
+                try (BufferedReader reader = Files.newBufferedReader(mProcFilePath)) {
+                    if (readFreqs(reader.readLine()) == null) {
+                        return null;
+                    }
+                } catch (IOException e) {
+                    if (++mErrors >= MAX_ERROR_COUNT) {
+                        mAllUidTimesAvailable = false;
+                    }
+                    Slog.e(mTag, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
                     return null;
+                } finally {
+                    StrictMode.setThreadPolicyMask(oldMask);
                 }
-            } catch (IOException e) {
-                if (++mErrors >= MAX_ERROR_COUNT) {
-                    mAllUidTimesAvailable = false;
-                }
-                Slog.e(mTag, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
-                return null;
-            } finally {
-                StrictMode.setThreadPolicyMask(oldMask);
             }
             // Check if the freqs in the proc file correspond to per-cluster freqs.
             final IntArray numClusterFreqs = extractClusterInfoFromProcFileFreqs();
@@ -402,6 +420,21 @@
             return mCpuFreqs;
         }
 
+        private long[] readFreqsThroughBpf() {
+            if (!mBpfTimesAvailable || mBpfReader == null) {
+                return null;
+            }
+            mCpuFreqs = mBpfReader.getDataDimensions();
+            if (mCpuFreqs == null) {
+                return null;
+            }
+            mFreqCount = mCpuFreqs.length;
+            mCurTimes = new long[mFreqCount];
+            mDeltaTimes = new long[mFreqCount];
+            mBuffer = new long[mFreqCount + 1];
+            return mCpuFreqs;
+        }
+
         private long[] readFreqs(String line) {
             if (line == null || line.trim().isEmpty()) {
                 return null;
@@ -422,8 +455,45 @@
             return mCpuFreqs;
         }
 
+        private void processUidDelta(@Nullable Callback<long[]> cb) {
+            final int uid = (int) mBuffer[0];
+            long[] lastTimes = mLastTimes.get(uid);
+            if (lastTimes == null) {
+                lastTimes = new long[mFreqCount];
+                mLastTimes.put(uid, lastTimes);
+            }
+            copyToCurTimes();
+            boolean notify = false;
+            boolean valid = true;
+            for (int i = 0; i < mFreqCount; i++) {
+                // Unit is 10ms.
+                mDeltaTimes[i] = mCurTimes[i] - lastTimes[i];
+                if (mDeltaTimes[i] < 0) {
+                    Slog.e(mTag, "Negative delta from freq time proc: " + mDeltaTimes[i]);
+                    valid = false;
+                }
+                notify |= mDeltaTimes[i] > 0;
+            }
+            if (notify && valid) {
+                System.arraycopy(mCurTimes, 0, lastTimes, 0, mFreqCount);
+                if (cb != null) {
+                    cb.onUidCpuTime(uid, mDeltaTimes);
+                }
+            }
+        }
+
         @Override
         void readDeltaImpl(@Nullable Callback<long[]> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            processUidDelta(cb);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -434,36 +504,24 @@
                         Slog.wtf(mTag, "Invalid line: " + buf.toString());
                         continue;
                     }
-                    final int uid = (int) mBuffer[0];
-                    long[] lastTimes = mLastTimes.get(uid);
-                    if (lastTimes == null) {
-                        lastTimes = new long[mFreqCount];
-                        mLastTimes.put(uid, lastTimes);
-                    }
-                    copyToCurTimes();
-                    boolean notify = false;
-                    boolean valid = true;
-                    for (int i = 0; i < mFreqCount; i++) {
-                        // Unit is 10ms.
-                        mDeltaTimes[i] = mCurTimes[i] - lastTimes[i];
-                        if (mDeltaTimes[i] < 0) {
-                            Slog.e(mTag, "Negative delta from freq time proc: " + mDeltaTimes[i]);
-                            valid = false;
-                        }
-                        notify |= mDeltaTimes[i] > 0;
-                    }
-                    if (notify && valid) {
-                        System.arraycopy(mCurTimes, 0, lastTimes, 0, mFreqCount);
-                        if (cb != null) {
-                            cb.onUidCpuTime(uid, mDeltaTimes);
-                        }
-                    }
+                    processUidDelta(cb);
                 }
             }
         }
 
         @Override
         void readAbsoluteImpl(Callback<long[]> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            copyToCurTimes();
+                            cb.onUidCpuTime((int) mBuffer[0], mCurTimes);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -481,11 +539,24 @@
         }
 
         private void copyToCurTimes() {
+            long factor = mBpfTimesAvailable ? 1 : 10;
             for (int i = 0; i < mFreqCount; i++) {
-                mCurTimes[i] = mBuffer[i + 1] * 10;
+                mCurTimes[i] = mBuffer[i + 1] * factor;
             }
         }
 
+        private boolean checkPrecondition(BpfMapIterator iter) {
+            if (iter == null) {
+                mBpfTimesAvailable = false;
+                return false;
+            }
+            if (mCpuFreqs != null) {
+                return true;
+            }
+            mBpfTimesAvailable = (readFreqsThroughBpf() != null);
+            return mBpfTimesAvailable;
+        }
+
         private boolean checkPrecondition(ProcFileIterator iter) {
             if (iter == null || !iter.hasNextLine()) {
                 // Error logged in KernelCpuProcStringReader.
@@ -544,16 +615,43 @@
         private long[] mBuffer;
 
         public KernelCpuUidActiveTimeReader(boolean throttle) {
-            super(KernelCpuProcStringReader.getActiveTimeReaderInstance(), throttle);
+            super(KernelCpuProcStringReader.getActiveTimeReaderInstance(),
+                  KernelCpuUidBpfMapReader.getActiveTimeReaderInstance(), throttle);
         }
 
         @VisibleForTesting
-        public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
-            super(reader, throttle);
+        public KernelCpuUidActiveTimeReader(KernelCpuProcStringReader reader, KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
+            super(reader, bpfReader, throttle);
+        }
+
+        private void processUidDelta(@Nullable Callback<Long> cb) {
+            int uid = (int) mBuffer[0];
+            long cpuActiveTime = sumActiveTime(mBuffer, mBpfTimesAvailable ? 1 : 10);
+            if (cpuActiveTime > 0) {
+                long delta = cpuActiveTime - mLastTimes.get(uid, 0L);
+                if (delta > 0) {
+                    mLastTimes.put(uid, cpuActiveTime);
+                    if (cb != null) {
+                        cb.onUidCpuTime(uid, delta);
+                    }
+                } else if (delta < 0) {
+                    Slog.e(mTag, "Negative delta from active time proc: " + delta);
+                }
+            }
         }
 
         @Override
         void readDeltaImpl(@Nullable Callback<Long> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            processUidDelta(cb);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -564,25 +662,30 @@
                         Slog.wtf(mTag, "Invalid line: " + buf.toString());
                         continue;
                     }
-                    int uid = (int) mBuffer[0];
-                    long cpuActiveTime = sumActiveTime(mBuffer);
-                    if (cpuActiveTime > 0) {
-                        long delta = cpuActiveTime - mLastTimes.get(uid, 0L);
-                        if (delta > 0) {
-                            mLastTimes.put(uid, cpuActiveTime);
-                            if (cb != null) {
-                                cb.onUidCpuTime(uid, delta);
-                            }
-                        } else if (delta < 0) {
-                            Slog.e(mTag, "Negative delta from active time proc: " + delta);
-                        }
-                    }
+                    processUidDelta(cb);
                 }
             }
         }
 
+        private void processUidAbsolute(@Nullable Callback<Long> cb) {
+            long cpuActiveTime = sumActiveTime(mBuffer, mBpfTimesAvailable ? 1 : 10);
+            if (cpuActiveTime > 0) {
+                cb.onUidCpuTime((int) mBuffer[0], cpuActiveTime);
+            }
+        }
+
         @Override
         void readAbsoluteImpl(Callback<Long> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            processUidAbsolute(cb);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -593,23 +696,38 @@
                         Slog.wtf(mTag, "Invalid line: " + buf.toString());
                         continue;
                     }
-                    long cpuActiveTime = sumActiveTime(mBuffer);
-                    if (cpuActiveTime > 0) {
-                        cb.onUidCpuTime((int) mBuffer[0], cpuActiveTime);
-                    }
+                    processUidAbsolute(cb);
                 }
             }
         }
 
-        private static long sumActiveTime(long[] times) {
+        private static long sumActiveTime(long[] times, double factor) {
             // UID is stored at times[0].
             double sum = 0;
             for (int i = 1; i < times.length; i++) {
-                sum += (double) times[i] * 10 / i; // Unit is 10ms.
+                sum += (double) times[i] * factor / i; // Unit is 10ms.
             }
             return (long) sum;
         }
 
+        private boolean checkPrecondition(BpfMapIterator iter) {
+            if (iter == null) {
+                mBpfTimesAvailable = false;
+                return false;
+            }
+            if (mCores > 0) {
+                return true;
+            }
+            long[] cores = mBpfReader.getDataDimensions();
+            if (cores == null || cores.length < 1) {
+                mBpfTimesAvailable = false;
+                return false;
+            }
+            mCores = (int) cores[0];
+            mBuffer = new long[mCores + 1];
+            return true;
+        }
+
         private boolean checkPrecondition(ProcFileIterator iter) {
             if (iter == null || !iter.hasNextLine()) {
                 // Error logged in KernelCpuProcStringReader.
@@ -668,16 +786,54 @@
         private long[] mDeltaTime;
 
         public KernelCpuUidClusterTimeReader(boolean throttle) {
-            super(KernelCpuProcStringReader.getClusterTimeReaderInstance(), throttle);
+            super(KernelCpuProcStringReader.getClusterTimeReaderInstance(),
+                  KernelCpuUidBpfMapReader.getClusterTimeReaderInstance(), throttle);
         }
 
         @VisibleForTesting
-        public KernelCpuUidClusterTimeReader(KernelCpuProcStringReader reader, boolean throttle) {
-            super(reader, throttle);
+        public KernelCpuUidClusterTimeReader(KernelCpuProcStringReader reader,
+                                             KernelCpuUidBpfMapReader bpfReader, boolean throttle) {
+            super(reader, bpfReader, throttle);
+        }
+
+        void processUidDelta(@Nullable Callback<long[]> cb) {
+            int uid = (int) mBuffer[0];
+            long[] lastTimes = mLastTimes.get(uid);
+            if (lastTimes == null) {
+                lastTimes = new long[mNumClusters];
+                mLastTimes.put(uid, lastTimes);
+            }
+            sumClusterTime();
+            boolean valid = true;
+            boolean notify = false;
+            for (int i = 0; i < mNumClusters; i++) {
+                mDeltaTime[i] = mCurTime[i] - lastTimes[i];
+                if (mDeltaTime[i] < 0) {
+                    Slog.e(mTag, "Negative delta from cluster time proc: " + mDeltaTime[i]);
+                    valid = false;
+                }
+                notify |= mDeltaTime[i] > 0;
+            }
+            if (notify && valid) {
+                System.arraycopy(mCurTime, 0, lastTimes, 0, mNumClusters);
+                if (cb != null) {
+                    cb.onUidCpuTime(uid, mDeltaTime);
+                }
+            }
         }
 
         @Override
         void readDeltaImpl(@Nullable Callback<long[]> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            processUidDelta(cb);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -688,35 +844,24 @@
                         Slog.wtf(mTag, "Invalid line: " + buf.toString());
                         continue;
                     }
-                    int uid = (int) mBuffer[0];
-                    long[] lastTimes = mLastTimes.get(uid);
-                    if (lastTimes == null) {
-                        lastTimes = new long[mNumClusters];
-                        mLastTimes.put(uid, lastTimes);
-                    }
-                    sumClusterTime();
-                    boolean valid = true;
-                    boolean notify = false;
-                    for (int i = 0; i < mNumClusters; i++) {
-                        mDeltaTime[i] = mCurTime[i] - lastTimes[i];
-                        if (mDeltaTime[i] < 0) {
-                            Slog.e(mTag, "Negative delta from cluster time proc: " + mDeltaTime[i]);
-                            valid = false;
-                        }
-                        notify |= mDeltaTime[i] > 0;
-                    }
-                    if (notify && valid) {
-                        System.arraycopy(mCurTime, 0, lastTimes, 0, mNumClusters);
-                        if (cb != null) {
-                            cb.onUidCpuTime(uid, mDeltaTime);
-                        }
-                    }
+                    processUidDelta(cb);
                 }
             }
         }
 
         @Override
         void readAbsoluteImpl(Callback<long[]> cb) {
+            if (mBpfTimesAvailable) {
+                try (BpfMapIterator iter = mBpfReader.open(!mThrottle)) {
+                    if (checkPrecondition(iter)) {
+                        while (iter.getNextUid(mBuffer)) {
+                            sumClusterTime();
+                            cb.onUidCpuTime((int) mBuffer[0], mCurTime);
+                        }
+                        return;
+                    }
+                }
+            }
             try (ProcFileIterator iter = mReader.open(!mThrottle)) {
                 if (!checkPrecondition(iter)) {
                     return;
@@ -734,17 +879,45 @@
         }
 
         private void sumClusterTime() {
+            double factor = mBpfTimesAvailable ? 1 : 10;
             // UID is stored at mBuffer[0].
             int core = 1;
             for (int i = 0; i < mNumClusters; i++) {
                 double sum = 0;
                 for (int j = 1; j <= mCoresOnClusters[i]; j++) {
-                    sum += (double) mBuffer[core++] * 10 / j; // Unit is 10ms.
+                    sum += (double) mBuffer[core++] * factor / j; // Unit is 10ms.
                 }
                 mCurTime[i] = (long) sum;
             }
         }
 
+        private boolean checkPrecondition(BpfMapIterator iter) {
+            if (iter == null) {
+                mBpfTimesAvailable = false;
+                return false;
+            }
+            if (mNumClusters > 0) {
+                return true;
+            }
+            long[] coresOnClusters = mBpfReader.getDataDimensions();
+            if (coresOnClusters == null || coresOnClusters.length < 1) {
+                mBpfTimesAvailable = false;
+                return false;
+            }
+            mNumClusters = coresOnClusters.length;
+            mCoresOnClusters = new int[mNumClusters];
+            int cores = 0;
+            for (int i = 0; i < mNumClusters; i++) {
+                mCoresOnClusters[i] = (int) coresOnClusters[i];
+                cores += mCoresOnClusters[i];
+            }
+            mNumCores = cores;
+            mBuffer = new long[cores + 1];
+            mCurTime = new long[mNumClusters];
+            mDeltaTime = new long[mNumClusters];
+            return true;
+        }
+
         private boolean checkPrecondition(ProcFileIterator iter) {
             if (iter == null || !iter.hasNextLine()) {
                 // Error logged in KernelCpuProcStringReader.
diff --git a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
index 3c43a11..fc0ce6f 100644
--- a/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
+++ b/core/java/com/android/internal/os/KernelSingleUidTimeReader.java
@@ -53,6 +53,8 @@
     private int mReadErrorCounter;
     @GuardedBy("this")
     private boolean mSingleUidCpuTimesAvailable = true;
+    @GuardedBy("this")
+    private boolean mBpfTimesAvailable = true;
     // We use the freq count obtained from /proc/uid_time_in_state to decide how many longs
     // to read from each /proc/uid/<uid>/time_in_state. On the first read, verify if this is
     // correct and if not, set {@link #mSingleUidCpuTimesAvailable} to false. This flag will
@@ -62,6 +64,8 @@
 
     private final Injector mInjector;
 
+    private static final native boolean canReadBpfTimes();
+
     KernelSingleUidTimeReader(int cpuFreqsCount) {
         this(cpuFreqsCount, new Injector());
     }
@@ -83,6 +87,18 @@
             if (!mSingleUidCpuTimesAvailable) {
                 return null;
             }
+            if (mBpfTimesAvailable) {
+                final long[] cpuTimesMs = mInjector.readBpfData(uid);
+                if (cpuTimesMs.length == 0) {
+                    mBpfTimesAvailable = false;
+                } else if (!mCpuFreqsCountVerified && cpuTimesMs.length != mCpuFreqsCount) {
+                    mSingleUidCpuTimesAvailable = false;
+                    return null;
+                } else {
+                    mCpuFreqsCountVerified = true;
+                    return computeDelta(uid, cpuTimesMs);
+                }
+            }
             // Read total cpu times from the proc file.
             final String procFile = new StringBuilder(PROC_FILE_DIR)
                     .append(uid)
@@ -230,6 +246,8 @@
         public byte[] readData(String procFile) throws IOException {
             return Files.readAllBytes(Paths.get(procFile));
         }
+
+        public native long[] readBpfData(int uid);
     }
 
     @VisibleForTesting
diff --git a/core/java/com/android/internal/os/PowerProfile.java b/core/java/com/android/internal/os/PowerProfile.java
index 3db8f4e..add2304 100644
--- a/core/java/com/android/internal/os/PowerProfile.java
+++ b/core/java/com/android/internal/os/PowerProfile.java
@@ -393,6 +393,9 @@
     }
 
     public int getNumCoresInCpuCluster(int cluster) {
+        if (cluster < 0 || cluster >= mCpuClusters.length) {
+            return 0; // index out of bound
+        }
         return mCpuClusters[cluster].numCpus;
     }
 
diff --git a/core/java/com/android/internal/os/TEST_MAPPING b/core/java/com/android/internal/os/TEST_MAPPING
new file mode 100644
index 0000000..f44b9fb
--- /dev/null
+++ b/core/java/com/android/internal/os/TEST_MAPPING
@@ -0,0 +1,30 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksCoreTests",
+      "options": [
+        {
+          "include-filter": "com.android.internal.os.KernelCpuUidFreqTimeReaderTest"
+        },
+        {
+          "include-filter": "com.android.internal.os.KernelCpuUidActiveTimeReaderTest"
+        },
+        {
+          "include-filter": "com.android.internal.os.KernelCpuUidClusterTimeReaderTest"
+        },
+        {
+          "include-filter": "com.android.internal.os.KernelSingleUidTimeReaderTest"
+        },
+        {
+          "include-filter": "com.android.internal.os.KernelCpuUidBpfMapReaderTest"
+        }
+
+      ],
+      "file_patterns": [
+        "KernelCpuUidTimeReader\\.java",
+        "KernelCpuUidBpfMapReader\\.java",
+        "KernelSingleUidTimeReader\\.java"
+      ]
+    }
+  ]
+}
diff --git a/core/java/com/android/internal/policy/DockedDividerUtils.java b/core/java/com/android/internal/policy/DockedDividerUtils.java
index c68e506..b61b9de 100644
--- a/core/java/com/android/internal/policy/DockedDividerUtils.java
+++ b/core/java/com/android/internal/policy/DockedDividerUtils.java
@@ -16,14 +16,15 @@
 
 package com.android.internal.policy;
 
-import android.graphics.Rect;
-
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
 import static android.view.WindowManager.DOCKED_TOP;
 
+import android.content.res.Resources;
+import android.graphics.Rect;
+
 /**
  * Utility functions for docked stack divider used by both window manager and System UI.
  *
@@ -105,23 +106,6 @@
         return start + (end - start) / 2 - dividerSize / 2;
     }
 
-    public static int getDockSideFromCreatedMode(boolean dockOnTopOrLeft,
-            boolean isHorizontalDivision) {
-        if (dockOnTopOrLeft) {
-            if (isHorizontalDivision) {
-                return DOCKED_TOP;
-            } else {
-                return DOCKED_LEFT;
-            }
-        } else {
-            if (isHorizontalDivision) {
-                return DOCKED_BOTTOM;
-            } else {
-                return DOCKED_RIGHT;
-            }
-        }
-    }
-
     public static int invertDockSide(int dockSide) {
         switch (dockSide) {
             case DOCKED_LEFT:
@@ -136,4 +120,21 @@
                 return DOCKED_INVALID;
         }
     }
+
+    /** Returns the inset distance from the divider window edge to the dividerview. */
+    public static int getDividerInsets(Resources res) {
+        return res.getDimensionPixelSize(com.android.internal.R.dimen.docked_stack_divider_insets);
+    }
+
+    /** Returns the size of the divider */
+    public static int getDividerSize(Resources res, int dividerInsets) {
+        final int windowWidth = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_thickness);
+        return windowWidth - 2 * dividerInsets;
+    }
+
+    /** Returns the docked-stack side */
+    public static int getDockSide(int displayWidth, int displayHeight) {
+        return displayWidth > displayHeight ? DOCKED_LEFT : DOCKED_TOP;
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 775368b..24222d3 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -335,7 +335,7 @@
         super(context);
         mLayoutInflater = LayoutInflater.from(context);
         mRenderShadowsInCompositor = Settings.Global.getInt(context.getContentResolver(),
-                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0;
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 1) != 0;
     }
 
     /**
diff --git a/core/java/com/android/internal/util/CollectionUtils.java b/core/java/com/android/internal/util/CollectionUtils.java
index 4dac542..9b2bcfb 100644
--- a/core/java/com/android/internal/util/CollectionUtils.java
+++ b/core/java/com/android/internal/util/CollectionUtils.java
@@ -186,6 +186,17 @@
     }
 
     /**
+     * Returns the given map, or an immutable empty map if the provided map is null
+     *
+     * This can be used to guarantee null-safety without paying the price of extra allocations
+     *
+     * @see Collections#emptyMap
+     */
+    public static @NonNull <K, V> Map<K, V> emptyIfNull(@Nullable Map<K, V> cur) {
+        return cur == null ? Collections.emptyMap() : cur;
+    }
+
+    /**
      * Returns the size of the given collection, or 0 if null
      */
     public static int size(@Nullable Collection<?> cur) {
@@ -297,6 +308,33 @@
     }
 
     /**
+     * Similar to {@link List#add(int, Object)}, but with support for list values of {@code null}
+     * and {@link Collections#emptyList}
+     */
+    public static @NonNull <T> List<T> add(@Nullable List<T> cur, int index, T val) {
+        if (cur == null || cur == Collections.emptyList()) {
+            cur = new ArrayList<>();
+        }
+        cur.add(index, val);
+        return cur;
+    }
+
+    /**
+     * Similar to {@link Set#addAll(Collection)}}, but with support for list values of {@code null}
+     * and {@link Collections#emptySet}
+     */
+    public static @NonNull <T> Set<T> addAll(@Nullable Set<T> cur, @Nullable Collection<T> val) {
+        if (isEmpty(val)) {
+            return cur != null ? cur : Collections.emptySet();
+        }
+        if (cur == null || cur == Collections.emptySet()) {
+            cur = new ArraySet<>();
+        }
+        cur.addAll(val);
+        return cur;
+    }
+
+    /**
      * @see #add(List, Object)
      */
     public static @NonNull <T> Set<T> add(@Nullable Set<T> cur, T val) {
diff --git a/core/java/com/android/internal/util/Parcelling.java b/core/java/com/android/internal/util/Parcelling.java
index 390c596..6258a69 100644
--- a/core/java/com/android/internal/util/Parcelling.java
+++ b/core/java/com/android/internal/util/Parcelling.java
@@ -15,10 +15,18 @@
  */
 package com.android.internal.util;
 
+import static java.util.Collections.emptySet;
+
 import android.annotation.Nullable;
 import android.os.Parcel;
+import android.text.TextUtils;
 import android.util.ArrayMap;
+import android.util.ArraySet;
 
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 /**
@@ -90,6 +98,132 @@
      */
     interface BuiltIn {
 
+        class ForInternedString implements Parcelling<String> {
+            @Override
+            public void parcel(@Nullable String item, Parcel dest, int parcelFlags) {
+                dest.writeString(item);
+            }
+
+            @Nullable
+            @Override
+            public String unparcel(Parcel source) {
+                return TextUtils.safeIntern(source.readString());
+            }
+        }
+
+        class ForInternedStringArray implements Parcelling<String[]> {
+            @Override
+            public void parcel(String[] item, Parcel dest, int parcelFlags) {
+                dest.writeStringArray(item);
+            }
+
+            @Nullable
+            @Override
+            public String[] unparcel(Parcel source) {
+                String[] array = source.readStringArray();
+                if (array != null) {
+                    int size = ArrayUtils.size(array);
+                    for (int index = 0; index < size; index++) {
+                        array[index] = TextUtils.safeIntern(array[index]);
+                    }
+                }
+                return array;
+            }
+        }
+
+        class ForInternedStringList implements Parcelling<List<String>> {
+            @Override
+            public void parcel(List<String> item, Parcel dest, int parcelFlags) {
+                dest.writeStringList(item);
+            }
+
+            @Override
+            public List<String> unparcel(Parcel source) {
+                ArrayList<String> list = source.createStringArrayList();
+                if (list != null) {
+                    int size = list.size();
+                    for (int index = 0; index < size; index++) {
+                        list.set(index, list.get(index).intern());
+                    }
+                }
+                return CollectionUtils.emptyIfNull(list);
+            }
+        }
+
+        class ForInternedStringValueMap implements Parcelling<Map<String, String>> {
+            @Override
+            public void parcel(Map<String, String> item, Parcel dest, int parcelFlags) {
+                dest.writeMap(item);
+            }
+
+            @Override
+            public Map<String, String> unparcel(Parcel source) {
+                ArrayMap<String, String> map = new ArrayMap<>();
+                source.readMap(map, String.class.getClassLoader());
+                for (int index = 0; index < map.size(); index++) {
+                    map.setValueAt(index, TextUtils.safeIntern(map.valueAt(index)));
+                }
+                return map;
+            }
+        }
+
+        class ForInternedStringSet implements Parcelling<Set<String>> {
+            @Override
+            public void parcel(Set<String> item, Parcel dest, int parcelFlags) {
+                if (item == null) {
+                    dest.writeInt(-1);
+                } else {
+                    dest.writeInt(item.size());
+                    for (String string : item) {
+                        dest.writeString(string);
+                    }
+                }
+            }
+
+            @Override
+            public Set<String> unparcel(Parcel source) {
+                final int size = source.readInt();
+                if (size < 0) {
+                    return emptySet();
+                }
+                Set<String> set = new ArraySet<>();
+                for (int count = 0; count < size; count++) {
+                    set.add(TextUtils.safeIntern(source.readString()));
+                }
+                return set;
+            }
+        }
+
+        class ForBoolean implements Parcelling<Boolean> {
+            @Override
+            public void parcel(@Nullable Boolean item, Parcel dest, int parcelFlags) {
+                if (item == null) {
+                    // This writes 1 for null to mirror TypedArray.getInteger(booleanResId, 1)
+                    dest.writeInt(1);
+                } else if (!item) {
+                    dest.writeInt(0);
+                } else {
+                    dest.writeInt(-1);
+                }
+            }
+
+            @Nullable
+            @Override
+            public Boolean unparcel(Parcel source) {
+                switch (source.readInt()) {
+                    default:
+                        throw new IllegalStateException("Malformed Parcel reading Boolean: "
+                                + source);
+                    case 1:
+                        return null;
+                    case 0:
+                        return Boolean.FALSE;
+                    case -1:
+                        return Boolean.TRUE;
+                }
+            }
+        }
+
         class ForPattern implements Parcelling<Pattern> {
 
             @Override
diff --git a/core/java/com/android/internal/util/function/LongObjPredicate.java b/core/java/com/android/internal/util/function/LongObjPredicate.java
new file mode 100644
index 0000000..9e46307
--- /dev/null
+++ b/core/java/com/android/internal/util/function/LongObjPredicate.java
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+package com.android.internal.util.function;
+
+/**
+ * Represents a predicate (boolean-valued function) of a {@code long}-valued argument
+ * and an object-valued argument.
+ *
+ * @param <T> the type of the object-valued argument to the predicate
+ */
+@FunctionalInterface
+public interface LongObjPredicate<T> {
+    /**
+     * Evaluates this predicate on the given arguments.
+     *
+     * @param value the first input argument
+     * @param t the second input argument
+     * @return {@code true} if the input arguments match the predicate,
+     *         otherwise {@code false}
+     */
+    boolean test(long value, T t);
+}
diff --git a/core/java/com/android/internal/view/FloatingActionMode.java b/core/java/com/android/internal/view/FloatingActionMode.java
index 69b1609..633d684 100644
--- a/core/java/com/android/internal/view/FloatingActionMode.java
+++ b/core/java/com/android/internal/view/FloatingActionMode.java
@@ -210,7 +210,7 @@
     }
 
     private boolean isContentRectWithinBounds() {
-        mContext.getDisplay().getRealSize(mDisplaySize);
+        mContext.getDisplayNoVerify().getRealSize(mDisplaySize);
         mScreenRect.set(0, 0, mDisplaySize.x, mDisplaySize.y);
 
         return intersectsClosed(mContentRectOnScreen, mScreenRect)
diff --git a/core/java/com/android/internal/view/IInputMethod.aidl b/core/java/com/android/internal/view/IInputMethod.aidl
index 475a321..fd4b5ab 100644
--- a/core/java/com/android/internal/view/IInputMethod.aidl
+++ b/core/java/com/android/internal/view/IInputMethod.aidl
@@ -16,10 +16,8 @@
 
 package com.android.internal.view;
 
-import android.content.ComponentName;
 import android.os.IBinder;
 import android.os.ResultReceiver;
-import android.view.autofill.AutofillId;
 import android.view.InputChannel;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputBinding;
@@ -29,6 +27,7 @@
 import com.android.internal.view.IInputContext;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 
 /**
  * Top-level interface to an input method component (implemented in a
@@ -38,7 +37,7 @@
 oneway interface IInputMethod {
     void initializeInternal(IBinder token, int displayId, IInputMethodPrivilegedOperations privOps);
 
-    void onCreateInlineSuggestionsRequest(in ComponentName componentName, in AutofillId autofillId,
+    void onCreateInlineSuggestionsRequest(in InlineSuggestionsRequestInfo requestInfo,
             in IInlineSuggestionsRequestCallback cb);
 
     void bindInput(in InputBinding binding);
diff --git a/core/java/com/android/internal/view/IInputMethodClient.aidl b/core/java/com/android/internal/view/IInputMethodClient.aidl
index 41f902e..4509032 100644
--- a/core/java/com/android/internal/view/IInputMethodClient.aidl
+++ b/core/java/com/android/internal/view/IInputMethodClient.aidl
@@ -28,6 +28,7 @@
     void onBindMethod(in InputBindResult res);
     void onUnbindMethod(int sequence, int unbindReason);
     void setActive(boolean active, boolean fullscreen);
+    void scheduleStartInputIfNecessary(boolean fullscreen);
     void reportFullscreenMode(boolean fullscreen);
     void reportPreRendered(in EditorInfo info);
     void applyImeVisibility(boolean setVisible);
diff --git a/core/java/android/service/controls/IControlsLoadCallback.aidl b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.aidl
similarity index 62%
copy from core/java/android/service/controls/IControlsLoadCallback.aidl
copy to core/java/com/android/internal/view/InlineSuggestionsRequestInfo.aidl
index bfc61cd..8125c0d 100644
--- a/core/java/android/service/controls/IControlsLoadCallback.aidl
+++ b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2020, The Android Open Source Project
+ * 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
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,13 +14,6 @@
  * limitations under the License.
  */
 
-package android.service.controls;
+package com.android.internal.view;
 
-import android.service.controls.Control;
-
-/**
- * @hide
- */
-oneway interface IControlsLoadCallback {
-    void accept(in IBinder token, in List<Control> controls);
-}
\ No newline at end of file
+parcelable InlineSuggestionsRequestInfo;
diff --git a/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.java b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.java
new file mode 100644
index 0000000..6148490
--- /dev/null
+++ b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.java
@@ -0,0 +1,229 @@
+/*
+ * 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.internal.view;
+
+import android.annotation.NonNull;
+import android.content.ComponentName;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.view.autofill.AutofillId;
+import android.view.inputmethod.InlineSuggestionsRequest;
+
+import com.android.internal.util.DataClass;
+
+/**
+ * Wraps the information needed to create an {@link InlineSuggestionsRequest}.
+ *
+ * @hide
+ */
+@DataClass(
+        genToString = true,
+        genHiddenConstDefs = true,
+        genEqualsHashCode = true)
+public final class InlineSuggestionsRequestInfo implements Parcelable {
+    /**
+     * The {@link ComponentName} of current app/activity
+     */
+    private final @NonNull ComponentName mComponentName;
+
+    /**
+     * The {@link AutofillId} of currently focused field.
+     */
+    private final @NonNull AutofillId mAutofillId;
+
+    /**
+     * The extras that contain the UI renderer related information
+     */
+    private final @NonNull Bundle mUiExtras;
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    /**
+     * Creates a new InlineSuggestionsRequestInfo.
+     *
+     * @param componentName
+     *   The {@link ComponentName} of current app/activity
+     * @param autofillId
+     *   The {@link AutofillId} of currently focused field.
+     * @param uiExtras
+     *   The extras that contain the ui renderer related information
+     */
+    @DataClass.Generated.Member
+    public InlineSuggestionsRequestInfo(
+            @NonNull ComponentName componentName,
+            @NonNull AutofillId autofillId,
+            @NonNull Bundle uiExtras) {
+        this.mComponentName = componentName;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mComponentName);
+        this.mAutofillId = autofillId;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAutofillId);
+        this.mUiExtras = uiExtras;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mUiExtras);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    /**
+     * The {@link ComponentName} of current app/activity
+     */
+    @DataClass.Generated.Member
+    public @NonNull ComponentName getComponentName() {
+        return mComponentName;
+    }
+
+    /**
+     * The {@link AutofillId} of currently focused field.
+     */
+    @DataClass.Generated.Member
+    public @NonNull AutofillId getAutofillId() {
+        return mAutofillId;
+    }
+
+    /**
+     * The extras that contain the ui renderer related information
+     */
+    @DataClass.Generated.Member
+    public @NonNull Bundle getUiExtras() {
+        return mUiExtras;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public String toString() {
+        // You can override field toString logic by defining methods like:
+        // String fieldNameToString() { ... }
+
+        return "InlineSuggestionsRequestInfo { " +
+                "componentName = " + mComponentName + ", " +
+                "autofillId = " + mAutofillId + ", " +
+                "uiExtras = " + mUiExtras +
+        " }";
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(@android.annotation.Nullable Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(InlineSuggestionsRequestInfo other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        InlineSuggestionsRequestInfo that = (InlineSuggestionsRequestInfo) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && java.util.Objects.equals(mComponentName, that.mComponentName)
+                && java.util.Objects.equals(mAutofillId, that.mAutofillId)
+                && java.util.Objects.equals(mUiExtras, that.mUiExtras);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + java.util.Objects.hashCode(mComponentName);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mAutofillId);
+        _hash = 31 * _hash + java.util.Objects.hashCode(mUiExtras);
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(@NonNull android.os.Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeTypedObject(mComponentName, flags);
+        dest.writeTypedObject(mAutofillId, flags);
+        dest.writeBundle(mUiExtras);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    /** @hide */
+    @SuppressWarnings({"unchecked", "RedundantCast"})
+    @DataClass.Generated.Member
+    /* package-private */ InlineSuggestionsRequestInfo(@NonNull android.os.Parcel in) {
+        // You can override field unparcelling by defining methods like:
+        // static FieldType unparcelFieldName(Parcel in) { ... }
+
+        ComponentName componentName = (ComponentName) in.readTypedObject(ComponentName.CREATOR);
+        AutofillId autofillId = (AutofillId) in.readTypedObject(AutofillId.CREATOR);
+        Bundle uiExtras = in.readBundle();
+
+        this.mComponentName = componentName;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mComponentName);
+        this.mAutofillId = autofillId;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mAutofillId);
+        this.mUiExtras = uiExtras;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mUiExtras);
+
+        // onConstructed(); // You can define this method to get a callback
+    }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<InlineSuggestionsRequestInfo> CREATOR
+            = new Parcelable.Creator<InlineSuggestionsRequestInfo>() {
+        @Override
+        public InlineSuggestionsRequestInfo[] newArray(int size) {
+            return new InlineSuggestionsRequestInfo[size];
+        }
+
+        @Override
+        public InlineSuggestionsRequestInfo createFromParcel(@NonNull android.os.Parcel in) {
+            return new InlineSuggestionsRequestInfo(in);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1582076613213L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.java",
+            inputSignatures = "private final @android.annotation.NonNull android.content.ComponentName mComponentName\nprivate final @android.annotation.NonNull android.view.autofill.AutofillId mAutofillId\nprivate final @android.annotation.NonNull android.os.Bundle mUiExtras\nclass InlineSuggestionsRequestInfo extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genToString=true, genHiddenConstDefs=true, genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/com/android/internal/view/InputBindResult.java b/core/java/com/android/internal/view/InputBindResult.java
index a5964b5..f29e95c 100644
--- a/core/java/com/android/internal/view/InputBindResult.java
+++ b/core/java/com/android/internal/view/InputBindResult.java
@@ -89,57 +89,64 @@
          */
         int SUCCESS_WAITING_IME_BINDING = 2;
         /**
+         * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService} has a
+         * pending operation to switch to a different user.
+         *
+         * <p>Note that in this state even what would be the next current IME is not determined.</p>
+         */
+        int SUCCESS_WAITING_USER_SWITCHING = 3;
+        /**
          * Indicates that this is not intended for starting input but just for reporting window
          * focus change from the application process.
          *
          * <p>All other fields do not have meaningful value.</p>
          */
-        int SUCCESS_REPORT_WINDOW_FOCUS_ONLY = 3;
+        int SUCCESS_REPORT_WINDOW_FOCUS_ONLY = 4;
         /**
          * Indicates somehow
          * {@link
          * com.android.server.inputmethod.InputMethodManagerService#startInputOrWindowGainedFocus}
          * is trying to return null {@link InputBindResult}, which must never happen.
          */
-        int ERROR_NULL = 4;
+        int ERROR_NULL = 5;
         /**
          * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService}
          * recognizes no IME.
          */
-        int ERROR_NO_IME = 5;
+        int ERROR_NO_IME = 6;
         /**
          * Indicates that {@link android.view.inputmethod.EditorInfo#packageName} does not match
          * the caller UID.
          *
          * @see android.view.inputmethod.EditorInfo#packageName
          */
-        int ERROR_INVALID_PACKAGE_NAME = 6;
+        int ERROR_INVALID_PACKAGE_NAME = 7;
         /**
          * Indicates that the system is still in an early stage of the boot process and any 3rd
          * party application is not allowed to run.
          *
          * @see com.android.server.SystemService#PHASE_THIRD_PARTY_APPS_CAN_START
          */
-        int ERROR_SYSTEM_NOT_READY = 7;
+        int ERROR_SYSTEM_NOT_READY = 8;
         /**
          * Indicates that {@link com.android.server.inputmethod.InputMethodManagerService} tried to
          * connect to an {@link android.inputmethodservice.InputMethodService} but failed.
          *
          * @see android.content.Context#bindServiceAsUser(Intent, ServiceConnection, int, UserHandle)
          */
-        int ERROR_IME_NOT_CONNECTED = 8;
+        int ERROR_IME_NOT_CONNECTED = 9;
         /**
          * Indicates that the caller is not the foreground user, does not have
          * {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL} permission, or the user
          * specified in {@link android.view.inputmethod.EditorInfo#targetInputMethodUser} is not
          * running.
          */
-        int ERROR_INVALID_USER = 9;
+        int ERROR_INVALID_USER = 10;
         /**
          * Indicates that the caller should have specified non-null
          * {@link android.view.inputmethod.EditorInfo}.
          */
-        int ERROR_NULL_EDITOR_INFO = 10;
+        int ERROR_NULL_EDITOR_INFO = 11;
         /**
          * Indicates that the target window the client specified cannot be the IME target right now.
          *
@@ -149,24 +156,24 @@
          *
          * @see com.android.server.wm.WindowManagerInternal#isInputMethodClientFocus(int, int, int)
          */
-        int ERROR_NOT_IME_TARGET_WINDOW = 11;
+        int ERROR_NOT_IME_TARGET_WINDOW = 12;
         /**
          * Indicates that focused view in the current window is not an editor.
          */
-        int ERROR_NO_EDITOR = 12;
+        int ERROR_NO_EDITOR = 13;
         /**
          * Indicates that there is a mismatch in display ID between IME client and focused Window.
          */
-        int ERROR_DISPLAY_ID_MISMATCH = 13;
+        int ERROR_DISPLAY_ID_MISMATCH = 14;
         /**
          * Indicates that current IME client is no longer allowed to access to the associated
          * display.
          */
-        int ERROR_INVALID_DISPLAY_ID = 14;
+        int ERROR_INVALID_DISPLAY_ID = 15;
         /**
          * Indicates that the client is not recognized by the system.
          */
-        int ERROR_INVALID_CLIENT = 15;
+        int ERROR_INVALID_CLIENT = 16;
     }
 
     @ResultCode
@@ -299,6 +306,8 @@
                 return "SUCCESS_WAITING_IME_SESSION";
             case ResultCode.SUCCESS_WAITING_IME_BINDING:
                 return "SUCCESS_WAITING_IME_BINDING";
+            case ResultCode.SUCCESS_WAITING_USER_SWITCHING:
+                return "SUCCESS_WAITING_USER_SWITCHING";
             case ResultCode.SUCCESS_REPORT_WINDOW_FOCUS_ONLY:
                 return "SUCCESS_REPORT_WINDOW_FOCUS_ONLY";
             case ResultCode.ERROR_NULL:
@@ -386,4 +395,11 @@
      * Predefined error object for {@link ResultCode#ERROR_INVALID_CLIENT}.
      */
     public static final InputBindResult INVALID_CLIENT = error(ResultCode.ERROR_INVALID_CLIENT);
+
+    /**
+     * Predefined <strong>success</strong> object for
+     * {@link ResultCode#SUCCESS_WAITING_USER_SWITCHING}.
+     */
+    public static final InputBindResult USER_SWITCHING =
+            error(ResultCode.SUCCESS_WAITING_USER_SWITCHING);
 }
diff --git a/core/java/com/android/internal/view/RotationPolicy.java b/core/java/com/android/internal/view/RotationPolicy.java
index 13425e5..cfb2bf9 100644
--- a/core/java/com/android/internal/view/RotationPolicy.java
+++ b/core/java/com/android/internal/view/RotationPolicy.java
@@ -77,10 +77,7 @@
             final Point size = new Point();
             final IWindowManager wm = WindowManagerGlobal.getWindowManagerService();
             try {
-                final Display display = context.getDisplay();
-                final int displayId = display != null
-                        ? display.getDisplayId()
-                        : Display.DEFAULT_DISPLAY;
+                final int displayId = context.getDisplayId();
                 wm.getInitialDisplaySize(displayId, size);
                 return size.x < size.y ?
                         Configuration.ORIENTATION_PORTRAIT : Configuration.ORIENTATION_LANDSCAPE;
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index e24e982..e35fda1 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -57,6 +57,8 @@
     void registerStrongAuthTracker(in IStrongAuthTracker tracker);
     void unregisterStrongAuthTracker(in IStrongAuthTracker tracker);
     void requireStrongAuth(int strongAuthReason, int userId);
+    void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId);
+    void scheduleNonStrongBiometricIdleTimeout(int userId);
     void systemReady();
     void userPresent(int userId);
     int getStrongAuthForUser(int userId);
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 864429c..d9b2902 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -49,6 +49,7 @@
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 import android.util.SparseLongArray;
 
@@ -1382,6 +1383,22 @@
         }
     }
 
+    public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
+        try {
+            getLockSettings().reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not report successful biometric unlock", e);
+        }
+    }
+
+    public void scheduleNonStrongBiometricIdleTimeout(int userId) {
+        try {
+            getLockSettings().scheduleNonStrongBiometricIdleTimeout(userId);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not schedule non-strong biometric idle timeout", e);
+        }
+    }
+
     /**
      * @see StrongAuthTracker#getStrongAuthForUser
      */
@@ -1557,7 +1574,8 @@
                         SOME_AUTH_REQUIRED_AFTER_USER_REQUEST,
                         STRONG_AUTH_REQUIRED_AFTER_LOCKOUT,
                         STRONG_AUTH_REQUIRED_AFTER_TIMEOUT,
-                        STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN})
+                        STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN,
+                        STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT})
         @Retention(RetentionPolicy.SOURCE)
         public @interface StrongAuthFlags {}
 
@@ -1604,6 +1622,12 @@
         public static final int STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE = 0x40;
 
         /**
+         * Strong authentication is required because it hasn't been used for a time after a
+         * non-strong biometric (i.e. weak or convenience biometric) is used to unlock device.
+         */
+        public static final int STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT = 0x80;
+
+        /**
          * Strong auth flags that do not prevent biometric methods from being accepted as auth.
          * If any other flags are set, biometric authentication is disabled.
          */
@@ -1614,6 +1638,10 @@
         private final H mHandler;
         private final int mDefaultStrongAuthFlags;
 
+        private final SparseBooleanArray mIsNonStrongBiometricAllowedForUser =
+                new SparseBooleanArray();
+        private final boolean mDefaultIsNonStrongBiometricAllowed = true;
+
         public StrongAuthTracker(Context context) {
             this(context, Looper.myLooper());
         }
@@ -1657,8 +1685,21 @@
          * @return true if unlocking with a biometric method alone is allowed for {@code userId}
          * by the current strong authentication requirements.
          */
-        public boolean isBiometricAllowedForUser(int userId) {
-            return (getStrongAuthForUser(userId) & ~ALLOWING_BIOMETRIC) == 0;
+        public boolean isBiometricAllowedForUser(boolean isStrongBiometric, int userId) {
+            boolean allowed = ((getStrongAuthForUser(userId) & ~ALLOWING_BIOMETRIC) == 0);
+            if (!isStrongBiometric) {
+                allowed &= isNonStrongBiometricAllowedAfterIdleTimeout(userId);
+            }
+            return allowed;
+        }
+
+        /**
+         * @return true if unlocking with a non-strong (i.e. weak or convenience) biometric method
+         * alone is allowed for {@code userId}, otherwise returns false.
+         */
+        public boolean isNonStrongBiometricAllowedAfterIdleTimeout(int userId) {
+            return mIsNonStrongBiometricAllowedForUser.get(userId,
+                    mDefaultIsNonStrongBiometricAllowed);
         }
 
         /**
@@ -1667,6 +1708,12 @@
         public void onStrongAuthRequiredChanged(int userId) {
         }
 
+        /**
+         * Called when whether non-strong biometric is allowed for {@code userId} changed.
+         */
+        public void onIsNonStrongBiometricAllowedChanged(int userId) {
+        }
+
         protected void handleStrongAuthRequiredChanged(@StrongAuthFlags int strongAuthFlags,
                 int userId) {
             int oldValue = getStrongAuthForUser(userId);
@@ -1680,6 +1727,18 @@
             }
         }
 
+        protected void handleIsNonStrongBiometricAllowedChanged(boolean allowed,
+                int userId) {
+            boolean oldValue = isNonStrongBiometricAllowedAfterIdleTimeout(userId);
+            if (allowed != oldValue) {
+                if (allowed == mDefaultIsNonStrongBiometricAllowed) {
+                    mIsNonStrongBiometricAllowedForUser.delete(userId);
+                } else {
+                    mIsNonStrongBiometricAllowedForUser.put(userId, allowed);
+                }
+                onIsNonStrongBiometricAllowedChanged(userId);
+            }
+        }
 
         protected final IStrongAuthTracker.Stub mStub = new IStrongAuthTracker.Stub() {
             @Override
@@ -1688,10 +1747,17 @@
                 mHandler.obtainMessage(H.MSG_ON_STRONG_AUTH_REQUIRED_CHANGED,
                         strongAuthFlags, userId).sendToTarget();
             }
+
+            @Override
+            public void onIsNonStrongBiometricAllowedChanged(boolean allowed, int userId) {
+                mHandler.obtainMessage(H.MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED,
+                        allowed ? 1 : 0, userId).sendToTarget();
+            }
         };
 
         private class H extends Handler {
             static final int MSG_ON_STRONG_AUTH_REQUIRED_CHANGED = 1;
+            static final int MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED = 2;
 
             public H(Looper looper) {
                 super(looper);
@@ -1703,6 +1769,10 @@
                     case MSG_ON_STRONG_AUTH_REQUIRED_CHANGED:
                         handleStrongAuthRequiredChanged(msg.arg1, msg.arg2);
                         break;
+                    case MSG_ON_IS_NON_STRONG_BIOMETRIC_ALLOWED_CHANGED:
+                        handleIsNonStrongBiometricAllowedChanged(msg.arg1 == 1 /* allowed */,
+                                msg.arg2);
+                        break;
                 }
             }
         }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 578c0cc..3378c07 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -1160,6 +1160,10 @@
             addFeature(PackageManager.FEATURE_INCREMENTAL_DELIVERY, 0);
         }
 
+        if (PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT) {
+            addFeature(PackageManager.FEATURE_APP_ENUMERATION, 0);
+        }
+
         for (String featureName : mUnavailableFeatures) {
             removeFeature(featureName);
         }
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 900445c..5912f40 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -153,7 +153,7 @@
                 "android_util_Binder.cpp",
                 "android_util_MemoryIntArray.cpp",
                 "android_util_Process.cpp",
-                "android_media_AudioDevice.cpp",
+                "android_media_AudioDeviceAttributes.cpp",
                 "android_media_AudioEffectDescriptor.cpp",
                 "android_media_AudioRecord.cpp",
                 "android_media_AudioSystem.cpp",
@@ -197,8 +197,11 @@
                 "android_content_res_ObbScanner.cpp",
                 "android_content_res_Configuration.cpp",
                 "android_security_Scrypt.cpp",
+                "com_android_internal_content_om_OverlayConfig.cpp",
                 "com_android_internal_os_ClassLoaderFactory.cpp",
                 "com_android_internal_os_FuseAppLoop.cpp",
+                "com_android_internal_os_KernelCpuUidBpfMapReader.cpp",
+                "com_android_internal_os_KernelSingleUidTimeReader.cpp",
                 "com_android_internal_os_Zygote.cpp",
                 "com_android_internal_os_ZygoteInit.cpp",
                 "hwbinder/EphemeralStorage.cpp",
@@ -273,6 +276,7 @@
                 "libdl",
                 "libdl_android",
                 "libstatslog",
+                "libtimeinstate",
                 "server_configurable_flags",
                 "libstatspull",
             ],
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index d790ada..4879478 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -86,7 +86,7 @@
 extern int register_android_hardware_UsbRequest(JNIEnv *env);
 extern int register_android_hardware_location_ActivityRecognitionHardware(JNIEnv* env);
 
-extern int register_android_media_AudioDevice(JNIEnv* env);
+extern int register_android_media_AudioDeviceAttributes(JNIEnv* env);
 extern int register_android_media_AudioEffectDescriptor(JNIEnv *env);
 extern int register_android_media_AudioRecord(JNIEnv *env);
 extern int register_android_media_AudioSystem(JNIEnv *env);
@@ -186,8 +186,11 @@
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
 extern int register_android_security_Scrypt(JNIEnv *env);
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
+extern int register_com_android_internal_content_om_OverlayConfig(JNIEnv *env);
 extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
 extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
+extern int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env);
+extern int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env);
 extern int register_com_android_internal_os_Zygote(JNIEnv *env);
 extern int register_com_android_internal_os_ZygoteInit(JNIEnv *env);
 extern int register_com_android_internal_util_VirtualRefBasePtr(JNIEnv *env);
@@ -1497,6 +1500,7 @@
         REG_JNI(register_android_os_MemoryFile),
         REG_JNI(register_android_os_SharedMemory),
         REG_JNI(register_android_os_incremental_IncrementalManager),
+        REG_JNI(register_com_android_internal_content_om_OverlayConfig),
         REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
         REG_JNI(register_com_android_internal_os_Zygote),
         REG_JNI(register_com_android_internal_os_ZygoteInit),
@@ -1513,7 +1517,7 @@
         REG_JNI(register_android_hardware_UsbDeviceConnection),
         REG_JNI(register_android_hardware_UsbRequest),
         REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
-        REG_JNI(register_android_media_AudioDevice),
+        REG_JNI(register_android_media_AudioDeviceAttributes),
         REG_JNI(register_android_media_AudioEffectDescriptor),
         REG_JNI(register_android_media_AudioSystem),
         REG_JNI(register_android_media_AudioRecord),
@@ -1558,6 +1562,8 @@
         REG_JNI(register_android_security_Scrypt),
         REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
         REG_JNI(register_com_android_internal_os_FuseAppLoop),
+        REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
+        REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),
 };
 
 /*
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 30e914d..130322a 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -19,11 +19,10 @@
 #include <utils/Color.h>
 
 #ifdef __ANDROID__ // Layoutlib does not support graphic buffer, parcel or render thread
-#include <binder/Parcel.h>
-#include <renderthread/RenderProxy.h>
 #include <android_runtime/android_graphics_GraphicBuffer.h>
-#include <android_runtime/android_hardware_HardwareBuffer.h>
-#include <private/android/AHardwareBufferHelpers.h>
+#include <binder/Parcel.h>
+#include <dlfcn.h>
+#include <renderthread/RenderProxy.h>
 #endif
 
 #include "core_jni_helpers.h"
@@ -1027,11 +1026,18 @@
     return createBitmap(env, bitmap.release(), getPremulBitmapCreateFlags(false));
 }
 
+#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
+typedef AHardwareBuffer* (*AHB_from_HB)(JNIEnv*, jobject);
+AHB_from_HB AHardwareBuffer_fromHardwareBuffer;
+
+typedef jobject (*AHB_to_HB)(JNIEnv*, AHardwareBuffer*);
+AHB_to_HB AHardwareBuffer_toHardwareBuffer;
+#endif
+
 static jobject Bitmap_wrapHardwareBufferBitmap(JNIEnv* env, jobject, jobject hardwareBuffer,
                                                jlong colorSpacePtr) {
 #ifdef __ANDROID__ // Layoutlib does not support graphic buffer
-    AHardwareBuffer* buffer = android_hardware_HardwareBuffer_getNativeHardwareBuffer(env,
-        hardwareBuffer);
+    AHardwareBuffer* buffer = AHardwareBuffer_fromHardwareBuffer(env, hardwareBuffer);
     sk_sp<Bitmap> bitmap = Bitmap::createFrom(buffer,
                                               GraphicsJNI::getNativeColorSpace(colorSpacePtr));
     if (!bitmap.get()) {
@@ -1057,6 +1063,19 @@
 #endif
 }
 
+static jobject Bitmap_getHardwareBuffer(JNIEnv* env, jobject, jlong bitmapPtr) {
+#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
+    LocalScopedBitmap bitmapHandle(bitmapPtr);
+    LOG_ALWAYS_FATAL_IF(!bitmapHandle->isHardware(),
+            "Hardware config is only supported config in Bitmap_getHardwareBuffer");
+
+    Bitmap& bitmap = bitmapHandle->bitmap();
+    return AHardwareBuffer_toHardwareBuffer(env, bitmap.hardwareBuffer());
+#else
+    return NULL;
+#endif
+}
+
 static jboolean Bitmap_isImmutable(CRITICAL_JNI_PARAMS_COMMA jlong bitmapHandle) {
     LocalScopedBitmap bitmapHolder(bitmapHandle);
     if (!bitmapHolder.valid()) return JNI_FALSE;
@@ -1123,6 +1142,8 @@
         (void*) Bitmap_wrapHardwareBufferBitmap },
     {   "nativeCreateGraphicBufferHandle", "(J)Landroid/graphics/GraphicBuffer;",
         (void*) Bitmap_createGraphicBufferHandle },
+    {   "nativeGetHardwareBuffer", "(J)Landroid/hardware/HardwareBuffer;",
+        (void*) Bitmap_getHardwareBuffer },
     {   "nativeComputeColorSpace",  "(J)Landroid/graphics/ColorSpace;", (void*)Bitmap_computeColorSpace },
     {   "nativeSetColorSpace",      "(JJ)V", (void*)Bitmap_setColorSpace },
     {   "nativeIsSRGB",             "(J)Z", (void*)Bitmap_isSRGB },
@@ -1140,6 +1161,18 @@
     gBitmap_nativePtr = GetFieldIDOrDie(env, gBitmap_class, "mNativePtr", "J");
     gBitmap_constructorMethodID = GetMethodIDOrDie(env, gBitmap_class, "<init>", "(JIIIZ[BLandroid/graphics/NinePatch$InsetStruct;Z)V");
     gBitmap_reinitMethodID = GetMethodIDOrDie(env, gBitmap_class, "reinit", "(IIZ)V");
+
+#ifdef __ANDROID__ // Layoutlib does not support graphic buffer
+    void* handle_ = dlopen("libandroid.so", RTLD_NOW | RTLD_NODELETE);
+    AHardwareBuffer_fromHardwareBuffer =
+            (AHB_from_HB)dlsym(handle_, "AHardwareBuffer_fromHardwareBuffer");
+    LOG_ALWAYS_FATAL_IF(AHardwareBuffer_fromHardwareBuffer == nullptr,
+                        "Failed to find required symbol AHardwareBuffer_fromHardwareBuffer!");
+
+    AHardwareBuffer_toHardwareBuffer = (AHB_to_HB)dlsym(handle_, "AHardwareBuffer_toHardwareBuffer");
+    LOG_ALWAYS_FATAL_IF(AHardwareBuffer_toHardwareBuffer == nullptr,
+                        " Failed to find required symbol AHardwareBuffer_toHardwareBuffer!");
+#endif
     return android::RegisterMethodsOrDie(env, "android/graphics/Bitmap", gBitmapMethods,
                                          NELEM(gBitmapMethods));
 }
diff --git a/core/jni/android_media_AudioDevice.cpp b/core/jni/android_media_AudioDeviceAttributes.cpp
similarity index 64%
rename from core/jni/android_media_AudioDevice.cpp
rename to core/jni/android_media_AudioDeviceAttributes.cpp
index f6a0e4b..e79c95e 100644
--- a/core/jni/android_media_AudioDevice.cpp
+++ b/core/jni/android_media_AudioDeviceAttributes.cpp
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "android_media_AudioDevice.h"
+#include "android_media_AudioDeviceAttributes.h"
 #include "android_media_AudioErrors.h"
 #include "core_jni_helpers.h"
 
@@ -22,29 +22,30 @@
 
 using namespace android;
 
-static jclass gAudioDeviceClass;
-static jmethodID gAudioDeviceCstor;
+static jclass gAudioDeviceAttributesClass;
+static jmethodID gAudioDeviceAttributesCstor;
 
 namespace android {
 
-jint createAudioDeviceFromNative(JNIEnv *env, jobject *jAudioDevice,
+jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
                                  const AudioDeviceTypeAddr *devTypeAddr) {
     jint jStatus = (jint)AUDIO_JAVA_SUCCESS;
     jint jNativeType = (jint)devTypeAddr->mType;
     ScopedLocalRef<jstring> jAddress(env, env->NewStringUTF(devTypeAddr->mAddress.data()));
 
-    *jAudioDevice =
-            env->NewObject(gAudioDeviceClass, gAudioDeviceCstor, jNativeType, jAddress.get());
+    *jAudioDeviceAttributes = env->NewObject(gAudioDeviceAttributesClass, gAudioDeviceAttributesCstor,
+            jNativeType, jAddress.get());
 
     return jStatus;
 }
 
 } // namespace android
 
-int register_android_media_AudioDevice(JNIEnv *env) {
-    jclass audioDeviceTypeAddressClass = FindClassOrDie(env, "android/media/AudioDevice");
-    gAudioDeviceClass = MakeGlobalRefOrDie(env, audioDeviceTypeAddressClass);
-    gAudioDeviceCstor =
+int register_android_media_AudioDeviceAttributes(JNIEnv *env) {
+    jclass audioDeviceTypeAddressClass =
+            FindClassOrDie(env, "android/media/AudioDeviceAttributes");
+    gAudioDeviceAttributesClass = MakeGlobalRefOrDie(env, audioDeviceTypeAddressClass);
+    gAudioDeviceAttributesCstor =
             GetMethodIDOrDie(env, audioDeviceTypeAddressClass, "<init>", "(ILjava/lang/String;)V");
 
     return 0;
diff --git a/core/jni/android_media_AudioDevice.h b/core/jni/android_media_AudioDeviceAttributes.h
similarity index 75%
rename from core/jni/android_media_AudioDevice.h
rename to core/jni/android_media_AudioDeviceAttributes.h
index fc92334..b49d9ba 100644
--- a/core/jni/android_media_AudioDevice.h
+++ b/core/jni/android_media_AudioDeviceAttributes.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ANDROID_MEDIA_AUDIODEVICE_H
-#define ANDROID_MEDIA_AUDIODEVICE_H
+#ifndef ANDROID_MEDIA_AUDIODEVICEATTRIBUTES_H
+#define ANDROID_MEDIA_AUDIODEVICEATTRIBUTES_H
 
 #include <media/AudioDeviceTypeAddr.h>
 #include <system/audio.h>
@@ -24,9 +24,9 @@
 
 namespace android {
 
-// Create a Java AudioDevice instance from a C++ AudioDeviceTypeAddress
+// Create a Java AudioDeviceAttributes instance from a C++ AudioDeviceTypeAddress
 
-extern jint createAudioDeviceFromNative(JNIEnv *env, jobject *jAudioDevice,
+extern jint createAudioDeviceAttributesFromNative(JNIEnv *env, jobject *jAudioDeviceAttributes,
                                         const AudioDeviceTypeAddr *devTypeAddr);
 } // namespace android
 
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index d8f30e9..ab3cf30 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -34,7 +34,7 @@
 #include <system/audio.h>
 #include <system/audio_policy.h>
 #include "android_media_AudioAttributes.h"
-#include "android_media_AudioDevice.h"
+#include "android_media_AudioDeviceAttributes.h"
 #include "android_media_AudioEffectDescriptor.h"
 #include "android_media_AudioErrors.h"
 #include "android_media_AudioFormat.h"
@@ -2352,7 +2352,7 @@
         jint strategy, jobjectArray jDeviceArray)
 {
     if (jDeviceArray == nullptr || env->GetArrayLength(jDeviceArray) != 1) {
-        ALOGE("%s invalid array to store AudioDevice", __FUNCTION__);
+        ALOGE("%s invalid array to store AudioDeviceAttributes", __FUNCTION__);
         return (jint)AUDIO_JAVA_BAD_VALUE;
     }
 
@@ -2362,10 +2362,10 @@
     if (status != NO_ERROR) {
         return (jint) status;
     }
-    jobject jAudioDevice = NULL;
-    jint jStatus = createAudioDeviceFromNative(env, &jAudioDevice, &elDevice);
+    jobject jAudioDeviceAttributes = NULL;
+    jint jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &elDevice);
     if (jStatus == AUDIO_JAVA_SUCCESS) {
-        env->SetObjectArrayElement(jDeviceArray, 0, jAudioDevice);
+        env->SetObjectArrayElement(jDeviceArray, 0, jAudioDeviceAttributes);
     }
     return jStatus;
 }
@@ -2380,7 +2380,7 @@
     // with reverse JNI to make the array grow as need as this would be less efficient, and some
     // components call this method often
     if (jDeviceArray == nullptr || maxResultSize == 0) {
-        ALOGE("%s invalid array to store AudioDevice", __FUNCTION__);
+        ALOGE("%s invalid array to store AudioDeviceAttributes", __FUNCTION__);
         return (jint)AUDIO_JAVA_BAD_VALUE;
     }
 
@@ -2401,13 +2401,13 @@
         return AUDIO_JAVA_INVALID_OPERATION;
     }
     size_t index = 0;
-    jobject jAudioDevice = NULL;
+    jobject jAudioDeviceAttributes = NULL;
     for (const auto& device : devices) {
-        jStatus = createAudioDeviceFromNative(env, &jAudioDevice, &device);
+        jStatus = createAudioDeviceAttributesFromNative(env, &jAudioDeviceAttributes, &device);
         if (jStatus != AUDIO_JAVA_SUCCESS) {
             return jStatus;
         }
-        env->SetObjectArrayElement(jDeviceArray, index++, jAudioDevice);
+        env->SetObjectArrayElement(jDeviceArray, index++, jAudioDeviceAttributes);
     }
     return jStatus;
 }
@@ -2519,10 +2519,10 @@
           (void *)android_media_AudioSystem_setPreferredDeviceForStrategy},
          {"removePreferredDeviceForStrategy", "(I)I",
           (void *)android_media_AudioSystem_removePreferredDeviceForStrategy},
-         {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDevice;)I",
+         {"getPreferredDeviceForStrategy", "(I[Landroid/media/AudioDeviceAttributes;)I",
           (void *)android_media_AudioSystem_getPreferredDeviceForStrategy},
          {"getDevicesForAttributes",
-          "(Landroid/media/AudioAttributes;[Landroid/media/AudioDevice;)I",
+          "(Landroid/media/AudioAttributes;[Landroid/media/AudioDeviceAttributes;)I",
           (void *)android_media_AudioSystem_getDevicesForAttributes},
          {"setUserIdDeviceAffinities", "(I[I[Ljava/lang/String;)I",
           (void *)android_media_AudioSystem_setUserIdDeviceAffinities},
diff --git a/core/jni/android_os_storage_StorageManager.cpp b/core/jni/android_os_storage_StorageManager.cpp
index aee6733..fd3e66b 100644
--- a/core/jni/android_os_storage_StorageManager.cpp
+++ b/core/jni/android_os_storage_StorageManager.cpp
@@ -15,6 +15,7 @@
  */
 
 #define LOG_TAG "StorageManager"
+#include <android-base/file.h>
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <fcntl.h>
@@ -25,11 +26,30 @@
 
 namespace android {
 
+static const char* kProcFilesystems = "/proc/filesystems";
+
+// Checks whether the passed in filesystem is listed in /proc/filesystems
+static bool IsFilesystemSupported(const std::string& fsType) {
+    std::string supported;
+    if (!android::base::ReadFileToString(kProcFilesystems, &supported)) {
+        PLOG(ERROR) << "Failed to read supported filesystems";
+        return false;
+    }
+    return supported.find(fsType + "\n") != std::string::npos;
+}
+
 jboolean android_os_storage_StorageManager_setQuotaProjectId(JNIEnv* env, jobject self,
                                                              jstring path, jlong projectId) {
     struct fsxattr fsx;
     ScopedUtfChars utf_chars_path(env, path);
 
+    static bool sdcardFsSupported = IsFilesystemSupported("sdcardfs");
+    if (sdcardFsSupported) {
+        // sdcardfs doesn't support project ID quota tracking and takes care of quota
+        // in a different way.
+        return JNI_TRUE;
+    }
+
     if (projectId > UINT32_MAX) {
         LOG(ERROR) << "Invalid project id: " << projectId;
         return JNI_FALSE;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index b01083b..8a53bd0 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -413,10 +413,15 @@
     return anw->perform(surface, NATIVE_WINDOW_SET_AUTO_REFRESH, int(enabled));
 }
 
-static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate) {
+static jint nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong nativeObject, jfloat frameRate,
+                               jint compatibility) {
     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
     ANativeWindow* anw = static_cast<ANativeWindow*>(surface);
-    return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, float(frameRate));
+    // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and
+    // NATIVE_WINDOW_SET_FRAME_RATE takes an
+    // ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The values are identical
+    // though, so no need to explicitly convert.
+    return anw->perform(surface, NATIVE_WINDOW_SET_FRAME_RATE, float(frameRate), compatibility);
 }
 
 // ----------------------------------------------------------------------------
@@ -453,7 +458,7 @@
             (void*)nativeAttachAndQueueBufferWithColorSpace},
     {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
     {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
-    {"nativeSetFrameRate", "(JF)I", (void*)nativeSetFrameRate},
+    {"nativeSetFrameRate", "(JFI)I", (void*)nativeSetFrameRate},
 };
 
 int register_android_view_Surface(JNIEnv* env)
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 3f81b11..a9ef257 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -37,6 +37,7 @@
 #include <stdio.h>
 #include <system/graphics.h>
 #include <ui/ConfigStoreTypes.h>
+#include <ui/DeviceProductInfo.h>
 #include <ui/DisplayConfig.h>
 #include <ui/DisplayInfo.h>
 #include <ui/DisplayedFrameStats.h>
@@ -65,9 +66,19 @@
 static struct {
     jclass clazz;
     jmethodID ctor;
+} gIntegerClassInfo;
+
+static jobject toInteger(JNIEnv* env, int32_t i) {
+    return env->NewObject(gIntegerClassInfo.clazz, gIntegerClassInfo.ctor, i);
+}
+
+static struct {
+    jclass clazz;
+    jmethodID ctor;
     jfieldID isInternal;
     jfieldID density;
     jfieldID secure;
+    jfieldID deviceProductInfo;
 } gDisplayInfoClassInfo;
 
 static struct {
@@ -111,6 +122,16 @@
 
 static struct {
     jclass clazz;
+    jmethodID ctor;
+} gDeviceProductInfoClassInfo;
+
+static struct {
+    jclass clazz;
+    jmethodID ctor;
+} gDeviceProductInfoManufactureDateClassInfo;
+
+static struct {
+    jclass clazz;
     jmethodID builder;
 } gGraphicBufferClassInfo;
 
@@ -592,11 +613,14 @@
 }
 
 static void nativeSetFrameRate(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
-                               jfloat frameRate) {
+                               jfloat frameRate, jint compatibility) {
     auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
 
     const auto ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
-    transaction->setFrameRate(ctrl, frameRate);
+    // Our compatibility is a Surface.FRAME_RATE_COMPATIBILITY_* value, and
+    // Transaction::setFrameRate() takes an ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_* value. The
+    // values are identical though, so no need to convert anything.
+    transaction->setFrameRate(ctrl, frameRate, static_cast<int8_t>(compatibility));
 }
 
 static jlongArray nativeGetPhysicalDisplayIds(JNIEnv* env, jclass clazz) {
@@ -773,6 +797,41 @@
     }
 }
 
+static jobject convertDeviceProductInfoToJavaObject(
+        JNIEnv* env, const std::optional<DeviceProductInfo>& info) {
+    using ModelYear = android::DeviceProductInfo::ModelYear;
+    using ManufactureYear = android::DeviceProductInfo::ManufactureYear;
+    using ManufactureWeekAndYear = android::DeviceProductInfo::ManufactureWeekAndYear;
+
+    if (!info) return nullptr;
+    jstring name = env->NewStringUTF(info->name.data());
+    jstring manufacturerPnpId = env->NewStringUTF(info->manufacturerPnpId.data());
+    jobject productId = env->NewStringUTF(info->productId.data());
+    const auto& date = info->manufactureOrModelDate;
+    jobject modelYear, manufactureDate;
+    if (const auto* model = std::get_if<ModelYear>(&date)) {
+        modelYear = toInteger(env, model->year);
+        manufactureDate = nullptr;
+    } else if (const auto* manufactureWeekAndYear = std::get_if<ManufactureWeekAndYear>(&date)) {
+        modelYear = nullptr;
+        manufactureDate = env->NewObject(gDeviceProductInfoManufactureDateClassInfo.clazz,
+                                               gDeviceProductInfoManufactureDateClassInfo.ctor,
+                                               toInteger(env, manufactureWeekAndYear->week),
+                                               toInteger(env, manufactureWeekAndYear->year));
+    } else if (const auto* manufactureYear = std::get_if<ManufactureYear>(&date)) {
+        modelYear = nullptr;
+        manufactureDate = env->NewObject(gDeviceProductInfoManufactureDateClassInfo.clazz,
+                                       gDeviceProductInfoManufactureDateClassInfo.ctor,
+                                       nullptr,
+                                       toInteger(env, manufactureYear->year));
+    } else {
+        LOG_FATAL("Unknown alternative for variant DeviceProductInfo::ManufactureOrModelDate");
+    }
+
+    return env->NewObject(gDeviceProductInfoClassInfo.clazz, gDeviceProductInfoClassInfo.ctor, name,
+                          manufacturerPnpId, productId, modelYear, manufactureDate);
+}
+
 static jobject nativeGetDisplayInfo(JNIEnv* env, jclass clazz, jobject tokenObj) {
     DisplayInfo info;
     if (const auto token = ibinderForJavaObject(env, tokenObj);
@@ -785,6 +844,8 @@
                          info.connectionType == DisplayConnectionType::Internal);
     env->SetFloatField(object, gDisplayInfoClassInfo.density, info.density);
     env->SetBooleanField(object, gDisplayInfoClassInfo.secure, info.secure);
+    env->SetObjectField(object, gDisplayInfoClassInfo.deviceProductInfo,
+                        convertDeviceProductInfoToJavaObject(env, info.deviceProductInfo));
     return object;
 }
 
@@ -1409,7 +1470,7 @@
             (void*)nativeSetLayerStack },
     {"nativeSetShadowRadius", "(JJF)V",
             (void*)nativeSetShadowRadius },
-    {"nativeSetFrameRate", "(JJF)V",
+    {"nativeSetFrameRate", "(JJFI)V",
             (void*)nativeSetFrameRate },
     {"nativeGetPhysicalDisplayIds", "()[J",
             (void*)nativeGetPhysicalDisplayIds },
@@ -1527,12 +1588,19 @@
     int err = RegisterMethodsOrDie(env, "android/view/SurfaceControl",
             sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
 
+    jclass integerClass = FindClassOrDie(env, "java/lang/Integer");
+    gIntegerClassInfo.clazz = MakeGlobalRefOrDie(env, integerClass);
+    gIntegerClassInfo.ctor = GetMethodIDOrDie(env, gIntegerClassInfo.clazz, "<init>", "(I)V");
+
     jclass infoClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayInfo");
     gDisplayInfoClassInfo.clazz = MakeGlobalRefOrDie(env, infoClazz);
     gDisplayInfoClassInfo.ctor = GetMethodIDOrDie(env, infoClazz, "<init>", "()V");
     gDisplayInfoClassInfo.isInternal = GetFieldIDOrDie(env, infoClazz, "isInternal", "Z");
     gDisplayInfoClassInfo.density = GetFieldIDOrDie(env, infoClazz, "density", "F");
     gDisplayInfoClassInfo.secure = GetFieldIDOrDie(env, infoClazz, "secure", "Z");
+    gDisplayInfoClassInfo.deviceProductInfo =
+            GetFieldIDOrDie(env, infoClazz, "deviceProductInfo",
+                            "Landroid/hardware/display/DeviceProductInfo;");
 
     jclass configClazz = FindClassOrDie(env, "android/view/SurfaceControl$DisplayConfig");
     gDisplayConfigClassInfo.clazz = MakeGlobalRefOrDie(env, configClazz);
@@ -1573,6 +1641,25 @@
     gHdrCapabilitiesClassInfo.ctor = GetMethodIDOrDie(env, hdrCapabilitiesClazz, "<init>",
             "([IFFF)V");
 
+    jclass deviceProductInfoClazz =
+            FindClassOrDie(env, "android/hardware/display/DeviceProductInfo");
+    gDeviceProductInfoClassInfo.clazz = MakeGlobalRefOrDie(env, deviceProductInfoClazz);
+    gDeviceProductInfoClassInfo.ctor =
+            GetMethodIDOrDie(env, deviceProductInfoClazz, "<init>",
+                             "(Ljava/lang/String;"
+                             "Ljava/lang/String;"
+                             "Ljava/lang/String;"
+                             "Ljava/lang/Integer;"
+                             "Landroid/hardware/display/DeviceProductInfo$ManufactureDate;)V");
+
+    jclass deviceProductInfoManufactureDateClazz =
+            FindClassOrDie(env, "android/hardware/display/DeviceProductInfo$ManufactureDate");
+    gDeviceProductInfoManufactureDateClassInfo.clazz =
+            MakeGlobalRefOrDie(env, deviceProductInfoManufactureDateClazz);
+    gDeviceProductInfoManufactureDateClassInfo.ctor =
+            GetMethodIDOrDie(env, deviceProductInfoManufactureDateClazz, "<init>",
+                             "(Ljava/lang/Integer;Ljava/lang/Integer;)V");
+
     jclass graphicsBufferClazz = FindClassOrDie(env, "android/graphics/GraphicBuffer");
     gGraphicBufferClassInfo.clazz = MakeGlobalRefOrDie(env, graphicsBufferClazz);
     gGraphicBufferClassInfo.builder = GetStaticMethodIDOrDie(env, graphicsBufferClazz,
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 27c5a73..93449ff 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -186,6 +186,7 @@
         proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer);
     }
     proxy->setSurface(window, enableTimeout);
+    ANativeWindow_release(window);
 }
 
 static jboolean android_view_ThreadedRenderer_pause(JNIEnv* env, jobject clazz,
diff --git a/core/jni/com_android_internal_content_om_OverlayConfig.cpp b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
new file mode 100644
index 0000000..6aa7c10
--- /dev/null
+++ b/core/jni/com_android_internal_content_om_OverlayConfig.cpp
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ */
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "core_jni_helpers.h"
+
+#include "android-base/logging.h"
+#include "androidfw/PosixUtils.h"
+
+using ::android::util::ExecuteBinary;
+
+static jclass g_stringClass = nullptr;
+
+static jobjectArray createIdmap(JNIEnv* env, jclass /*clazz*/, jstring targetPath,
+                           jobjectArray overlayPath, jobjectArray policies,
+                           jboolean enforceOverlayable) {
+  if (access("/system/bin/idmap2", X_OK) == -1) {
+    PLOG(WARNING) << "unable to execute idmap2";
+    return nullptr;
+  }
+
+  const char* targetApkPath = env->GetStringUTFChars(targetPath, NULL /* isCopy */);
+  std::vector<std::string> argv{"/system/bin/idmap2",
+    "create-multiple",
+    "--target-apk-path", targetApkPath,
+  };
+  env->ReleaseStringUTFChars(targetPath, targetApkPath);
+
+  // Add the overlays for which to generate idmap files to the idmap arguments.
+  for (size_t i = 0, count = env->GetArrayLength(overlayPath); i < count; ++i) {
+    jstring element = (jstring) env->GetObjectArrayElement(overlayPath, i);
+    const char* overlayApkPath = env->GetStringUTFChars(element, NULL /* isCopy */);
+    argv.emplace_back("--overlay-apk-path");
+    argv.emplace_back(overlayApkPath);
+    env->ReleaseStringUTFChars(element, overlayApkPath);
+  }
+
+  // Add the policies the overlays fulfill to the idmap arguments.
+  for (size_t i = 0, count = env->GetArrayLength(policies); i < count; ++i) {
+    jstring element = (jstring)env->GetObjectArrayElement(policies, i);
+    const char* policy = env->GetStringUTFChars(element, NULL /* isCopy */);
+    argv.emplace_back("--policy");
+    argv.emplace_back(policy);
+    env->ReleaseStringUTFChars(element, policy);
+  }
+
+  if (!enforceOverlayable) {
+    argv.emplace_back("--ignore-overlayable");
+  }
+
+  const auto result = ExecuteBinary(argv);
+  if (!result) {
+      LOG(ERROR) << "failed to execute idmap2";
+      return nullptr;
+  }
+
+  if (result->status != 0) {
+    LOG(ERROR) << "idmap2: " << result->stderr;
+    return nullptr;
+  }
+
+  // Return the paths of the idmaps created or updated during the idmap invocation.
+  std::vector<std::string> idmap_paths;
+  std::istringstream input(result->stdout);
+  std::string path;
+  while (std::getline(input, path)) {
+    idmap_paths.push_back(path);
+  }
+
+  jobjectArray array = env->NewObjectArray(idmap_paths.size(), g_stringClass, nullptr);
+  if (array == nullptr) {
+    return nullptr;
+  }
+  for (size_t i = 0; i < idmap_paths.size(); i++) {
+    const std::string path = idmap_paths[i];
+    jstring java_string = env->NewStringUTF(path.c_str());
+    if (env->ExceptionCheck()) {
+      return nullptr;
+    }
+    env->SetObjectArrayElement(array, i, java_string);
+    env->DeleteLocalRef(java_string);
+  }
+
+  return array;
+}
+
+static const JNINativeMethod g_methods[] = {
+    { "createIdmap",
+      "(Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Z)[Ljava/lang/String;",
+      (void *)createIdmap },
+};
+
+static const char* const kOverlayConfigPathName = "com/android/internal/content/om/OverlayConfig";
+
+namespace android {
+
+int register_com_android_internal_content_om_OverlayConfig(JNIEnv* env) {
+  jclass stringClass = FindClassOrDie(env, "java/lang/String");
+  g_stringClass = MakeGlobalRefOrDie(env, stringClass);
+
+  return RegisterMethodsOrDie(env, kOverlayConfigPathName, g_methods, NELEM(g_methods));
+}
+
+} // namespace android
diff --git a/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
new file mode 100644
index 0000000..7c68de5
--- /dev/null
+++ b/core/jni/com_android_internal_os_KernelCpuUidBpfMapReader.cpp
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+#include "core_jni_helpers.h"
+
+#include <sys/sysinfo.h>
+
+#include <android-base/stringprintf.h>
+#include <cputimeinstate.h>
+
+namespace android {
+
+static constexpr uint64_t NSEC_PER_MSEC = 1000000;
+
+static struct {
+    jclass clazz;
+    jmethodID put;
+    jmethodID get;
+} gSparseArrayClassInfo;
+
+static jfieldID gmData;
+
+static jlongArray getUidArray(JNIEnv *env, jobject sparseAr, uint32_t uid, jsize sz) {
+    jlongArray ar = (jlongArray)env->CallObjectMethod(sparseAr, gSparseArrayClassInfo.get, uid);
+    if (!ar) {
+        ar = env->NewLongArray(sz);
+        if (ar == NULL) return ar;
+        env->CallVoidMethod(sparseAr, gSparseArrayClassInfo.put, uid, ar);
+    }
+    return ar;
+}
+
+static void copy2DVecToArray(JNIEnv *env, jlongArray ar, std::vector<std::vector<uint64_t>> &vec) {
+    jsize start = 0;
+    for (auto &subVec : vec) {
+        for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC;
+        env->SetLongArrayRegion(ar, start, subVec.size(),
+                                reinterpret_cast<const jlong *>(subVec.data()));
+        start += subVec.size();
+    }
+}
+
+static jboolean KernelCpuUidFreqTimeBpfMapReader_removeUidRange(JNIEnv *env, jclass, jint startUid,
+                                                                jint endUid) {
+    for (uint32_t uid = startUid; uid <= endUid; ++uid) {
+        if (!android::bpf::clearUidTimes(uid)) return false;
+    }
+    return true;
+}
+
+static jboolean KernelCpuUidFreqTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
+    static uint64_t lastUpdate = 0;
+    uint64_t newLastUpdate = lastUpdate;
+    auto sparseAr = env->GetObjectField(thiz, gmData);
+    if (sparseAr == NULL) return false;
+    auto data = android::bpf::getUidsUpdatedCpuFreqTimes(&newLastUpdate);
+    if (!data.has_value()) return false;
+
+    jsize s = 0;
+    for (auto &[uid, times] : *data) {
+        if (s == 0) {
+            for (const auto &subVec : times) s += subVec.size();
+        }
+        jlongArray ar = getUidArray(env, sparseAr, uid, s);
+        if (ar == NULL) return false;
+        copy2DVecToArray(env, ar, times);
+    }
+    lastUpdate = newLastUpdate;
+    return true;
+}
+
+static jlongArray KernelCpuUidFreqTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
+    auto freqs = android::bpf::getCpuFreqs();
+    if (!freqs) return NULL;
+
+    std::vector<uint64_t> allFreqs;
+    for (const auto &vec : *freqs) std::copy(vec.begin(), vec.end(), std::back_inserter(allFreqs));
+
+    auto ar = env->NewLongArray(allFreqs.size());
+    if (ar != NULL) {
+        env->SetLongArrayRegion(ar, 0, allFreqs.size(),
+                                reinterpret_cast<const jlong *>(allFreqs.data()));
+    }
+    return ar;
+}
+
+static const JNINativeMethod gFreqTimeMethods[] = {
+        {"removeUidRange", "(II)Z", (void *)KernelCpuUidFreqTimeBpfMapReader_removeUidRange},
+        {"readBpfData", "()Z", (void *)KernelCpuUidFreqTimeBpfMapReader_readBpfData},
+        {"getDataDimensions", "()[J", (void *)KernelCpuUidFreqTimeBpfMapReader_getDataDimensions},
+};
+
+static jboolean KernelCpuUidActiveTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
+    static uint64_t lastUpdate = 0;
+    uint64_t newLastUpdate = lastUpdate;
+    auto sparseAr = env->GetObjectField(thiz, gmData);
+    if (sparseAr == NULL) return false;
+    auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate);
+    if (!data.has_value()) return false;
+
+    for (auto &[uid, times] : *data) {
+        // TODO: revise calling code so we can divide by NSEC_PER_MSEC here instead
+        for (auto &time : times.active) time /= NSEC_PER_MSEC;
+        jlongArray ar = getUidArray(env, sparseAr, uid, times.active.size());
+        if (ar == NULL) return false;
+        env->SetLongArrayRegion(ar, 0, times.active.size(),
+                                reinterpret_cast<const jlong *>(times.active.data()));
+    }
+    lastUpdate = newLastUpdate;
+    return true;
+}
+
+static jlongArray KernelCpuUidActiveTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
+    jlong nCpus = get_nprocs_conf();
+
+    auto ar = env->NewLongArray(1);
+    if (ar != NULL) env->SetLongArrayRegion(ar, 0, 1, &nCpus);
+    return ar;
+}
+
+static const JNINativeMethod gActiveTimeMethods[] = {
+        {"readBpfData", "()Z", (void *)KernelCpuUidActiveTimeBpfMapReader_readBpfData},
+        {"getDataDimensions", "()[J", (void *)KernelCpuUidActiveTimeBpfMapReader_getDataDimensions},
+};
+
+static jboolean KernelCpuUidClusterTimeBpfMapReader_readBpfData(JNIEnv *env, jobject thiz) {
+    static uint64_t lastUpdate = 0;
+    uint64_t newLastUpdate = lastUpdate;
+    auto sparseAr = env->GetObjectField(thiz, gmData);
+    if (sparseAr == NULL) return false;
+    auto data = android::bpf::getUidsUpdatedConcurrentTimes(&newLastUpdate);
+    if (!data.has_value()) return false;
+
+    jsize s = 0;
+    for (auto &[uid, times] : *data) {
+        if (s == 0) {
+            for (const auto &subVec : times.policy) s += subVec.size();
+        }
+        jlongArray ar = getUidArray(env, sparseAr, uid, s);
+        if (ar == NULL) return false;
+        copy2DVecToArray(env, ar, times.policy);
+    }
+    lastUpdate = newLastUpdate;
+    return true;
+}
+
+static jlongArray KernelCpuUidClusterTimeBpfMapReader_getDataDimensions(JNIEnv *env, jobject) {
+    auto times = android::bpf::getUidConcurrentTimes(0);
+    if (!times.has_value()) return NULL;
+
+    std::vector<jlong> clusterCores;
+    for (const auto &vec : times->policy) clusterCores.push_back(vec.size());
+    auto ar = env->NewLongArray(clusterCores.size());
+    if (ar != NULL) env->SetLongArrayRegion(ar, 0, clusterCores.size(), clusterCores.data());
+    return ar;
+}
+
+static const JNINativeMethod gClusterTimeMethods[] = {
+        {"readBpfData", "()Z", (void *)KernelCpuUidClusterTimeBpfMapReader_readBpfData},
+        {"getDataDimensions", "()[J",
+         (void *)KernelCpuUidClusterTimeBpfMapReader_getDataDimensions},
+};
+
+struct readerMethods {
+    const char *name;
+    const JNINativeMethod *methods;
+    int numMethods;
+};
+
+static const readerMethods gAllMethods[] = {
+        {"KernelCpuUidFreqTimeBpfMapReader", gFreqTimeMethods, NELEM(gFreqTimeMethods)},
+        {"KernelCpuUidActiveTimeBpfMapReader", gActiveTimeMethods, NELEM(gActiveTimeMethods)},
+        {"KernelCpuUidClusterTimeBpfMapReader", gClusterTimeMethods, NELEM(gClusterTimeMethods)},
+};
+
+static jboolean KernelCpuUidBpfMapReader_startTrackingBpfTimes(JNIEnv *, jobject) {
+    return android::bpf::startTrackingUidTimes();
+}
+
+int register_com_android_internal_os_KernelCpuUidBpfMapReader(JNIEnv *env) {
+    gSparseArrayClassInfo.clazz = FindClassOrDie(env, "android/util/SparseArray");
+    gSparseArrayClassInfo.clazz = MakeGlobalRefOrDie(env, gSparseArrayClassInfo.clazz);
+    gSparseArrayClassInfo.put =
+            GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "put", "(ILjava/lang/Object;)V");
+    gSparseArrayClassInfo.get =
+            GetMethodIDOrDie(env, gSparseArrayClassInfo.clazz, "get", "(I)Ljava/lang/Object;");
+    constexpr auto readerName = "com/android/internal/os/KernelCpuUidBpfMapReader";
+    constexpr JNINativeMethod method = {"startTrackingBpfTimes", "()Z",
+                                        (void *)KernelCpuUidBpfMapReader_startTrackingBpfTimes};
+
+    int ret = RegisterMethodsOrDie(env, readerName, &method, 1);
+    if (ret < 0) return ret;
+    auto c = FindClassOrDie(env, readerName);
+    gmData = GetFieldIDOrDie(env, c, "mData", "Landroid/util/SparseArray;");
+
+    for (const auto &m : gAllMethods) {
+        auto fullName = android::base::StringPrintf("%s$%s", readerName, m.name);
+        ret = RegisterMethodsOrDie(env, fullName.c_str(), m.methods, m.numMethods);
+        if (ret < 0) break;
+    }
+    return ret;
+}
+
+} // namespace android
diff --git a/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp
new file mode 100644
index 0000000..c0ecf33
--- /dev/null
+++ b/core/jni/com_android_internal_os_KernelSingleUidTimeReader.cpp
@@ -0,0 +1,54 @@
+/*
+ * 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.
+ */
+
+#include "core_jni_helpers.h"
+
+#include <cputimeinstate.h>
+
+namespace android {
+
+static constexpr uint64_t NSEC_PER_MSEC = 1000000;
+
+static jlongArray copyVecsToArray(JNIEnv *env, std::vector<std::vector<uint64_t>> &vec) {
+    jsize s = 0;
+    for (const auto &subVec : vec) s += subVec.size();
+    jlongArray ar = env->NewLongArray(s);
+    jsize start = 0;
+    for (auto &subVec : vec) {
+        for (uint32_t i = 0; i < subVec.size(); ++i) subVec[i] /= NSEC_PER_MSEC;
+        env->SetLongArrayRegion(ar, start, subVec.size(),
+                                reinterpret_cast<const jlong*>(subVec.data()));
+        start += subVec.size();
+    }
+    return ar;
+}
+
+static jlongArray getUidCpuFreqTimeMs(JNIEnv *env, jclass, jint uid) {
+    auto out = android::bpf::getUidCpuFreqTimes(uid);
+    if (!out) return env->NewLongArray(0);
+    return copyVecsToArray(env, out.value());
+}
+
+static const JNINativeMethod g_single_methods[] = {
+    {"readBpfData", "(I)[J", (void *)getUidCpuFreqTimeMs},
+};
+
+int register_com_android_internal_os_KernelSingleUidTimeReader(JNIEnv *env) {
+    return RegisterMethodsOrDie(env, "com/android/internal/os/KernelSingleUidTimeReader$Injector",
+                                g_single_methods, NELEM(g_single_methods));
+}
+
+}
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index d91911c..e4141e0 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -105,10 +105,12 @@
 using namespace std::placeholders;
 
 using android::String8;
+using android::base::ReadFileToString;
 using android::base::StringAppendF;
 using android::base::StringPrintf;
 using android::base::WriteStringToFile;
 using android::base::GetBoolProperty;
+using android::base::GetProperty;
 
 #define CREATE_ERROR(...) StringPrintf("%s:%d: ", __FILE__, __LINE__). \
                               append(StringPrintf(__VA_ARGS__))
@@ -174,6 +176,12 @@
 static const std::string ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
     "persist.zygote.app_data_isolation";
 
+/**
+ * Property to enable app data isolation for sdcard obb or data in vold.
+ */
+static const std::string ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+    "persist.sys.vold_app_data_isolation_enabled";
+
 static constexpr const uint64_t UPPER_HALF_WORD_MASK = 0xFFFF'FFFF'0000'0000;
 static constexpr const uint64_t LOWER_HALF_WORD_MASK = 0x0000'0000'FFFF'FFFF;
 
@@ -603,6 +611,15 @@
   }
 }
 
+static bool IsFilesystemSupported(const std::string& fsType) {
+    std::string supported;
+    if (!ReadFileToString("/proc/filesystems", &supported)) {
+        ALOGE("Failed to read supported filesystems");
+        return false;
+    }
+    return supported.find(fsType + "\n") != std::string::npos;
+}
+
 static void PreApplicationInit() {
   // The child process sets this to indicate it's not the zygote.
   android_mallopt(M_SET_ZYGOTE_CHILD, nullptr, 0);
@@ -782,6 +799,31 @@
   }
 }
 
+static void BindMountObbPackage(std::string_view package_name, int userId, fail_fn_t fail_fn) {
+
+  // TODO(148772775): Pass primary volume name from zygote argument to here
+  std::string source;
+  if (IsFilesystemSupported("sdcardfs")) {
+    source = StringPrintf("/mnt/runtime/default/emulated/%d/Android/obb/%s",
+        userId, package_name.data());
+  } else {
+    source = StringPrintf("/mnt/pass_through/%d/emulated/%d/Android/obb/%s",
+        userId, userId, package_name.data());
+  }
+  std::string target(
+      StringPrintf("/storage/emulated/%d/Android/obb/%s", userId, package_name.data()));
+
+  if (access(source.c_str(), F_OK) != 0) {
+    fail_fn(CREATE_ERROR("Cannot access source %s: %s", source.c_str(), strerror(errno)));
+  }
+
+  if (access(target.c_str(), F_OK) != 0) {
+    fail_fn(CREATE_ERROR("Cannot access target %s: %s", target.c_str(), strerror(errno)));
+  }
+
+  BindMount(source, target, fail_fn);
+}
+
 // Create a private mount namespace and bind mount appropriate emulated
 // storage for the given user.
 static void MountEmulatedStorage(uid_t uid, jint mount_mode,
@@ -1504,6 +1546,60 @@
   }
 }
 
+// Bind mount all obb directories that are visible to this app.
+// If app data isolation is not enabled for this process, bind mount the whole obb
+// directory instead.
+static void BindMountAppObbDirs(JNIEnv* env, jobjectArray pkg_data_info_list,
+    uid_t uid, const char* process_name, jstring managed_nice_name, fail_fn_t fail_fn) {
+
+  auto extract_fn = std::bind(ExtractJString, env, process_name, managed_nice_name, _1);
+  const userid_t user_id = multiuser_get_user_id(uid);
+
+  // If FUSE is not ready for this user, skip it
+  // TODO(148772775): Pass primary volume name from zygote argument to here
+  std::string tmp = GetProperty("vold.fuse_running_users", "");
+  std::istringstream fuse_running_users(tmp);
+  bool user_found = false;
+  std::string s;
+  std::string user_id_str = std::to_string(user_id);
+  while (!user_found && std::getline(fuse_running_users, s, ',')) {
+    if (user_id_str == s) {
+      user_found = true;
+    }
+  }
+  if (!user_found) {
+    ALOGI("User %d is not running fuse yet, fuse_running_users=%s", user_id, tmp.c_str());
+    return;
+  }
+
+  // Fuse is ready, so we can start using fuse path.
+  int size = (pkg_data_info_list != nullptr) ? env->GetArrayLength(pkg_data_info_list) : 0;
+
+  if (size == 0) {
+    // App data isolation is not enabled for this process, so we bind mount to whole obb/ dir.
+    std::string source;
+    if (IsFilesystemSupported("sdcardfs")) {
+      source = StringPrintf("/mnt/runtime/default/emulated/%d/Android/obb", user_id);
+    } else {
+      source = StringPrintf("/mnt/pass_through/%d/emulated/%d/Android/obb", user_id, user_id);
+    }
+    std::string target(StringPrintf("/storage/emulated/%d/Android/obb", user_id));
+
+    if (access(source.c_str(), F_OK) != 0) {
+      fail_fn(CREATE_ERROR("Error accessing %s: %s", source.c_str(), strerror(errno)));
+    }
+    BindMount(source, target, fail_fn);
+    return;
+  }
+
+  // Bind mount each package obb directory
+  for (int i = 0; i < size; i += 3) {
+    jstring package_str = (jstring) (env->GetObjectArrayElement(pkg_data_info_list, i));
+    std::string packageName = extract_fn(package_str).value();
+    BindMountObbPackage(packageName, user_id, fail_fn);
+  }
+}
+
 // Utility routine to specialize a zygote child process.
 static void SpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray gids,
                              jint runtime_flags, jobjectArray rlimits,
@@ -1552,6 +1648,12 @@
     isolateJitProfile(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
   }
 
+  if ((mount_external != MOUNT_EXTERNAL_INSTALLER) &&
+        GetBoolProperty(kPropFuse, false) &&
+        GetBoolProperty(ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false)) {
+    BindMountAppObbDirs(env, pkg_data_info_list, uid, process_name, managed_nice_name, fail_fn);
+  }
+
   // If this zygote isn't root, it won't be able to create a process group,
   // since the directory is owned by root.
   if (!is_system_server && getuid() == 0) {
diff --git a/core/jni/core_jni_helpers.h b/core/jni/core_jni_helpers.h
index f03f427..8bb4d50 100644
--- a/core/jni/core_jni_helpers.h
+++ b/core/jni/core_jni_helpers.h
@@ -47,28 +47,32 @@
 static inline jfieldID GetFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
                                        const char* field_signature) {
     jfieldID res = env->GetFieldID(clazz, field_name, field_signature);
-    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s", field_name);
+    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
+                        field_signature);
     return res;
 }
 
 static inline jmethodID GetMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
                                          const char* method_signature) {
     jmethodID res = env->GetMethodID(clazz, method_name, method_signature);
-    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s", method_name);
+    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find method %s with signature %s", method_name,
+                        method_signature);
     return res;
 }
 
 static inline jfieldID GetStaticFieldIDOrDie(JNIEnv* env, jclass clazz, const char* field_name,
                                              const char* field_signature) {
     jfieldID res = env->GetStaticFieldID(clazz, field_name, field_signature);
-    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s", field_name);
+    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static field %s with signature %s", field_name,
+                        field_signature);
     return res;
 }
 
 static inline jmethodID GetStaticMethodIDOrDie(JNIEnv* env, jclass clazz, const char* method_name,
                                                const char* method_signature) {
     jmethodID res = env->GetStaticMethodID(clazz, method_name, method_signature);
-    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s", method_name);
+    LOG_ALWAYS_FATAL_IF(res == NULL, "Unable to find static method %s with signature %s",
+                        method_name, method_signature);
     return res;
 }
 
diff --git a/core/proto/android/content/intent.proto b/core/proto/android/content/intent.proto
index 014d71c..26e7dbb 100644
--- a/core/proto/android/content/intent.proto
+++ b/core/proto/android/content/intent.proto
@@ -65,7 +65,7 @@
     optional string identifier = 13 [ (.android.privacy).dest = DEST_EXPLICIT ];
 }
 
-// Next Tag: 11
+// Next Tag: 12
 message IntentFilterProto {
     option (.android.msg_privacy).dest = DEST_AUTOMATIC;
 
@@ -86,6 +86,7 @@
     optional int32 priority = 8;
     optional bool has_partial_types = 9;
     optional bool get_auto_verify = 10;
+    repeated string mime_groups = 11;
 }
 
 message AuthorityEntryProto {
diff --git a/core/proto/android/server/peopleservice.proto b/core/proto/android/server/peopleservice.proto
index e476c52..e65a2ab 100644
--- a/core/proto/android/server/peopleservice.proto
+++ b/core/proto/android/server/peopleservice.proto
@@ -50,6 +50,9 @@
 
   // Integer representation of conversation bit flags.
   optional int32 conversation_flags = 6;
+
+  // The phone number of the contact.
+  optional string contact_phone_number = 7;
 }
 
 // On disk data of events.
diff --git a/core/proto/android/server/powermanagerservice.proto b/core/proto/android/server/powermanagerservice.proto
index c039570..6850d01 100644
--- a/core/proto/android/server/powermanagerservice.proto
+++ b/core/proto/android/server/powermanagerservice.proto
@@ -366,6 +366,15 @@
     // Whether battery level is low or not.
     optional bool is_battery_level_low = 8;
 
+    // Denotes which threshold should be used for automatic Battery Saver triggering.
+    enum AutomaticTriggerEnum {
+        TRIGGER_PERCENTAGE = 0;
+        TRIGGER_DYNAMIC = 1;
+    }
+    // The value of Global.AUTOMATIC_POWER_SAVE_MODE. This is a cached value, so it could
+    // be slightly different from what's in GlobalSettingsProto.DynamicPowerSavings.
+    optional AutomaticTriggerEnum setting_automatic_trigger = 19;
+
     // The value of Global.LOW_POWER_MODE. This is a cached value, so it could
     // be slightly different from what's in GlobalSettingsProto.LowPowerMode.
     optional bool setting_battery_saver_enabled = 9;
@@ -390,5 +399,18 @@
     // using elapsed realtime as the timebase.
     optional int64 last_adaptive_battery_saver_changed_externally_elapsed = 17;
 
-    // Next tag: 19
+    // The default disable threshold for Dynamic Power Savings enabled battery saver.
+    optional int32 default_dynamic_disable_threshold = 20;
+
+    // When to disable battery saver again if it was enabled due to an external suggestion.
+    // Corresponds to Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD. This is a cached value,
+    // so it could be slightly different from what's in GlobalSettingsProto.DynamicPowerSavings.
+    optional int32 dynamic_disable_threshold = 21;
+
+    // Whether we've received a suggestion that battery saver should be on from an external app.
+    // Corresponds to Global.DYNAMIC_POWER_SAVINGS_ENABLED. This is a cached value, so it could
+    // be slightly different from what's in GlobalSettingsProto.DynamicPowerSavings.
+    optional bool dynamic_battery_saver_enabled = 22;
+
+    // Next tag: 23
 }
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index b0b9ce6f..08db454 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -275,6 +275,7 @@
     optional float adjust_divider_amount = 25;
     optional bool animating_bounds = 26;
     optional float minimize_amount = 27;
+    optional bool created_by_organizer = 28;
 }
 
 /* represents ActivityRecordProto */
diff --git a/core/proto/android/service/graphicsstats.proto b/core/proto/android/service/graphicsstats.proto
index 2de5b7f..bb654f0 100644
--- a/core/proto/android/service/graphicsstats.proto
+++ b/core/proto/android/service/graphicsstats.proto
@@ -33,8 +33,9 @@
 
 message GraphicsStatsProto {
     enum PipelineType {
-        GL = 0;
-        VULKAN = 1;
+        UNKNOWN = 0;
+        GL = 1;
+        VULKAN = 2;
     }
     option (android.msg_privacy).dest = DEST_AUTOMATIC;
 
diff --git a/core/proto/android/stats/devicepolicy/device_policy_enums.proto b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
index 782b269..3d8108d 100644
--- a/core/proto/android/stats/devicepolicy/device_policy_enums.proto
+++ b/core/proto/android/stats/devicepolicy/device_policy_enums.proto
@@ -179,4 +179,11 @@
   PROVISIONING_DPC_SETUP_STARTED = 152;
   PROVISIONING_DPC_SETUP_COMPLETED = 153;
   PROVISIONING_ORGANIZATION_OWNED_MANAGED_PROFILE = 154;
+  RESOLVER_CROSS_PROFILE_TARGET_OPENED = 155;
+  RESOLVER_SWITCH_TABS = 156;
+  RESOLVER_EMPTY_STATE_WORK_APPS_DISABLED = 157;
+  RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL= 158;
+  RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK= 159;
+  RESOLVER_EMPTY_STATE_NO_APPS_RESOLVED= 160;
+  RESOLVER_AUTOLAUNCH_CROSS_PROFILE_TARGET = 161;
 }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 488698a..814b8ac 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -399,6 +399,9 @@
     <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
     <protected-broadcast android:name="android.intent.action.ADVANCED_SETTINGS" />
     <protected-broadcast android:name="android.intent.action.APPLICATION_RESTRICTIONS_CHANGED" />
+    <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRED_DEVICES" />
+    <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_PAIRING_RESULT" />
+    <protected-broadcast android:name="com.android.server.adb.WIRELESS_DEBUG_STATUS" />
 
     <!-- Legacy -->
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
@@ -645,6 +648,9 @@
 
     <protected-broadcast android:name="android.intent.action.DEVICE_CUSTOMIZATION_READY" />
 
+    <!-- Added in R -->
+    <protected-broadcast android:name="android.app.action.RESET_PROTECTION_POLICY_CHANGED" />
+
     <!-- For tether entitlement recheck-->
     <protected-broadcast
         android:name="com.android.server.connectivity.tethering.PROVISIONING_RECHECK_ALARM" />
@@ -1197,6 +1203,15 @@
                 android:description="@string/permdesc_acceptHandovers"
                 android:protectionLevel="dangerous" />
 
+    <!-- Allows an application assigned to the Dialer role to be granted access to the telephony
+         call audio streams, both TX and RX.
+         <p>Protection level: signature|appop
+    -->
+    <permission android:name="android.permission.ACCESS_CALL_AUDIO"
+                android.label="@string/permlab_accessCallAudio"
+                android:description="@string/permdesc_accessCallAudio"
+                android:protectionLevel="signature|appop" />
+
     <!-- ====================================================================== -->
     <!-- Permissions for accessing the device microphone                        -->
     <!-- ====================================================================== -->
@@ -1951,6 +1966,18 @@
         android:description="@string/permdesc_modifyAudioSettings"
         android:protectionLevel="normal" />
 
+    <!-- ======================================== -->
+    <!-- Permissions for factory reset protection -->
+    <!-- ======================================== -->
+    <eat-comment />
+
+    <!-- @SystemApi Allows an application to set a factory reset protection (FRP) policy.
+         <p>Not for use by third-party applications.
+         @hide
+    -->
+    <permission android:name="android.permission.MANAGE_FACTORY_RESET_PROTECTION"
+        android:protectionLevel="signature|privileged"/>
+
     <!-- ================================== -->
     <!-- Permissions for accessing hardware -->
     <!-- ================================== -->
@@ -2747,7 +2774,7 @@
     <permission android:name="android.permission.READ_DEVICE_CONFIG"
         android:protectionLevel="signature|preinstalled" />
 
-    <!-- @SystemApi @hide Allows an application to monitor config settings access.
+    <!-- @hide Allows an application to monitor {@link android.provider.Settings.Config} access.
     <p>Not for use by third-party applications. -->
     <permission android:name="android.permission.MONITOR_DEVICE_CONFIG_ACCESS"
         android:protectionLevel="signature"/>
@@ -3057,8 +3084,7 @@
 
     <!-- Allows SystemUI to request third party controls.
          <p>Should only be requested by the System and required by
-         ControlsService declarations.
-         @hide
+         {@link android.service.controls.ControlsProviderService} declarations.
     -->
     <permission android:name="android.permission.BIND_CONTROLS"
         android:protectionLevel="signature" />
@@ -4953,16 +4979,6 @@
     <permission android:name="android.permission.ACCESS_LOCUS_ID_USAGE_STATS"
                 android:protectionLevel="signature|appPredictor" />
 
-    <!-- Feature Id for Country Detector. -->
-    <feature android:featureId="CountryDetector" android:label="@string/country_detector"/>
-    <!-- Feature Id for Location service. -->
-    <feature android:featureId="LocationService" android:label="@string/location_service"/>
-    <!-- Feature Id for Sensor Notification service. -->
-    <feature android:featureId="SensorNotificationService"
-             android:label="@string/sensor_notification_service"/>
-    <!-- Feature Id for Twilight service. -->
-    <feature android:featureId="TwilightService" android:label="@string/twilight_service"/>
-
     <application android:process="system"
                  android:persistent="true"
                  android:hasCode="false"
diff --git a/core/res/res/layout/chooser_grid.xml b/core/res/res/layout/chooser_grid.xml
index 24a21eb..5676049 100644
--- a/core/res/res/layout/chooser_grid.xml
+++ b/core/res/res/layout/chooser_grid.xml
@@ -78,11 +78,19 @@
                 android:layout_height="wrap_content"
                 android:visibility="gone">
             </TabWidget>
+            <View
+                android:id="@+id/resolver_tab_divider"
+                android:visibility="gone"
+                android:layout_alwaysShow="true"
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="?attr/colorBackgroundFloating"
+                android:foreground="?attr/dividerVertical" />
             <FrameLayout
                 android:id="@android:id/tabcontent"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content">
-                <com.android.internal.app.ResolverViewPager
+                <com.android.internal.widget.ViewPager
                     android:id="@+id/profile_pager"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"/>
diff --git a/core/res/res/layout/resolve_grid_item.xml b/core/res/res/layout/resolve_grid_item.xml
index 7098c95..9aecfd9 100644
--- a/core/res/res/layout/resolve_grid_item.xml
+++ b/core/res/res/layout/resolve_grid_item.xml
@@ -30,8 +30,8 @@
               android:background="?attr/selectableItemBackgroundBorderless">
 
     <ImageView android:id="@+id/icon"
-               android:layout_width="@dimen/resolver_icon_size"
-               android:layout_height="@dimen/resolver_icon_size"
+               android:layout_width="@dimen/chooser_icon_size"
+               android:layout_height="@dimen/chooser_icon_size"
                android:scaleType="fitCenter" />
 
     <!-- Size manually tuned to match specs -->
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index b4e6286..4359b10 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -94,6 +94,13 @@
                 android:layout_height="wrap_content"
                 android:visibility="gone">
             </TabWidget>
+            <View
+                android:id="@+id/resolver_tab_divider"
+                android:visibility="gone"
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="?attr/colorBackgroundFloating"
+                android:foreground="?attr/dividerVertical" />
             <FrameLayout
                 android:id="@android:id/tabcontent"
                 android:layout_width="match_parent"
@@ -102,10 +109,7 @@
                     android:id="@+id/profile_pager"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:divider="?attr/dividerVertical"
-                    android:footerDividersEnabled="false"
-                    android:headerDividersEnabled="false"
-                    android:dividerHeight="1dp"/>
+                    android:minHeight="@dimen/resolver_empty_state_height" />
             </FrameLayout>
         </LinearLayout>
     </TabHost>
diff --git a/core/res/res/layout/resolver_list_per_profile.xml b/core/res/res/layout/resolver_list_per_profile.xml
index d481eff..c4f9ed9 100644
--- a/core/res/res/layout/resolver_list_per_profile.xml
+++ b/core/res/res/layout/resolver_list_per_profile.xml
@@ -29,7 +29,6 @@
         android:elevation="@dimen/resolver_elevation"
         android:nestedScrollingEnabled="true"
         android:scrollbarStyle="outsideOverlay"
-        android:scrollIndicators="top|bottom"
         android:divider="@null"
         android:footerDividersEnabled="false"
         android:headerDividersEnabled="false"
diff --git a/core/res/res/layout/resolver_list_with_default.xml b/core/res/res/layout/resolver_list_with_default.xml
index b546738..72e8b0c 100644
--- a/core/res/res/layout/resolver_list_with_default.xml
+++ b/core/res/res/layout/resolver_list_with_default.xml
@@ -175,6 +175,14 @@
                 android:layout_height="wrap_content"
                 android:visibility="gone">
             </TabWidget>
+            <View
+                android:id="@+id/resolver_tab_divider"
+                android:visibility="gone"
+                android:layout_alwaysShow="true"
+                android:layout_width="match_parent"
+                android:layout_height="1dp"
+                android:background="?attr/colorBackgroundFloating"
+                android:foreground="?attr/dividerVertical" />
             <FrameLayout
                 android:id="@android:id/tabcontent"
                 android:layout_width="match_parent"
@@ -183,10 +191,7 @@
                     android:id="@+id/profile_pager"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:dividerHeight="1dp"
-                    android:divider="?attr/dividerVertical"
-                    android:footerDividersEnabled="false"
-                    android:headerDividersEnabled="false"/>
+                    android:minHeight="@dimen/resolver_empty_state_height" />
             </FrameLayout>
         </LinearLayout>
     </TabHost>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 16bed503..950f163 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -2809,6 +2809,9 @@
              case-sensitive, unlike formal RFC MIME types.  As a result,
              MIME types here should always use lower case letters.</em></p> -->
         <attr name="mimeType" format="string" />
+        <!-- Specify a group of MIME types that are handled. MIME types can be added and
+             removed to a package's MIME group via the PackageManager. -->
+        <attr name="mimeGroup" format="string" />
         <!-- Specify a URI scheme that is handled, as per
              {@link android.content.IntentFilter#addDataScheme
              IntentFilter.addDataScheme()}.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b82591f..70d8a02 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2460,6 +2460,12 @@
          rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max -->
     <string name="config_ethernet_tcp_buffers" translatable="false">524288,1048576,3145728,524288,1048576,2097152</string>
 
+    <!-- What source to use to estimate link upstream and downstream bandwidth capacities.
+         Default is carrier_config, but it should be set to modem if the modem is returning
+         predictive (instead of instantaneous) bandwidth estimate.
+         Values are carrier_config and modem. -->
+    <string name="config_bandwidthEstimateSource">carrier_config</string>
+
     <!-- Whether WiFi display is supported by this device.
          There are many prerequisites for this feature to work correctly.
          Here are a few of them:
@@ -2582,6 +2588,18 @@
     <string name="config_customAdbPublicKeyConfirmationSecondaryUserComponent"
             >com.android.systemui/com.android.systemui.usb.UsbDebuggingSecondaryUserActivity</string>
 
+    <!-- Name of the activity or service that prompts the user to reject, accept, or whitelist
+         a wireless network for wireless debugging.
+         Can be customized for other product types -->
+    <string name="config_customAdbWifiNetworkConfirmationComponent"
+            >com.android.systemui/com.android.systemui.wifi.WifiDebuggingActivity</string>
+
+    <!-- Name of the activity that prompts the secondary user to acknowledge she/he needs to
+         switch to the primary user to enable wireless debugging.
+         Can be customized for other product types -->
+    <string name="config_customAdbWifiNetworkConfirmationSecondaryUserComponent"
+            >com.android.systemui/com.android.systemui.wifi.WifiDebuggingSecondaryUserActivity</string>
+
     <!-- Component name of the activity that shows the usb containment status. -->
     <string name="config_usbContaminantActivity" translatable="false"
             >com.android.systemui/com.android.systemui.usb.UsbContaminantActivity</string>
@@ -3532,11 +3550,10 @@
      mode -->
     <string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
         <item>com.android.dialer</item>
+        <item>com.android.systemui</item>
+        <item>android</item>
     </string-array>
 
-    <!-- An array of packages which can listen for notifications on low ram devices. -->
-    <string-array translatable="false" name="config_allowedManagedServicesOnLowRamDevices" />
-
     <!-- The default value for transition animation scale found in developer settings.
          1.0 corresponds to 1x animator scale, 0 means that there will be no transition
          animations. Note that this is only a default and will be overridden by a
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index c44a0be..4f221d0 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -768,6 +768,7 @@
     <dimen name="chooser_header_scroll_elevation">4dp</dimen>
     <dimen name="chooser_max_collapsed_height">288dp</dimen>
     <dimen name="chooser_direct_share_label_placeholder_max_width">72dp</dimen>
+    <dimen name="chooser_icon_size">42dp</dimen>
     <dimen name="resolver_icon_size">32dp</dimen>
     <dimen name="resolver_button_bar_spacing">8dp</dimen>
     <dimen name="resolver_badge_size">18dp</dimen>
@@ -780,9 +781,6 @@
 
     <dimen name="chooser_action_button_icon_size">18dp</dimen>
 
-    <!-- Assistant handles -->
-    <dimen name="assist_handle_shadow_radius">2dp</dimen>
-
     <!-- For Waterfall Display -->
     <dimen name="waterfall_display_left_edge_size">0px</dimen>
     <dimen name="waterfall_display_top_edge_size">0px</dimen>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 80e5d1b..7f7bbe9 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -3014,6 +3014,7 @@
       <public name="minExtensionVersion" />
       <public name="allowNativeHeapPointerTagging" />
       <public name="preserveLegacyExternalStorage" />
+      <public name="mimeGroup" />
     </public-group>
 
     <public-group type="drawable" first-id="0x010800b5">
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index e7ad8eb..1445736 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -421,14 +421,6 @@
          [CHAR LIMIT=NONE] -->
     <string name="location_changed_notification_text">Tap to see your location settings.</string>
 
-    <!-- Feature Id for Country Detector. [CHAR LIMIT=NONE]-->
-    <string name="country_detector">Country Detector</string>
-    <!-- Feature Id for Location service. [CHAR LIMIT=NONE]-->
-    <string name="location_service">Location Service</string>
-    <!-- Feature Id for Sensor Notification service. [CHAR LIMIT=NONE]-->
-    <string name="sensor_notification_service">Sensor Notification Service</string>
-    <!-- Feature Id for Twilight service. [CHAR LIMIT=NONE]-->
-    <string name="twilight_service">Twilight Service</string>
 
     <!-- Factory reset warning dialog strings--> <skip />
     <!-- Shows up in the dialog's title to warn about an impeding factory reset. [CHAR LIMIT=NONE] -->
@@ -3535,6 +3527,12 @@
     <!-- Message of notification shown when ADB is actively connected to the phone. -->
     <string name="adb_active_notification_message">Tap to turn off USB debugging</string>
     <string name="adb_active_notification_message" product="tv">Select to disable USB debugging.</string>
+    <!-- Title of notification shown when ADB Wireless is actively connected to the phone. [CHAR LIMIT=NONE] -->
+    <string name="adbwifi_active_notification_title">Wireless debugging connected</string>
+    <!-- Message of notification shown when ADB Wireless is actively connected to the phone. [CHAR LIMIT=NONE] -->
+    <string name="adbwifi_active_notification_message">Tap to turn off wireless debugging</string>
+    <!-- Message of notification shown when ADB Wireless is actively connected to the TV. [CHAR LIMIT=NONE] -->
+    <string name="adbwifi_active_notification_message" product="tv">Select to disable wireless debugging.</string>
 
     <!-- Title of notification shown when Test Harness Mode is enabled. [CHAR LIMIT=NONE] -->
     <string name="test_harness_mode_notification_title">Test Harness Mode enabled</string>
@@ -5372,4 +5370,9 @@
     <string name="resolver_no_apps_available_explanation">We couldn\u2019t find any apps</string>
     <!-- Button which switches on the disabled work profile [CHAR LIMIT=NONE] -->
     <string name="resolver_switch_on_work">Switch on work</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permlab_accessCallAudio">Record or play audio in telephony calls</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_accessCallAudio">Allows this app, when assigned as default dialer application, to record or play audio in telephony calls.</string>
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 02d90a7..a3da411 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -473,6 +473,7 @@
   <java-symbol type="integer" name="config_num_physical_slots" />
   <java-symbol type="array" name="config_integrityRuleProviderPackages" />
   <java-symbol type="bool" name="config_useAssistantVolume" />
+  <java-symbol type="string" name="config_bandwidthEstimateSource" />
 
   <java-symbol type="color" name="tab_indicator_text_v4" />
 
@@ -2008,6 +2009,8 @@
   <java-symbol type="string" name="accessibility_binding_label" />
   <java-symbol type="string" name="adb_active_notification_message" />
   <java-symbol type="string" name="adb_active_notification_title" />
+  <java-symbol type="string" name="adbwifi_active_notification_message" />
+  <java-symbol type="string" name="adbwifi_active_notification_title" />
   <java-symbol type="string" name="test_harness_mode_notification_title" />
   <java-symbol type="string" name="test_harness_mode_notification_message" />
   <java-symbol type="string" name="console_running_notification_title" />
@@ -2153,6 +2156,8 @@
   <java-symbol type="integer" name="config_attentiveWarningDuration" />
   <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
   <java-symbol type="string" name="config_customAdbPublicKeyConfirmationSecondaryUserComponent" />
+  <java-symbol type="string" name="config_customAdbWifiNetworkConfirmationComponent" />
+  <java-symbol type="string" name="config_customAdbWifiNetworkConfirmationSecondaryUserComponent" />
   <java-symbol type="string" name="config_customVpnConfirmDialogComponent" />
   <java-symbol type="string" name="config_customVpnAlwaysOnDisconnectedDialogComponent" />
   <java-symbol type="string" name="config_platformVpnConfirmDialogComponent" />
@@ -3167,8 +3172,6 @@
   <java-symbol type="array" name="config_nonBlockableNotificationPackages" />
   <java-symbol type="array" name="config_priorityOnlyDndExemptPackages" />
 
-  <java-symbol type="array" name="config_allowedManagedServicesOnLowRamDevices" />
-
   <!-- Screen-size-dependent modes for picker dialogs. -->
   <java-symbol type="integer" name="time_picker_mode" />
   <java-symbol type="integer" name="date_picker_mode" />
@@ -3765,6 +3768,7 @@
   <java-symbol type="dimen" name="resolver_small_margin"/>
   <java-symbol type="dimen" name="resolver_edge_margin"/>
   <java-symbol type="dimen" name="resolver_elevation"/>
+  <java-symbol type="dimen" name="chooser_icon_size"/>
 
   <!-- For DropBox -->
   <java-symbol type="integer" name="config_dropboxLowPriorityBroadcastRateLimitPeriod" />
@@ -3840,9 +3844,6 @@
   <!-- For App Standby -->
   <java-symbol type="string" name="as_app_forced_to_restricted_bucket" />
 
-  <!-- Assistant handles -->
-  <java-symbol type="dimen" name="assist_handle_shadow_radius" />
-
   <!-- For Waterfall Display -->
   <java-symbol type="dimen" name="waterfall_display_left_edge_size" />
   <java-symbol type="dimen" name="waterfall_display_top_edge_size" />
@@ -3875,6 +3876,7 @@
   <java-symbol type="id" name="resolver_empty_state_title" />
   <java-symbol type="id" name="resolver_empty_state_subtitle" />
   <java-symbol type="id" name="resolver_empty_state_button" />
+  <java-symbol type="id" name="resolver_tab_divider" />
   <java-symbol type="string" name="resolver_cant_share_with_work_apps" />
   <java-symbol type="string" name="resolver_cant_share_with_personal_apps" />
   <java-symbol type="string" name="resolver_cant_share_cross_profile_explanation" />
diff --git a/core/res/res/xml/power_profile.xml b/core/res/res/xml/power_profile.xml
index 899d630..d8ec72f 100644
--- a/core/res/res/xml/power_profile.xml
+++ b/core/res/res/xml/power_profile.xml
@@ -51,6 +51,12 @@
       <value>0.1</value> <!-- ~1mA -->
   </array>
 
+  <!-- Additional power consumption by CPU excluding cluster and core when
+       running -->
+  <array name="cpu.active">
+      <value>0.1</value>
+  </array>
+
   <!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the
        number of CPU cores for that cluster.
 
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 18778b9..33fead6 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -88,15 +88,8 @@
         ":FrameworksCoreTests_install_loc_internal",
         ":FrameworksCoreTests_install_loc_sdcard",
         ":FrameworksCoreTests_install_loc_unspecified",
-        ":FrameworksCoreTests_install_split_base",
-        ":FrameworksCoreTests_install_split_feature_a",
         ":FrameworksCoreTests_install_use_perm_good",
         ":FrameworksCoreTests_install_uses_feature",
-        ":FrameworksCoreTests_install_uses_sdk_0",
-        ":FrameworksCoreTests_install_uses_sdk_q0",
-        ":FrameworksCoreTests_install_uses_sdk_r",
-        ":FrameworksCoreTests_install_uses_sdk_r0",
-        ":FrameworksCoreTests_install_uses_sdk_r5",
         ":FrameworksCoreTests_install_verifier_bad",
         ":FrameworksCoreTests_install_verifier_good",
         ":FrameworksCoreTests_keyset_permdef_sa_unone",
@@ -114,6 +107,7 @@
         ":FrameworksCoreTests_keyset_splata_api",
         ":FrameworksCoreTests_keyset_splat_api",
         ":FrameworksCoreTests_locales",
+        ":FrameworksCoreTests_overlay_config",
         ":FrameworksCoreTests_version_1",
         ":FrameworksCoreTests_version_1_diff",
         ":FrameworksCoreTests_version_1_nosys",
diff --git a/core/tests/coretests/apks/install-split-base/Android.bp b/core/tests/coretests/apks/install-split-base/Android.bp
deleted file mode 100644
index ddf75b2..0000000
--- a/core/tests/coretests/apks/install-split-base/Android.bp
+++ /dev/null
@@ -1,6 +0,0 @@
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_split_base",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-
-    srcs: ["**/*.java"],
-}
diff --git a/core/tests/coretests/apks/install_uses_sdk/Android.bp b/core/tests/coretests/apks/install_uses_sdk/Android.bp
deleted file mode 100644
index 92b09ed..0000000
--- a/core/tests/coretests/apks/install_uses_sdk/Android.bp
+++ /dev/null
@@ -1,39 +0,0 @@
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_uses_sdk_r0",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-    manifest: "AndroidManifest-r0.xml",
-
-    srcs: ["**/*.java"],
-}
-
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_uses_sdk_r5",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-    manifest: "AndroidManifest-r5.xml",
-
-    srcs: ["**/*.java"],
-}
-
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_uses_sdk_q0",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-    manifest: "AndroidManifest-q0.xml",
-
-    srcs: ["**/*.java"],
-}
-
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_uses_sdk_r",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-    manifest: "AndroidManifest-r.xml",
-
-    srcs: ["**/*.java"],
-}
-
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_uses_sdk_0",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
-    manifest: "AndroidManifest-0.xml",
-
-    srcs: ["**/*.java"],
-}
diff --git a/core/tests/coretests/apks/overlay_config/Android.bp b/core/tests/coretests/apks/overlay_config/Android.bp
new file mode 100644
index 0000000..9573557
--- /dev/null
+++ b/core/tests/coretests/apks/overlay_config/Android.bp
@@ -0,0 +1,4 @@
+android_test_helper_app {
+    name: "FrameworksCoreTests_overlay_config",
+    defaults: ["FrameworksCoreTests_apks_defaults"],
+}
diff --git a/core/tests/coretests/apks/overlay_config/AndroidManifest.xml b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
new file mode 100644
index 0000000..b15338e
--- /dev/null
+++ b/core/tests/coretests/apks/overlay_config/AndroidManifest.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.frameworks.coretests.overlay_config">
+
+    <application android:hasCode="false" />
+
+    <uses-sdk android:targetSdkVersion="21"/>
+
+    <overlay android:targetPackage="android"
+             android:targetName="TestResources" />
+</manifest>
diff --git a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
index 82a7b2c..f0e70a5 100644
--- a/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
@@ -90,6 +90,12 @@
     }
 
     @Test
+    public void testLoadAnimatedImage() {
+        assertNotNull("Can't find animated image",
+                mShortcutInfo.loadAnimatedImage(mTargetContext));
+    }
+
+    @Test
     public void testHtmlDescription() {
         final String htmlDescription = mTargetContext.getResources()
                 .getString(R.string.accessibility_shortcut_html_description);
diff --git a/core/tests/coretests/src/android/content/ContentResolverTest.java b/core/tests/coretests/src/android/content/ContentResolverTest.java
index 78c4420..1737bd0 100644
--- a/core/tests/coretests/src/android/content/ContentResolverTest.java
+++ b/core/tests/coretests/src/android/content/ContentResolverTest.java
@@ -234,4 +234,12 @@
         assertThat(type).isNull();
         assertThat(end).isLessThan(start + 5000);
     }
+
+    @Test
+    public void testCanonicalize() {
+        Uri canonical = mResolver.canonicalize(
+                Uri.parse("content://android.content.FakeProviderRemote/something"));
+        assertThat(canonical).isEqualTo(
+                Uri.parse("content://android.content.FakeProviderRemote/canonical"));
+    }
 }
diff --git a/core/tests/coretests/src/android/content/ContextTest.java b/core/tests/coretests/src/android/content/ContextTest.java
index f074233..f0997a6 100644
--- a/core/tests/coretests/src/android/content/ContextTest.java
+++ b/core/tests/coretests/src/android/content/ContextTest.java
@@ -16,11 +16,13 @@
 
 package android.content;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+
 import static org.junit.Assert.assertEquals;
 
 import android.app.ActivityThread;
+import android.hardware.display.DisplayManager;
 import android.os.UserHandle;
-import android.view.WindowManager;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
@@ -45,17 +47,16 @@
         final Context testContext =
                 InstrumentationRegistry.getInstrumentation().getTargetContext();
 
-        assertEquals(testContext.getDisplay().getDisplayId(), testContext.getDisplayId());
+        assertEquals(testContext.getDisplayNoVerify().getDisplayId(), testContext.getDisplayId());
     }
 
-    // TODO(b/128338354): Re-visit this test after introducing WindowContext
     @Test
     public void testDisplayIdForDefaultDisplayContext() {
         final Context testContext =
                 InstrumentationRegistry.getInstrumentation().getTargetContext();
-        final WindowManager wm = testContext.getSystemService(WindowManager.class);
+        final DisplayManager dm = testContext.getSystemService(DisplayManager.class);
         final Context defaultDisplayContext =
-                testContext.createDisplayContext(wm.getDefaultDisplay());
+                testContext.createDisplayContext(dm.getDisplay(DEFAULT_DISPLAY));
 
         assertEquals(defaultDisplayContext.getDisplay().getDisplayId(),
                 defaultDisplayContext.getDisplayId());
diff --git a/core/tests/coretests/src/android/content/FakeProviderRemote.java b/core/tests/coretests/src/android/content/FakeProviderRemote.java
index 7b9bdbc..1d7ba5d 100644
--- a/core/tests/coretests/src/android/content/FakeProviderRemote.java
+++ b/core/tests/coretests/src/android/content/FakeProviderRemote.java
@@ -54,4 +54,10 @@
     public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
         return 0;
     }
+
+    @Override
+    public Uri canonicalize(Uri uri) {
+        return new Uri.Builder().scheme(uri.getScheme()).authority(uri.getAuthority())
+                .appendPath("canonical").build();
+    }
 }
diff --git a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
index 62c9c98..7e4c138 100644
--- a/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
+++ b/core/tests/coretests/src/android/content/integrity/IntegrityFormulaTest.java
@@ -109,8 +109,8 @@
     @Test
     public void createGreaterThanOrEqualsToFormula_versionCode() {
         int versionCode = 12;
-        IntegrityFormula formula = IntegrityFormula.Application.versionCodeGreaterThanOrEqualTo(
-                versionCode);
+        IntegrityFormula formula =
+                IntegrityFormula.Application.versionCodeGreaterThanOrEqualTo(versionCode);
 
         AtomicFormula.LongAtomicFormula stringAtomicFormula =
                 (AtomicFormula.LongAtomicFormula) formula;
@@ -124,11 +124,11 @@
     public void createIsTrueFormula_preInstalled() {
         IntegrityFormula formula = IntegrityFormula.Application.isPreInstalled();
 
-        AtomicFormula.BooleanAtomicFormula stringAtomicFormula =
+        AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
                 (AtomicFormula.BooleanAtomicFormula) formula;
 
-        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
-        assertThat(stringAtomicFormula.getValue()).isTrue();
+        assertThat(booleanAtomicFormula.getKey()).isEqualTo(AtomicFormula.PRE_INSTALLED);
+        assertThat(booleanAtomicFormula.getValue()).isTrue();
     }
 
     @Test
@@ -136,8 +136,8 @@
         String packageName = "com.test.package";
         String certificateName = "certificate";
         IntegrityFormula formula1 = IntegrityFormula.Application.packageNameEquals(packageName);
-        IntegrityFormula formula2 = IntegrityFormula.Application.certificatesContain(
-                certificateName);
+        IntegrityFormula formula2 =
+                IntegrityFormula.Application.certificatesContain(certificateName);
 
         IntegrityFormula compoundFormula = IntegrityFormula.all(formula1, formula2);
 
@@ -149,8 +149,8 @@
         String packageName = "com.test.package";
         String certificateName = "certificate";
         IntegrityFormula formula1 = IntegrityFormula.Application.packageNameEquals(packageName);
-        IntegrityFormula formula2 = IntegrityFormula.Application.certificatesContain(
-                certificateName);
+        IntegrityFormula formula2 =
+                IntegrityFormula.Application.certificatesContain(certificateName);
 
         IntegrityFormula compoundFormula = IntegrityFormula.any(formula1, formula2);
 
@@ -166,4 +166,29 @@
 
         assertThat(compoundFormula.getTag()).isEqualTo(COMPOUND_FORMULA_TAG);
     }
+
+    @Test
+    public void createIsTrueFormula_stampNotTrusted() {
+        IntegrityFormula formula = IntegrityFormula.SourceStamp.notTrusted();
+
+        AtomicFormula.BooleanAtomicFormula booleanAtomicFormula =
+                (AtomicFormula.BooleanAtomicFormula) formula;
+
+        assertThat(booleanAtomicFormula.getKey()).isEqualTo(AtomicFormula.STAMP_TRUSTED);
+        assertThat(booleanAtomicFormula.getValue()).isFalse();
+    }
+
+    @Test
+    public void createEqualsFormula_stampCertificateHash() {
+        String stampCertificateHash = "test-cert";
+        IntegrityFormula formula =
+                IntegrityFormula.SourceStamp.stampCertificateHashEquals(stampCertificateHash);
+
+        AtomicFormula.StringAtomicFormula stringAtomicFormula =
+                (AtomicFormula.StringAtomicFormula) formula;
+
+        assertThat(stringAtomicFormula.getKey()).isEqualTo(AtomicFormula.STAMP_CERTIFICATE_HASH);
+        assertThat(stringAtomicFormula.getValue()).matches(stampCertificateHash);
+        assertThat(stringAtomicFormula.getIsHashedValue()).isTrue();
+    }
 }
diff --git a/core/tests/coretests/src/android/os/PowerManagerTest.java b/core/tests/coretests/src/android/os/PowerManagerTest.java
index ea0a0fd..37e8d59 100644
--- a/core/tests/coretests/src/android/os/PowerManagerTest.java
+++ b/core/tests/coretests/src/android/os/PowerManagerTest.java
@@ -244,6 +244,28 @@
     }
 
     @Test
+    public void testGetThermalHeadroom() throws Exception {
+        float headroom = mPm.getThermalHeadroom(0);
+        // If the device doesn't support thermal headroom, return early
+        if (Float.isNaN(headroom)) {
+            return;
+        }
+        assertTrue("Expected non-negative headroom", headroom >= 0.0f);
+        assertTrue("Expected reasonably small headroom", headroom < 10.0f);
+
+        // Call again immediately to ensure rate limiting works
+        headroom = mPm.getThermalHeadroom(0);
+        assertTrue("Expected NaN because of rate limiting", Float.isNaN(headroom));
+
+        // Sleep for a second before attempting to call again so as to not get rate limited
+        Thread.sleep(1000);
+        headroom = mPm.getThermalHeadroom(5);
+        assertFalse("Expected data to still be available", Float.isNaN(headroom));
+        assertTrue("Expected non-negative headroom", headroom >= 0.0f);
+        assertTrue("Expected reasonably small headroom", headroom < 10.0f);
+    }
+
+    @Test
     public void testUserspaceRebootNotSupported_throwsUnsupportedOperationException() {
         // Can't use assumption framework with AndroidTestCase :(
         if (mPm.isRebootingUserspaceSupported()) {
diff --git a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
index a24b4e0..4c2ca7e 100644
--- a/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
+++ b/core/tests/coretests/src/android/service/controls/ControlProviderServiceTest.java
@@ -21,12 +21,17 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.Manifest;
 import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
 import android.content.IIntentSender;
 import android.content.Intent;
+import android.content.res.Resources;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -43,6 +48,7 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -58,15 +64,24 @@
 @RunWith(AndroidJUnit4.class)
 public class ControlProviderServiceTest {
 
+    private static final ComponentName TEST_SYSUI_COMPONENT =
+            ComponentName.unflattenFromString("sysui/.test.cls");
+    private static final ComponentName TEST_COMPONENT =
+            ComponentName.unflattenFromString("test.pkg/.test.cls");
+
     private IBinder mToken = new Binder();
     @Mock
     private IControlsActionCallback.Stub mActionCallback;
     @Mock
-    private IControlsLoadCallback.Stub mLoadCallback;
-    @Mock
     private IControlsSubscriber.Stub mSubscriber;
     @Mock
     private IIntentSender mIIntentSender;
+    @Mock
+    private Resources mResources;
+    @Mock
+    private Context mContext;
+    @Captor
+    private ArgumentCaptor<Intent> mIntentArgumentCaptor;
 
     private PendingIntent mPendingIntent;
     private FakeControlsProviderService mControlsProviderService;
@@ -79,11 +94,13 @@
 
         when(mActionCallback.asBinder()).thenCallRealMethod();
         when(mActionCallback.queryLocalInterface(any())).thenReturn(mActionCallback);
-        when(mLoadCallback.asBinder()).thenCallRealMethod();
-        when(mLoadCallback.queryLocalInterface(any())).thenReturn(mLoadCallback);
         when(mSubscriber.asBinder()).thenCallRealMethod();
         when(mSubscriber.queryLocalInterface(any())).thenReturn(mSubscriber);
 
+        when(mResources.getString(com.android.internal.R.string.config_systemUIServiceComponent))
+                .thenReturn(TEST_SYSUI_COMPONENT.flattenToString());
+        when(mContext.getResources()).thenReturn(mResources);
+
         Bundle b = new Bundle();
         b.putBinder(ControlsProviderService.CALLBACK_TOKEN, mToken);
         Intent intent = new Intent();
@@ -102,22 +119,28 @@
         Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
                 .setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
 
-        @SuppressWarnings("unchecked")
-        ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+                ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+        ArgumentCaptor<Control> controlCaptor =
+                ArgumentCaptor.forClass(Control.class);
 
         ArrayList<Control> list = new ArrayList<>();
         list.add(control1);
         list.add(control2);
 
         mControlsProviderService.setControls(list);
-        mControlsProvider.load(mLoadCallback);
+        mControlsProvider.load(mSubscriber);
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
-        verify(mLoadCallback).accept(eq(mToken), captor.capture());
-        List<Control> l = captor.getValue();
-        assertEquals(2, l.size());
-        assertTrue(equals(control1, l.get(0)));
-        assertTrue(equals(control2, l.get(1)));
+        verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+        subscriptionCaptor.getValue().request(1000);
+
+        verify(mSubscriber, times(2)).onNext(eq(mToken), controlCaptor.capture());
+        List<Control> values = controlCaptor.getAllValues();
+        assertTrue(equals(values.get(0), list.get(0)));
+        assertTrue(equals(values.get(1), list.get(1)));
+
+        verify(mSubscriber).onComplete(eq(mToken));
     }
 
     @Test
@@ -128,50 +151,57 @@
                 .build();
         Control statelessControl = new Control.StatelessBuilder(control).build();
 
-        @SuppressWarnings("unchecked")
-        ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+                ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+        ArgumentCaptor<Control> controlCaptor =
+                ArgumentCaptor.forClass(Control.class);
 
         ArrayList<Control> list = new ArrayList<>();
         list.add(control);
 
         mControlsProviderService.setControls(list);
-        mControlsProvider.load(mLoadCallback);
+        mControlsProvider.load(mSubscriber);
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
-        verify(mLoadCallback).accept(eq(mToken), captor.capture());
-        List<Control> l = captor.getValue();
-        assertEquals(1, l.size());
-        assertFalse(equals(control, l.get(0)));
-        assertTrue(equals(statelessControl, l.get(0)));
-        assertEquals(Control.STATUS_UNKNOWN, l.get(0).getStatus());
+        verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+        subscriptionCaptor.getValue().request(1000);
+
+        verify(mSubscriber).onNext(eq(mToken), controlCaptor.capture());
+        Control c = controlCaptor.getValue();
+        assertFalse(equals(control, c));
+        assertTrue(equals(statelessControl, c));
+        assertEquals(Control.STATUS_UNKNOWN, c.getStatus());
+
+        verify(mSubscriber).onComplete(eq(mToken));
     }
 
     @Test
-    public void testLoadSuggested_withMaxNumber() throws RemoteException {
+    public void testOnLoadSuggested_allStateless() throws RemoteException {
         Control control1 = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
         Control control2 = new Control.StatelessBuilder("TEST_ID_2", mPendingIntent)
                 .setDeviceType(DeviceTypes.TYPE_AIR_FRESHENER).build();
 
-        @SuppressWarnings("unchecked")
-        ArgumentCaptor<List<Control>> captor = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<IControlsSubscription.Stub> subscriptionCaptor =
+                ArgumentCaptor.forClass(IControlsSubscription.Stub.class);
+        ArgumentCaptor<Control> controlCaptor =
+                ArgumentCaptor.forClass(Control.class);
 
         ArrayList<Control> list = new ArrayList<>();
         list.add(control1);
         list.add(control2);
 
-        final int maxSuggested = 1;
-
         mControlsProviderService.setControls(list);
-        mControlsProvider.loadSuggested(maxSuggested, mLoadCallback);
+        mControlsProvider.loadSuggested(mSubscriber);
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
 
-        verify(mLoadCallback).accept(eq(mToken), captor.capture());
-        List<Control> l = captor.getValue();
-        assertEquals(maxSuggested, l.size());
+        verify(mSubscriber).onSubscribe(eq(mToken), subscriptionCaptor.capture());
+        subscriptionCaptor.getValue().request(1);
 
-        for (int i = 0; i < maxSuggested; ++i) {
-            assertTrue(equals(list.get(i), l.get(i)));
-        }
+        verify(mSubscriber).onNext(eq(mToken), controlCaptor.capture());
+        Control c = controlCaptor.getValue();
+        assertTrue(equals(c, list.get(0)));
+
+        verify(mSubscriber).onComplete(eq(mToken));
     }
 
     @Test
@@ -213,6 +243,21 @@
                 ControlAction.RESPONSE_OK);
     }
 
+    @Test
+    public void testRequestAdd() {
+        Control control = new Control.StatelessBuilder("TEST_ID", mPendingIntent).build();
+        ControlsProviderService.requestAddControl(mContext, TEST_COMPONENT, control);
+
+        verify(mContext).sendBroadcast(mIntentArgumentCaptor.capture(),
+                eq(Manifest.permission.BIND_CONTROLS));
+        Intent intent = mIntentArgumentCaptor.getValue();
+        assertEquals(ControlsProviderService.ACTION_ADD_CONTROL, intent.getAction());
+        assertEquals(TEST_SYSUI_COMPONENT.getPackageName(), intent.getPackage());
+        assertEquals(TEST_COMPONENT, intent.getParcelableExtra(Intent.EXTRA_COMPONENT_NAME));
+        assertTrue(equals(control,
+                intent.getParcelableExtra(ControlsProviderService.EXTRA_CONTROL)));
+    }
+
     private static boolean equals(Control c1, Control c2) {
         if (c1 == c2) return true;
         if (c1 == null || c2 == null) return false;
@@ -244,22 +289,19 @@
         }
 
         @Override
-        public void loadSuggestedControls(int maxNumber, Consumer<List<Control>> cb) {
-            cb.accept(mControls);
-        }
-
-        @Override
         public Publisher<Control> publisherFor(List<String> ids) {
             return new Publisher<Control>() {
                 public void subscribe(final Subscriber s) {
-                    s.onSubscribe(new Subscription() {
-                            public void request(long n) {
-                                for (Control c : mControls) {
-                                    s.onNext(c);
-                                }
-                            }
-                            public void cancel() {}
-                        });
+                    s.onSubscribe(createSubscription(s, mControls));
+                }
+            };
+        }
+
+        @Override
+        public Publisher<Control> publisherForSuggested() {
+            return new Publisher<Control>() {
+                public void subscribe(final Subscriber s) {
+                    s.onSubscribe(createSubscription(s, mControls));
                 }
             };
         }
@@ -269,7 +311,19 @@
                 Consumer<Integer> cb) {
             cb.accept(ControlAction.RESPONSE_OK);
         }
+
+        private Subscription createSubscription(Subscriber s, List<Control> controls) {
+            return new Subscription() {
+                public void request(long n) {
+                    int i = 0;
+                    for (Control c : mControls) {
+                        if (i++ < n) s.onNext(c);
+                        else break;
+                    }
+                    s.onComplete();
+                }
+                public void cancel() {}
+            };
+        }
     }
 }
-
-
diff --git a/core/tests/coretests/src/android/util/EventLogTest.java b/core/tests/coretests/src/android/util/EventLogTest.java
new file mode 100644
index 0000000..94e72c4
--- /dev/null
+++ b/core/tests/coretests/src/android/util/EventLogTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.util;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.util.EventLog.Event;
+
+import junit.framework.AssertionFailedError;
+
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/** Unit tests for {@link android.util.EventLog} */
+public class EventLogTest {
+
+    @Test
+    public void testWithNewData() throws Throwable {
+        Event event = createEvent(() -> {
+            EventLog.writeEvent(314,  123);
+        }, 314);
+
+        assertTrue(event.withNewData(12345678L).getData().equals(12345678L));
+        assertTrue(event.withNewData(2.718f).getData().equals(2.718f));
+        assertTrue(event.withNewData("test string").getData().equals("test string"));
+
+        Object[] objects = ((Object[]) event.withNewData(
+                new Object[] {111, 2.22f, 333L, "444"}).getData());
+        assertEquals(4, objects.length);
+        assertTrue(objects[0].equals(111));
+        assertTrue(objects[1].equals(2.22f));
+        assertTrue(objects[2].equals(333L));
+        assertTrue(objects[3].equals("444"));
+    }
+
+    /**
+     * Creates an Event object. Only the native code has the serialization and deserialization logic
+     * so need to actually emit a real log in order to generate the object.
+     */
+    private Event createEvent(Runnable generator, int expectedTag) throws Exception {
+        Long markerData = System.currentTimeMillis();
+        EventLog.writeEvent(expectedTag, markerData);
+        generator.run();
+
+        List<Event> events = new ArrayList<>();
+        // Give the message some time to show up in the log
+        Thread.sleep(20);
+        EventLog.readEvents(new int[] {expectedTag}, events);
+        for (int i = 0; i < events.size() - 1; i++) {
+            if (markerData.equals(events.get(i).getData())) {
+                return events.get(i + 1);
+            }
+        }
+        throw new AssertionFailedError("Unable to locate marker event");
+    }
+}
diff --git a/core/tests/coretests/src/android/util/LongSparseArrayTest.java b/core/tests/coretests/src/android/util/LongSparseArrayTest.java
new file mode 100644
index 0000000..bf3f0f5
--- /dev/null
+++ b/core/tests/coretests/src/android/util/LongSparseArrayTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.util;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.function.LongObjPredicate;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * Tests for {@link LongSparseArray}.
+ */
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class LongSparseArrayTest {
+    @Test
+    public void testRemoveIf() {
+        final LongSparseArray<Integer> sparseArray = new LongSparseArray();
+        for (int i = 0; i < 10; ++i) {
+            for (int j = 100; j < 110; ++j) {
+                sparseArray.put(i, j);
+                sparseArray.put(-i, j);
+                sparseArray.put(j, -i);
+                sparseArray.put(-j, -i);
+            }
+        }
+
+        final LongObjPredicate<Integer> predicate = (value, obj) -> (value < 0 && obj < 0);
+        sparseArray.removeIf(predicate);
+
+        for (int i = 0; i < sparseArray.size(); ++i) {
+            assertThat(predicate.test(sparseArray.keyAt(i), sparseArray.valueAt(i)))
+                    .isFalse();
+        }
+    }
+}
diff --git a/core/tests/coretests/src/android/view/CutoutSpecificationTest.java b/core/tests/coretests/src/android/view/CutoutSpecificationTest.java
index 1f831bb..7872810 100644
--- a/core/tests/coretests/src/android/view/CutoutSpecificationTest.java
+++ b/core/tests/coretests/src/android/view/CutoutSpecificationTest.java
@@ -21,10 +21,27 @@
 import static org.testng.Assert.assertThrows;
 
 import android.graphics.Rect;
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
 
+/**
+ * Tests for {@link CutoutSpecification} used by {@link DisplayCutout}.
+ *
+ * <p>Build/Install/Run:
+ *  atest FrameworksCoreTests:CutoutSpecificationTest
+ *
+ * <p>This test class is a part of Window Manager Service tests and specified in
+ * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}.
+ */
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+@Presubmit
 public class CutoutSpecificationTest {
     private static final String WITHOUT_BIND_CUTOUT_SPECIFICATION = "M 0,0\n"
             + "h 48\n"
@@ -69,6 +86,13 @@
             + "z\n"
             + "@right\n"
             + "@bind_right_cutout\n"
+            + "@bottom\n"
+            + "M 0,0\n"
+            + "h -24\n"
+            + "v -48\n"
+            + "h 48\n"
+            + "v 48\n"
+            + "z\n"
             + "@dp";
     private static final String CORNER_CUTOUT_SPECIFICATION = "M 0,0\n"
             + "h 1\n"
@@ -141,13 +165,66 @@
     }
 
     @Test
+    public void parse_withBindMarker_shouldHaveTopBound() {
+        CutoutSpecification cutoutSpecification = mParser.parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getTopBound()).isEqualTo(new Rect(0, 0, 168, 168));
+    }
+
+    @Test
     public void parse_withBindMarker_shouldHaveRightBound() {
         CutoutSpecification cutoutSpecification = mParser.parse(WITH_BIND_CUTOUT_SPECIFICATION);
         assertThat(cutoutSpecification.getRightBound()).isEqualTo(new Rect(912, 960, 1080, 1128));
     }
 
     @Test
-    public void parse_tallCutout_shouldBeDone() {
+    public void parse_withBindMarker_shouldHaveBottomBound() {
+        CutoutSpecification cutoutSpecification = mParser.parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getBottomBound()).isEqualTo(new Rect(456, 1752, 624, 1920));
+    }
+
+    @Test
+    public void parse_withBindMarker_shouldMatchExpectedSafeInset() {
+        CutoutSpecification cutoutSpecification = mParser.parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getSafeInset()).isEqualTo(new Rect(168, 168, 168, 168));
+    }
+
+    @Test
+    public void parse_withBindMarker_tabletLikeDevice_shouldHaveLeftBound() {
+        CutoutSpecification cutoutSpecification = new CutoutSpecification.Parser(3.5f, 1920, 1080)
+                .parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getLeftBound()).isEqualTo(new Rect(0, 540, 168, 708));
+    }
+
+    @Test
+    public void parse_withBindMarker_tabletLikeDevice_shouldHaveTopBound() {
+        CutoutSpecification cutoutSpecification = new CutoutSpecification.Parser(3.5f, 1920, 1080)
+                .parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getTopBound()).isEqualTo(new Rect(0, 0, 168, 168));
+    }
+
+    @Test
+    public void parse_withBindMarker_tabletLikeDevice_shouldHaveRightBound() {
+        CutoutSpecification cutoutSpecification = new CutoutSpecification.Parser(3.5f, 1920, 1080)
+                .parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getRightBound()).isEqualTo(new Rect(1752, 540, 1920, 708));
+    }
+
+    @Test
+    public void parse_withBindMarker_tabletLikeDevice_shouldHaveBottomBound() {
+        CutoutSpecification cutoutSpecification = new CutoutSpecification.Parser(3.5f, 1920, 1080)
+                .parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getBottomBound()).isEqualTo(new Rect(876, 912, 1044, 1080));
+    }
+
+    @Test
+    public void parse_withBindMarker_tabletLikeDevice_shouldMatchExpectedSafeInset() {
+        CutoutSpecification cutoutSpecification = new CutoutSpecification.Parser(3.5f, 1920, 1080)
+                .parse(WITH_BIND_CUTOUT_SPECIFICATION);
+        assertThat(cutoutSpecification.getSafeInset()).isEqualTo(new Rect(168, 0, 168, 168));
+    }
+
+    @Test
+    public void parse_tallCutout_topBoundShouldMatchExpectedHeight() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 0,0\n"
                 + "L -48, 0\n"
                 + "L -44.3940446283, 36.0595537175\n"
@@ -162,7 +239,7 @@
     }
 
     @Test
-    public void parse_wideCutout_shouldBeDone() {
+    public void parse_wideCutout_topBoundShouldMatchExpectedWidth() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 0,0\n"
                 + "L -72, 0\n"
                 + "L -69.9940446283, 20.0595537175\n"
@@ -177,7 +254,7 @@
     }
 
     @Test
-    public void parse_narrowCutout_shouldBeDone() {
+    public void parse_narrowCutout_topBoundShouldHaveExpectedWidth() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 0,0\n"
                 + "L -24, 0\n"
                 + "L -21.9940446283, 20.0595537175\n"
@@ -192,7 +269,7 @@
     }
 
     @Test
-    public void parse_doubleCutout_shouldBeDone() {
+    public void parse_doubleCutout_topBoundShouldHaveExpectedHeight() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 0,0\n"
                 + "L -72, 0\n"
                 + "L -69.9940446283, 20.0595537175\n"
@@ -217,7 +294,7 @@
     }
 
     @Test
-    public void parse_cornerCutout_shouldBeDone() {
+    public void parse_cornerCutout_topBoundShouldHaveExpectedHeight() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 0,0\n"
                 + "L -48, 0\n"
                 + "C -48,48 -48,48 0,48\n"
@@ -229,7 +306,7 @@
     }
 
     @Test
-    public void parse_holeCutout_shouldBeDone() {
+    public void parse_holeCutout_shouldMatchExpectedInset() {
         CutoutSpecification cutoutSpecification = mParser.parse("M 20.0,20.0\n"
                 + "h 136\n"
                 + "v 136\n"
@@ -259,4 +336,38 @@
         assertThat(cutoutSpecification.getSafeInset())
                 .isEqualTo(new Rect(6, 0, 8, 0));
     }
+
+    @Test
+    public void parse_bottomLeftSpec_withBindLeftMarker_shouldBeLeftBound() {
+        CutoutSpecification cutoutSpecification =
+                new CutoutSpecification.Parser(2f, 400, 200)
+                        .parse("@bottom"
+                                + "M 0,0\n"
+                                + "v -10\n"
+                                + "h 10\n"
+                                + "v 10\n"
+                                + "z\n"
+                                + "@left\n"
+                                + "@bind_left_cutout");
+
+        assertThat(cutoutSpecification.getLeftBound())
+                .isEqualTo(new Rect(0, 190, 10, 200));
+    }
+
+    @Test
+    public void parse_bottomRightSpec_withBindRightMarker_shouldBeRightBound() {
+        CutoutSpecification cutoutSpecification =
+                new CutoutSpecification.Parser(2f, 400, 200)
+                        .parse("@bottom"
+                                + "M 0,0\n"
+                                + "v -10\n"
+                                + "h -10\n"
+                                + "v 10\n"
+                                + "z\n"
+                                + "@right\n"
+                                + "@bind_right_cutout");
+
+        assertThat(cutoutSpecification.getRightBound())
+                .isEqualTo(new Rect(390, 190, 400, 200));
+    }
 }
diff --git a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
index 7c78bce..7f0e0d2 100644
--- a/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/ImeInsetsSourceConsumerTest.java
@@ -61,7 +61,7 @@
                 .setName("testSurface")
                 .build();
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
-            ViewRootImpl viewRootImpl = new ViewRootImpl(mContext, mContext.getDisplay());
+            ViewRootImpl viewRootImpl = new ViewRootImpl(mContext, mContext.getDisplayNoVerify());
             try {
                 viewRootImpl.setView(new TextView(mContext), new LayoutParams(), null);
             } catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 24fe2a0..7737b1a 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -110,7 +110,7 @@
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             Context context = InstrumentationRegistry.getTargetContext();
             // cannot mock ViewRootImpl since it's final.
-            mViewRoot = new ViewRootImpl(context, context.getDisplay());
+            mViewRoot = new ViewRootImpl(context, context.getDisplayNoVerify());
             try {
                 mViewRoot.setView(new TextView(context), new LayoutParams(), null);
             } catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
index 5e9e2f0..754c679 100644
--- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java
@@ -77,7 +77,8 @@
         instrumentation.runOnMainSync(() -> {
             final Context context = instrumentation.getTargetContext();
             // cannot mock ViewRootImpl since it's final.
-            final ViewRootImpl viewRootImpl = new ViewRootImpl(context, context.getDisplay());
+            final ViewRootImpl viewRootImpl = new ViewRootImpl(context,
+                    context.getDisplayNoVerify());
             try {
                 viewRootImpl.setView(new TextView(context), new LayoutParams(), null);
             } catch (BadTokenException e) {
diff --git a/core/tests/coretests/src/android/view/ViewRootImplTest.java b/core/tests/coretests/src/android/view/ViewRootImplTest.java
index df6ed8c..e2adbcc 100644
--- a/core/tests/coretests/src/android/view/ViewRootImplTest.java
+++ b/core/tests/coretests/src/android/view/ViewRootImplTest.java
@@ -61,7 +61,7 @@
 
         InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
             mViewRootImpl = new ViewRootImplAccessor(
-                    new ViewRootImpl(mContext, mContext.getDisplay()));
+                    new ViewRootImpl(mContext, mContext.getDisplayNoVerify()));
         });
     }
 
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
index ade1e0d..79e7c50 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityNodeInfoTest.java
@@ -46,7 +46,7 @@
     // The number of fields tested in the corresponding CTS AccessibilityNodeInfoTest:
     // See fullyPopulateAccessibilityNodeInfo, assertEqualsAccessibilityNodeInfo,
     // and assertAccessibilityNodeInfoCleared in that class.
-    private static final int NUM_MARSHALLED_PROPERTIES = 38;
+    private static final int NUM_MARSHALLED_PROPERTIES = 39;
 
     /**
      * The number of properties that are purposely not marshalled
diff --git a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
index b71c580..75a7504 100644
--- a/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
+++ b/core/tests/coretests/src/android/view/accessibility/AccessibilityServiceConnectionImpl.java
@@ -157,4 +157,8 @@
     }
 
     public void takeScreenshot(int displayId, RemoteCallback callback) {}
+
+    public void setTouchExplorationPassthroughRegion(int displayId, Region region) {}
+
+    public void setGestureDetectionPassthroughRegion(int displayId, Region region) {}
 }
diff --git a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
index a602fa3..0a094c61d 100644
--- a/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
+++ b/core/tests/coretests/src/android/widget/EditorCursorDragTest.java
@@ -25,6 +25,9 @@
 import static androidx.test.espresso.action.ViewActions.replaceText;
 import static androidx.test.espresso.matcher.ViewMatchers.withId;
 
+import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
+
 import static org.hamcrest.Matchers.emptyString;
 import static org.hamcrest.Matchers.not;
 import static org.junit.Assert.assertFalse;
@@ -32,11 +35,14 @@
 
 import android.app.Activity;
 import android.app.Instrumentation;
+import android.text.Layout;
+import android.util.Log;
 import android.view.InputDevice;
 import android.view.MotionEvent;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
+import androidx.test.filters.Suppress;
 import androidx.test.rule.ActivityTestRule;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -44,20 +50,24 @@
 
 import com.google.common.base.Strings;
 
-import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.atomic.AtomicLong;
+
 @RunWith(AndroidJUnit4.class)
 @SmallTest
 public class EditorCursorDragTest {
+    private static final String LOG_TAG = EditorCursorDragTest.class.getSimpleName();
+
+    private static final AtomicLong sTicker = new AtomicLong(1);
+
     @Rule
     public ActivityTestRule<TextViewActivity> mActivityRule = new ActivityTestRule<>(
             TextViewActivity.class);
 
-    private boolean mOriginalFlagValue;
     private Instrumentation mInstrumentation;
     private Activity mActivity;
 
@@ -65,13 +75,6 @@
     public void before() throws Throwable {
         mInstrumentation = InstrumentationRegistry.getInstrumentation();
         mActivity = mActivityRule.getActivity();
-        mOriginalFlagValue = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
-    }
-
-    @After
-    public void after() throws Throwable {
-        Editor.FLAG_ENABLE_CURSOR_DRAG = mOriginalFlagValue;
     }
 
     @Test
@@ -119,13 +122,11 @@
         onView(withId(R.id.textview)).perform(replaceText(text));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
 
-        // Swipe along a diagonal path. This should drag the cursor.
-        onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
-        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
-
-        // Swipe along a steeper diagonal path. This should still drag the cursor.
+        // Swipe along a diagonal path. This should drag the cursor. Because we snap the finger to
+        // the handle as the touch moves downwards (and because we have some slop to avoid jumping
+        // across lines), the cursor position will end up higher than the finger position.
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
-        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
+        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("1")));
 
         // Swipe right-down along a very steep diagonal path. This should not drag the cursor.
         // Normally this would trigger a scroll, but since the full view fits on the screen there
@@ -133,12 +134,15 @@
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
         onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
 
+        // Tap to clear the selection.
+        int index = text.indexOf("line9");
+        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+        onView(withId(R.id.textview)).check(hasSelection(emptyString()));
+        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+
         // Swipe right-up along a very steep diagonal path. This should not drag the cursor.
         // Normally this would trigger a scroll, but since the full view fits on the screen there
         // is nothing to scroll and the gesture will trigger a selection drag.
-        int index = text.indexOf("line9");
-        onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
-        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
         onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
     }
@@ -154,13 +158,11 @@
         onView(withId(R.id.textview)).perform(replaceText(text));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
 
-        // Swipe along a diagonal path. This should drag the cursor.
-        onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("2")));
-        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("2")));
-
-        // Swipe along a steeper diagonal path. This should still drag the cursor.
+        // Swipe along a diagonal path. This should drag the cursor. Because we snap the finger to
+        // the handle as the touch moves downwards (and because we have some slop to avoid jumping
+        // across lines), the cursor position will end up higher than the finger position.
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("3")));
-        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("3")));
+        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("1")));
 
         // Swipe right-down along a very steep diagonal path. This should not drag the cursor.
         // Normally this would trigger a scroll up, but since the view is already at the top there
@@ -168,11 +170,14 @@
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line1"), text.indexOf("7")));
         onView(withId(R.id.textview)).check(hasSelection(not(emptyString())));
 
-        // Swipe right-up along a very steep diagonal path. This should not drag the cursor. This
-        // will trigger a downward scroll and the cursor position will not change.
+        // Tap to clear the selection.
         int index = text.indexOf("line9");
         onView(withId(R.id.textview)).perform(clickOnTextAtIndex(index));
+        onView(withId(R.id.textview)).check(hasSelection(emptyString()));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
+
+        // Swipe right-up along a very steep diagonal path. This should not drag the cursor. This
+        // will trigger a downward scroll and the cursor position will not change.
         onView(withId(R.id.textview)).perform(dragOnText(text.indexOf("line7"), text.indexOf("1")));
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(index));
     }
@@ -387,12 +392,14 @@
         assertFalse(editor.getSelectionController().isCursorBeingModified());
     }
 
+    @Suppress // b/149712851
     @Test // Reproduces b/147366705
     public void testCursorDrag_nonSelectableTextView() throws Throwable {
         String text = "Hello world!";
         TextView tv = mActivity.findViewById(R.id.nonselectable_textview);
         tv.setText(text);
         Editor editor = tv.getEditorForTesting();
+        assertThat(editor).isNotNull();
 
         // Simulate a tap. No error should be thrown.
         long event1Time = 1001;
@@ -404,6 +411,68 @@
                 dragOnText(text.indexOf("llo"), text.indexOf("!")));
     }
 
+    @Test
+    public void testCursorDrag_slop() throws Throwable {
+        String text = "line1: This is the 1st line: A\n"
+                    + "line2: This is the 2nd line: B\n"
+                    + "line3: This is the 3rd line: C\n";
+        onView(withId(R.id.textview)).perform(replaceText(text));
+        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+        TextView tv = mActivity.findViewById(R.id.textview);
+
+        // Simulate a drag where the finger moves slightly up and down (above and below the original
+        // line where the drag started). The cursor should just move along the original line without
+        // jumping up or down across lines.
+        MotionEventInfo[] events = new MotionEventInfo[]{
+                // Start dragging along the second line
+                motionEventInfo(text.indexOf("line2"), 1.0f),
+                motionEventInfo(text.indexOf("This is the 2nd"), 1.0f),
+                // Move to the bottom of the first line; cursor should remain on second line
+                motionEventInfo(text.indexOf("he 1st"), 0.0f, text.indexOf("he 2nd")),
+                // Move to the top of the third line; cursor should remain on second line
+                motionEventInfo(text.indexOf("e: C"), 1.0f, text.indexOf("e: B")),
+                motionEventInfo(text.indexOf("B"), 0.0f)
+        };
+        simulateDrag(tv, events, true);
+    }
+
+    @Test
+    public void testCursorDrag_snapToHandle() throws Throwable {
+        String text = "line1: This is the 1st line: A\n"
+                    + "line2: This is the 2nd line: B\n"
+                    + "line3: This is the 3rd line: C\n";
+        onView(withId(R.id.textview)).perform(replaceText(text));
+        onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(0));
+        TextView tv = mActivity.findViewById(R.id.textview);
+
+        // When the drag motion moves downward, we delay jumping to the lower line to allow the
+        // user's touch to snap to the cursor's handle. Once the finger is over the handle, we
+        // position the cursor above the user's actual touch (offset such that the finger remains
+        // over the handle rather than on top of the cursor vertical bar). This improves the
+        // visibility of the cursor and the text underneath.
+        MotionEventInfo[] events = new MotionEventInfo[]{
+                // Start dragging along the first line
+                motionEventInfo(text.indexOf("line1"), 1.0f),
+                motionEventInfo(text.indexOf("This is the 1st"), 1.0f),
+                // Move to the bottom of the third line; cursor should end up on second line
+                motionEventInfo(text.indexOf("he 3rd"), 0.0f, text.indexOf("he 2nd")),
+                // Move to the middle of the second line; cursor should end up on the first line
+                motionEventInfo(text.indexOf("he 2nd"), 0.5f, text.indexOf("he 1st"))
+        };
+        simulateDrag(tv, events, true);
+
+        // If the drag motion hasn't moved downward (ie, we haven't had a chance to snap to the
+        // handle), we position the cursor directly at the touch position.
+        events = new MotionEventInfo[]{
+                // Start dragging along the third line
+                motionEventInfo(text.indexOf("line3"), 1.0f),
+                motionEventInfo(text.indexOf("This is the 3rd"), 1.0f),
+                // Move to the middle of the second line; cursor should end up on the second line
+                motionEventInfo(text.indexOf("he 2nd"), 0.5f, text.indexOf("he 2nd")),
+        };
+        simulateDrag(tv, events, true);
+    }
+
     private static MotionEvent downEvent(long downTime, long eventTime, float x, float y) {
         return MotionEvent.obtain(downTime, eventTime, MotionEvent.ACTION_DOWN, x, y, 0);
     }
@@ -436,4 +505,89 @@
         event.setButtonState(MotionEvent.BUTTON_PRIMARY);
         return event;
     }
+
+    public static MotionEventInfo motionEventInfo(int index, float ratioToLineTop) {
+        return new MotionEventInfo(index, ratioToLineTop, index);
+    }
+
+    public static MotionEventInfo motionEventInfo(int index, float ratioToLineTop,
+            int expectedCursorIndex) {
+        return new MotionEventInfo(index, ratioToLineTop, expectedCursorIndex);
+    }
+
+    private static class MotionEventInfo {
+        public final int index;
+        public final float ratioToLineTop; // 0.0 = bottom of line, 0.5 = middle of line, etc
+        public final int expectedCursorIndex;
+
+        private MotionEventInfo(int index, float ratioToLineTop, int expectedCursorIndex) {
+            this.index = index;
+            this.ratioToLineTop = ratioToLineTop;
+            this.expectedCursorIndex = expectedCursorIndex;
+        }
+
+        public float[] getCoordinates(TextView textView) {
+            Layout layout = textView.getLayout();
+            int line = layout.getLineForOffset(index);
+            float x = layout.getPrimaryHorizontal(index) + textView.getTotalPaddingLeft();
+            int bottom = layout.getLineBottom(line);
+            int top = layout.getLineTop(line);
+            float y = bottom - ((bottom - top) * ratioToLineTop) + textView.getTotalPaddingTop();
+            return new float[]{x, y};
+        }
+    }
+
+    private void simulateDrag(TextView tv, MotionEventInfo[] events, boolean runAssertions)
+            throws Exception {
+        Editor editor = tv.getEditorForTesting();
+
+        float[] downCoords = events[0].getCoordinates(tv);
+        long downEventTime = sTicker.addAndGet(10_000);
+        MotionEvent downEvent = downEvent(downEventTime, downEventTime,
+                downCoords[0], downCoords[1]);
+        mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(downEvent));
+
+        for (int i = 1; i < events.length; i++) {
+            float[] moveCoords = events[i].getCoordinates(tv);
+            long eventTime = downEventTime + i;
+            MotionEvent event = moveEvent(downEventTime, eventTime, moveCoords[0], moveCoords[1]);
+            mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(event));
+            assertCursorPosition(tv, events[i].expectedCursorIndex, runAssertions);
+        }
+
+        MotionEventInfo lastEvent = events[events.length - 1];
+        float[] upCoords = lastEvent.getCoordinates(tv);
+        long upEventTime = downEventTime + events.length;
+        MotionEvent upEvent = upEvent(downEventTime, upEventTime, upCoords[0], upCoords[1]);
+        mInstrumentation.runOnMainSync(() -> editor.onTouchEvent(upEvent));
+    }
+
+    private static void assertCursorPosition(TextView tv, int expectedPosition,
+            boolean runAssertions) {
+        String textAfterExpectedPos = getTextAfterIndex(tv, expectedPosition, 15);
+        String textAfterActualPos = getTextAfterIndex(tv, tv.getSelectionStart(), 15);
+        String msg = "Expected cursor at " + expectedPosition + ", just before \""
+                + textAfterExpectedPos + "\". Cursor is at " + tv.getSelectionStart()
+                + ", just before \"" + textAfterActualPos + "\".";
+        Log.d(LOG_TAG, msg);
+        if (runAssertions) {
+            assertWithMessage(msg).that(tv.getSelectionStart()).isEqualTo(expectedPosition);
+            assertThat(tv.getSelectionEnd()).isEqualTo(expectedPosition);
+        }
+    }
+
+    private static String getTextAfterIndex(TextView tv, int position, int maxLength) {
+        int end = Math.min(position + maxLength, tv.getText().length());
+        try {
+            String afterPosition = tv.getText().subSequence(position, end).toString();
+            if (afterPosition.indexOf('\n') > 0) {
+                afterPosition = afterPosition.substring(0, afterPosition.indexOf('\n'));
+            }
+            return afterPosition;
+        } catch (StringIndexOutOfBoundsException e) {
+            Log.d(LOG_TAG, "Invalid target position: position=" + position + ", length="
+                    + tv.getText().length() + ", end=" + end);
+            return "";
+        }
+    }
 }
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityTest.java b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
index 0c38e71..88a6f9e 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityTest.java
@@ -31,8 +31,8 @@
 import static android.widget.espresso.TextViewActions.doubleTapAndDragOnText;
 import static android.widget.espresso.TextViewActions.doubleTapHandle;
 import static android.widget.espresso.TextViewActions.dragHandle;
-import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
 import static android.widget.espresso.TextViewActions.longPressAndDragHandle;
+import static android.widget.espresso.TextViewActions.longPressAndDragOnText;
 import static android.widget.espresso.TextViewActions.longPressHandle;
 import static android.widget.espresso.TextViewActions.longPressOnTextAtIndex;
 import static android.widget.espresso.TextViewAssertions.doesNotHaveStyledText;
@@ -514,29 +514,26 @@
         onView(withId(R.id.textview)).check(hasInsertionPointerAtIndex(text.indexOf("f")));
     }
 
+    private void enableFlagsForInsertionHandleGestures() {
+        final TextView textView = mActivity.findViewById(R.id.textview);
+        final Editor editor = textView.getEditorForTesting();
+        editor.setFlagCursorDragFromAnywhereEnabled(true);
+        editor.setFlagInsertionHandleGesturesEnabled(true);
+        // Note: We don't need to reset these flags explicitly at the end of each test, because a
+        // fresh TextView and Editor will be created for each test.
+    }
+
     @Test
     public void testInsertionHandle_touchThrough() {
-        final TextView textView = mActivity.findViewById(R.id.textview);
-        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
-        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        textView.getEditorForTesting().setCursorControlEnabled(true);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
-
+        enableFlagsForInsertionHandleGestures();
         testInsertionHandle();
         testInsertionHandle_multiLine();
-
-        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
     }
 
     @Test
     public void testInsertionHandle_longPressToSelect() {
-        // This test only makes sense when Cursor Control flag is enabled.
+        enableFlagsForInsertionHandleGestures();
         final TextView textView = mActivity.findViewById(R.id.textview);
-        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
-        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        textView.getEditorForTesting().setCursorControlEnabled(true);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
 
         final String text = "hello the world";
         onView(withId(R.id.textview)).perform(replaceText(text));
@@ -546,20 +543,12 @@
 
         onHandleView(com.android.internal.R.id.insertion_handle).perform(longPressHandle(textView));
         onView(withId(R.id.textview)).check(hasSelection("world"));
-
-        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
     }
 
     @Test
     public void testInsertionHandle_longPressAndDragToSelect() {
-        // This test only makes sense when Cursor Control flag is enabled.
+        enableFlagsForInsertionHandleGestures();
         final TextView textView = mActivity.findViewById(R.id.textview);
-        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
-        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        textView.getEditorForTesting().setCursorControlEnabled(true);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
-
         final String text = "hello the world";
         onView(withId(R.id.textview)).perform(replaceText(text));
 
@@ -569,19 +558,12 @@
         onHandleView(com.android.internal.R.id.insertion_handle)
                 .perform(longPressAndDragHandle(textView, Handle.INSERTION, text.indexOf('t')));
         onView(withId(R.id.textview)).check(hasSelection("the world"));
-
-        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
     }
 
     @Test
     public void testInsertionHandle_doubleTapToSelect() {
-        // This test only makes sense when Cursor Control flag is enabled.
+        enableFlagsForInsertionHandleGestures();
         final TextView textView = mActivity.findViewById(R.id.textview);
-        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
-        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        textView.getEditorForTesting().setCursorControlEnabled(true);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
 
         final String text = "hello the world";
         onView(withId(R.id.textview)).perform(replaceText(text));
@@ -591,19 +573,12 @@
 
         onHandleView(com.android.internal.R.id.insertion_handle).perform(doubleTapHandle(textView));
         onView(withId(R.id.textview)).check(hasSelection("world"));
-
-        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
     }
 
     @Test
     public void testInsertionHandle_doubleTapAndDragToSelect() {
-        // This test only makes sense when Cursor Control flag is enabled.
+        enableFlagsForInsertionHandleGestures();
         final TextView textView = mActivity.findViewById(R.id.textview);
-        boolean cursorControlEnabled = textView.getEditorForTesting().getCursorControlEnabled();
-        boolean cursorDragEnabled = Editor.FLAG_ENABLE_CURSOR_DRAG;
-        textView.getEditorForTesting().setCursorControlEnabled(true);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = true;
 
         final String text = "hello the world";
         onView(withId(R.id.textview)).perform(replaceText(text));
@@ -614,9 +589,6 @@
         onHandleView(com.android.internal.R.id.insertion_handle)
                 .perform(doubleTapAndDragHandle(textView, Handle.INSERTION, text.indexOf('t')));
         onView(withId(R.id.textview)).check(hasSelection("the world"));
-
-        textView.getEditorForTesting().setCursorControlEnabled(cursorControlEnabled);
-        Editor.FLAG_ENABLE_CURSOR_DRAG = cursorDragEnabled;
     }
 
     @Test
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
new file mode 100644
index 0000000..fbf75df
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
@@ -0,0 +1,161 @@
+/*
+ * 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.internal.content;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.pm.parsing.ParsingPackageRead;
+import android.os.Build;
+import android.util.ArrayMap;
+
+import com.android.internal.content.om.OverlayConfig.PackageProvider;
+import com.android.internal.content.om.OverlayScanner;
+import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
+
+import org.junit.Assert;
+import org.junit.rules.TestRule;
+import org.junit.runner.Description;
+import org.junit.runners.model.Statement;
+import org.mockito.Mockito;
+import org.mockito.invocation.InvocationOnMock;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Supplier;
+
+/**
+ * A {@link TestRule} that runs a test case twice. First, the test case runs with a non-null
+ * {@link OverlayScanner} as if the zygote process is scanning the overlay packages
+ * and parsing configuration files. The test case then runs with a non-null
+ * {@link PackageProvider} as if the system server is parsing configuration files.
+ *
+ * This simulates what will happen on device. If an exception would be thrown in the zygote, then
+ * the exception should be thrown in the first run of the test case.
+ */
+public class OverlayConfigIterationRule implements TestRule {
+
+    enum Iteration {
+        ZYGOTE,
+        SYSTEM_SERVER,
+    }
+
+    private final ArrayMap<File, ParsedOverlayInfo> mOverlayStubResults = new ArrayMap<>();
+    private Supplier<OverlayScanner> mOverlayScanner;
+    private PackageProvider mPkgProvider;
+    private Iteration mIteration;
+
+    /**
+     * Mocks the parsing of the file to make it appear to the scanner that the file is a valid
+     * overlay APK.
+     **/
+    void addOverlay(File path, String packageName, String targetPackage, int targetSdkVersion,
+            boolean isStatic, int priority) {
+        try {
+            final File canonicalPath = new File(path.getCanonicalPath());
+            mOverlayStubResults.put(canonicalPath, new ParsedOverlayInfo(
+                    packageName, targetPackage, targetSdkVersion, isStatic, priority,
+                    canonicalPath));
+        } catch (IOException e) {
+            Assert.fail("Failed to add overlay " + e);
+        }
+    }
+
+    void addOverlay(File path, String packageName) {
+        addOverlay(path, packageName, "target");
+    }
+
+    void addOverlay(File path, String packageName, String targetPackage) {
+        addOverlay(path, packageName, targetPackage, Build.VERSION_CODES.CUR_DEVELOPMENT);
+    }
+
+    void addOverlay(File path, String packageName, String targetPackage, int targetSdkVersion) {
+        addOverlay(path, packageName, targetPackage, targetSdkVersion, false, 0);
+    }
+
+    /** Retrieves the {@link OverlayScanner} for the current run of the test. */
+    Supplier<OverlayScanner> getScannerFactory() {
+        return mOverlayScanner;
+    }
+
+    /** Retrieves the {@link PackageProvider} for the current run of the test. */
+    PackageProvider getPackageProvider() {
+        return mPkgProvider;
+    }
+
+    /** Retrieves the current iteration of the test. */
+    Iteration getIteration() {
+        return mIteration;
+    }
+
+
+    @Override
+    public Statement apply(Statement base, Description description) {
+        return new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                // Run the test once as if the zygote process is scanning the overlay packages
+                // and parsing configuration files.
+                mOverlayScanner = () -> {
+                    OverlayScanner scanner = Mockito.spy(new OverlayScanner());
+                    for (Map.Entry<File, ParsedOverlayInfo> overlay :
+                            mOverlayStubResults.entrySet()) {
+                        doReturn(overlay.getValue()).when(scanner)
+                                .parseOverlayManifest(overlay.getKey());
+                    }
+                    return scanner;
+                };
+                mPkgProvider = null;
+                mIteration = Iteration.ZYGOTE;
+                base.evaluate();
+
+                // Run the test once more (if the first test did not throw an exception) as if
+                // the system server is parsing the configuration files and using PackageManager to
+                // retrieving information of overlays.
+                mOverlayScanner = null;
+                mPkgProvider = Mockito.mock(PackageProvider.class);
+                mIteration = Iteration.SYSTEM_SERVER;
+                doAnswer((InvocationOnMock invocation) -> {
+                    final Object[] args = invocation.getArguments();
+                    final BiConsumer<ParsingPackageRead, Boolean> f =
+                            (BiConsumer<ParsingPackageRead, Boolean>) args[0];
+                    for (Map.Entry<File, ParsedOverlayInfo> overlay :
+                            mOverlayStubResults.entrySet()) {
+                        final ParsingPackageRead a = Mockito.mock(ParsingPackageRead.class);
+                        final ParsedOverlayInfo info = overlay.getValue();
+                        when(a.getPackageName()).thenReturn(info.packageName);
+                        when(a.getOverlayTarget()).thenReturn(info.targetPackageName);
+                        when(a.getTargetSdkVersion()).thenReturn(info.targetSdkVersion);
+                        when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
+                        when(a.getOverlayPriority()).thenReturn(info.priority);
+                        when(a.getBaseCodePath()).thenReturn(info.path.getPath());
+                        f.accept(a, !info.path.getPath().contains("data/overlay"));
+                    }
+                    return null;
+                }).when(mPkgProvider).forEachPackage(any());
+
+                base.evaluate();
+            }
+        };
+    }
+}
+
+
diff --git a/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
new file mode 100644
index 0000000..dee118f
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigTest.java
@@ -0,0 +1,603 @@
+/*
+ * 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.internal.content;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.os.FileUtils;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.frameworks.coretests.R;
+import com.android.internal.content.om.OverlayConfig;
+import com.android.internal.content.om.OverlayConfig.IdmapInvocation;
+import com.android.internal.content.om.OverlayScanner;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.RuleChain;
+import org.junit.rules.TemporaryFolder;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayConfigTest {
+    private static final String TEST_APK_PACKAGE_NAME =
+            "com.android.frameworks.coretests.overlay_config";
+
+    private ExpectedException mExpectedException = ExpectedException.none();
+    private OverlayConfigIterationRule mScannerRule = new OverlayConfigIterationRule();
+    private TemporaryFolder mTestFolder = new TemporaryFolder();
+
+    @Rule
+    public RuleChain chain = RuleChain.outerRule(mExpectedException)
+            .around(mTestFolder).around(mScannerRule);
+
+    private OverlayConfig createConfigImpl() throws IOException {
+        return new OverlayConfig(mTestFolder.getRoot().getCanonicalFile(),
+                mScannerRule.getScannerFactory(), mScannerRule.getPackageProvider());
+    }
+
+    private File createFile(String fileName) throws IOException {
+        return createFile(fileName, "");
+    }
+
+    private File createFile(String fileName, String content) throws IOException {
+        final File f = new File(String.format("%s/%s", mTestFolder.getRoot(), fileName));
+        if (!f.getParentFile().equals(mTestFolder.getRoot())) {
+            f.getParentFile().mkdirs();
+        }
+        FileUtils.stringToFile(f.getPath(), content);
+        return f;
+    }
+
+    private static void assertConfig(OverlayConfig overlayConfig, String packageName,
+            boolean mutable, boolean enabled, int configIndex) {
+        final OverlayConfig.Configuration config = overlayConfig.getConfiguration(packageName);
+        assertNotNull(config);
+        assertEquals(mutable, config.parsedConfig.mutable);
+        assertEquals(enabled, config.parsedConfig.enabled);
+        assertEquals(configIndex, config.configIndex);
+    }
+
+    @Test
+    public void testImmutableAfterNonImmutableFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("immutable overlays must precede mutable overlays");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "  <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+        createConfigImpl();
+    }
+
+    @Test
+    public void testConfigureAbsentPackageFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("not present in partition");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "</config>");
+
+        createConfigImpl();
+    }
+
+    @Test
+    public void testConfigurePackageTwiceFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("configured multiple times in a single partition");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "  <overlay package=\"one\" mutable=\"false\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        createConfigImpl();
+    }
+
+    @Test
+    public void testConfigureOverlayAcrossPartitionsFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("not present in partition");
+
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        createConfigImpl();
+    }
+
+    @Test
+    public void testConfigureOverlayOutsideOverlayDirFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("not present in partition");
+
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/app/one.apk"), "one");
+        createConfigImpl();
+    }
+
+    @Test
+    public void testMergeOAbsolutePathFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("must be relative to the directory");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <merge path=\"/product/overlay/config/auto-generated-config.xml\" />"
+                        + "</config>");
+
+        createConfigImpl();
+    }
+
+    @Test
+    public void testMergeOutsideDirFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("outside of configuration directory");
+
+        createFile("/product/overlay/auto-generated-config.xml");
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <merge path=\"../auto-generated-config.xml\" />"
+                        + "</config>");
+
+        createConfigImpl();
+    }
+
+    @Test
+    public void testMergeOutsidePartitionFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("outside of configuration directory");
+
+        createFile("/vendor/overlay/config/config2.xml");
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <merge path=\"../../../vendor/overlay/config/config2.xml\" />"
+                        + "</config>");
+
+        createConfigImpl();
+    }
+
+    @Test
+    public void testMergeCircularFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("Maximum <merge> depth exceeded");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <merge path=\"config2.xml\" />"
+                        + "</config>");
+        createFile("/product/overlay/config/config2.xml",
+                "<config>"
+                        + "  <merge path=\"config.xml\" />"
+                        + "</config>");
+
+        createConfigImpl();
+    }
+
+    @Test
+    public void testMergeMissingFileFails() throws IOException {
+        mExpectedException.expect(IllegalStateException.class);
+        mExpectedException.expectMessage("does not exist");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <merge path=\"config2.xml\" />"
+                        + "</config>");
+        createConfigImpl();
+    }
+
+    @Test
+    public void testProductOverridesVendor() throws IOException {
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"false\" />"
+                        + "</config>");
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", true, true, 1);
+    }
+
+    @Test
+    public void testPartitionPrecedence() throws IOException {
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" enabled=\"true\" />"
+                        + "</config>");
+        createFile("/odm/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"two\" enabled=\"true\" />"
+                        + "</config>");
+        createFile("/oem/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"three\" enabled=\"true\" />"
+                        + "</config>");
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"four\" enabled=\"true\" />"
+                        + "</config>");
+        createFile("/system_ext/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"five\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
+        mScannerRule.addOverlay(createFile("/oem/overlay/three.apk"), "three");
+        mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four");
+        mScannerRule.addOverlay(createFile("/system_ext/overlay/five.apk"), "five");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", true, true, 0);
+        assertConfig(overlayConfig, "two", true, true, 1);
+        assertConfig(overlayConfig, "three", true, true, 2);
+        assertConfig(overlayConfig, "four", true, true, 3);
+        assertConfig(overlayConfig, "five", true, true, 4);
+    }
+
+    @Test
+    public void testImmutable() throws IOException {
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" mutable=\"false\" />"
+                        + "  <overlay package=\"two\" />"
+                        + "  <overlay package=\"three\" mutable=\"true\" />"
+                        + "</config>");
+
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, false, 0);
+        assertConfig(overlayConfig, "two", true, false, 1);
+        assertConfig(overlayConfig, "three", true, false, 2);
+    }
+
+    @Test
+    public void testEnabled() throws IOException {
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" />"
+                        + "  <overlay package=\"two\" enabled=\"true\" />"
+                        + "  <overlay package=\"three\" enabled=\"false\" />"
+                        + "</config>");
+
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", true, false, 0);
+        assertConfig(overlayConfig, "two", true, true, 1);
+        assertConfig(overlayConfig, "three", true, false, 2);
+    }
+
+    @Test
+    public void testMerge() throws IOException {
+        createFile("/product/overlay/config/auto-generated-config.xml",
+                "<config>"
+                        + "  <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"three\" mutable=\"false\" enabled=\"true\" />"
+                        + "</config>");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <merge path=\"auto-generated-config.xml\" />"
+                        + "  <overlay package=\"four\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one");
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two");
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three");
+        mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        OverlayConfig.Configuration o1 = overlayConfig.getConfiguration("one");
+        assertNotNull(o1);
+        assertFalse(o1.parsedConfig.mutable);
+        assertTrue(o1.parsedConfig.enabled);
+        assertEquals(0, o1.configIndex);
+
+        OverlayConfig.Configuration o2 = overlayConfig.getConfiguration("two");
+        assertNotNull(o2);
+        assertFalse(o2.parsedConfig.mutable);
+        assertTrue(o2.parsedConfig.enabled);
+        assertEquals(1, o2.configIndex);
+
+        OverlayConfig.Configuration o3 = overlayConfig.getConfiguration("three");
+        assertNotNull(o3);
+        assertFalse(o3.parsedConfig.mutable);
+        assertTrue(o3.parsedConfig.enabled);
+        assertEquals(2, o3.configIndex);
+
+        OverlayConfig.Configuration o4 = overlayConfig.getConfiguration("four");
+        assertNotNull(o4);
+        assertTrue(o4.parsedConfig.mutable);
+        assertTrue(o4.parsedConfig.enabled);
+        assertEquals(3, o4.configIndex);
+    }
+
+    @Test
+    public void testIdmapInvocationsFrameworkImmutable() throws IOException {
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"three\" enabled=\"true\" />"
+                        + "</config>");
+
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"four\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"five\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"six\" mutable=\"false\" enabled=\"false\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android");
+        mScannerRule.addOverlay(createFile("/vendor/overlay/two.apk"), "two", "android");
+        mScannerRule.addOverlay(createFile("/vendor/overlay/three.apk"), "three", "android");
+        mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android");
+        mScannerRule.addOverlay(createFile("/product/overlay/five.apk"), "five");
+        mScannerRule.addOverlay(createFile("/product/overlay/six.apk"), "six", "android");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
+            final ArrayList<IdmapInvocation> idmapInvocations =
+                    overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+            assertEquals(2, idmapInvocations.size());
+
+            final IdmapInvocation i0 = idmapInvocations.get(0);
+            assertTrue(i0.enforceOverlayable);
+            assertEquals("vendor", i0.policy);
+            assertEquals(2, i0.overlayPaths.size());
+            assertTrue(i0.overlayPaths.get(0).endsWith("/vendor/overlay/one.apk"));
+            assertTrue(i0.overlayPaths.get(1).endsWith("/vendor/overlay/two.apk"));
+
+            final IdmapInvocation i1 = idmapInvocations.get(1);
+            assertTrue(i1.enforceOverlayable);
+            assertEquals("product", i1.policy);
+            assertEquals(1, i1.overlayPaths.size());
+            assertTrue(i1.overlayPaths.get(0).endsWith("/product/overlay/four.apk"));
+        }
+    }
+
+    @Test
+    public void testIdmapInvocationsDifferentTargetSdk() throws IOException {
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"three\" mutable=\"false\" enabled=\"true\" />"
+                        + "  <overlay package=\"four\" mutable=\"false\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one", "android");
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android");
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 28);
+        mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android");
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+
+        if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.ZYGOTE) {
+            final ArrayList<IdmapInvocation> idmapInvocations =
+                    overlayConfig.getImmutableFrameworkOverlayIdmapInvocations();
+            assertEquals(3, idmapInvocations.size());
+
+            final IdmapInvocation i0 = idmapInvocations.get(0);
+            assertTrue(i0.enforceOverlayable);
+            assertEquals(2, i0.overlayPaths.size());
+            assertTrue(i0.overlayPaths.get(0).endsWith("/product/overlay/one.apk"));
+            assertTrue(i0.overlayPaths.get(1).endsWith("/product/overlay/two.apk"));
+
+            final IdmapInvocation i1 = idmapInvocations.get(1);
+            assertFalse(i1.enforceOverlayable);
+            assertEquals(1, i1.overlayPaths.size());
+            assertTrue(i1.overlayPaths.get(0).endsWith("/product/overlay/three.apk"));
+
+            final IdmapInvocation i2 = idmapInvocations.get(2);
+            assertTrue(i2.enforceOverlayable);
+            assertEquals(1, i2.overlayPaths.size());
+            assertTrue(i2.overlayPaths.get(0).endsWith("/product/overlay/four.apk"));
+        }
+    }
+
+    @Test
+    public void testNoConfigIsStatic() throws IOException {
+        mScannerRule.addOverlay(createFile("/product/overlay/one.apk"), "one", "android", 28, true,
+                1);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 28, false,
+                0);
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 28,
+                true, 0);
+        mScannerRule.addOverlay(createFile("/product/overlay/four.apk"), "four", "android", 28,
+                false, 2);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 1);
+        assertConfig(overlayConfig, "three", false, true, 0);
+
+    }
+
+    @Test
+    public void testVendorStaticPrecedesProductImmutable() throws IOException {
+        createFile("/product/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"two\" mutable=\"false\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+                1);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 0);
+        assertConfig(overlayConfig, "two", false, true, 1);
+    }
+
+    @Test
+    public void testVendorImmutablePrecededProductStatic() throws IOException {
+        createFile("/vendor/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"one\" mutable=\"false\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+                1);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 0);
+        assertConfig(overlayConfig, "two", false, true, 1);
+    }
+
+    @Test
+    public void testNoConfigsAllowPartitionReordering() throws IOException {
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+                1);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 1);
+        assertConfig(overlayConfig, "two", false, true, 0);
+    }
+
+    @Test
+    public void testConfigDisablesPartitionReordering() throws IOException {
+        createFile("/odm/overlay/config/config.xml",
+                "<config>"
+                        + "  <overlay package=\"two\" enabled=\"true\" />"
+                        + "</config>");
+
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+                1);
+        mScannerRule.addOverlay(createFile("/odm/overlay/two.apk"), "two");
+        mScannerRule.addOverlay(createFile("/product/overlay/three.apk"), "three", "android", 0,
+                true, 0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 0);
+        assertConfig(overlayConfig, "two", true, true, 1);
+        assertConfig(overlayConfig, "three", false, true, 2);
+    }
+
+    @Test
+    public void testStaticOverlayOutsideOverlayDir() throws IOException {
+        mScannerRule.addOverlay(createFile("/product/app/one.apk"), "one", "android", 0, true, 0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        if (mScannerRule.getIteration() == OverlayConfigIterationRule.Iteration.SYSTEM_SERVER) {
+            assertConfig(overlayConfig, "one", false, true, 0);
+        }
+    }
+
+    @Test
+    public void testSortStaticOverlaysDifferentTargets() throws IOException {
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "other", 0, true, 0);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 1);
+        assertConfig(overlayConfig, "two", false, true, 0);
+    }
+
+    @Test
+    public void testSortStaticOverlaysSamePriority() throws IOException {
+        mScannerRule.addOverlay(createFile("/vendor/overlay/one.apk"), "one", "android", 0, true,
+                0);
+        mScannerRule.addOverlay(createFile("/product/overlay/two.apk"), "two", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertConfig(overlayConfig, "one", false, true, 1);
+        assertConfig(overlayConfig, "two", false, true, 0);
+    }
+
+    @Test
+    public void testNonSystemOverlayCannotBeStatic() throws IOException {
+        mScannerRule.addOverlay(createFile("/data/overlay/one.apk"), "one", "android", 0, true,
+                0);
+
+        final OverlayConfig overlayConfig = createConfigImpl();
+        assertTrue(overlayConfig.isMutable("one"));
+        assertFalse(overlayConfig.isEnabled("one"));
+        assertEquals(Integer.MAX_VALUE, overlayConfig.getPriority("one"));
+    }
+
+    @Test
+    public void testGetOverlayInfo() throws IOException {
+        if (mScannerRule.getIteration() != OverlayConfigIterationRule.Iteration.ZYGOTE) {
+            // Run only one iteration of the test.
+            return;
+        }
+
+        final InputStream is = InstrumentationRegistry.getContext().getResources()
+                .openRawResource(R.raw.overlay_config);
+        final File partitionDir = mTestFolder.newFolder("product", "overlay");
+        final File testApk = new File(partitionDir, "test.apk");
+        FileUtils.copy(is, new FileOutputStream(testApk));
+
+        final OverlayScanner scanner = new OverlayScanner();
+        scanner.scanDir(partitionDir);
+
+        final OverlayScanner.ParsedOverlayInfo info = scanner.getParsedInfo(TEST_APK_PACKAGE_NAME);
+        assertNotNull(info);
+        assertEquals(TEST_APK_PACKAGE_NAME, info.packageName);
+        assertEquals("android", info.targetPackageName);
+        assertEquals(testApk.getPath(), info.path.getPath());
+        assertEquals(21, info.targetSdkVersion);
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
index a6329298..2ad8e18 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
@@ -40,6 +40,7 @@
         BatteryStatsUserLifecycleTests.class,
         KernelCpuProcStringReaderTest.class,
         KernelCpuUidActiveTimeReaderTest.class,
+        KernelCpuUidBpfMapReaderTest.class,
         KernelCpuUidClusterTimeReaderTest.class,
         KernelCpuUidFreqTimeReaderTest.class,
         KernelCpuUidUserSysTimeReaderTest.class,
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
index 1b13a99..2ccd74e 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidActiveTimeReaderTest.java
@@ -21,11 +21,11 @@
 
 import android.content.Context;
 import android.os.FileUtils;
+import android.util.SparseArray;
 import android.util.SparseLongArray;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidActiveTimeReader;
 
@@ -33,11 +33,15 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Random;
 
 /**
@@ -46,14 +50,16 @@
  * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidActiveTimeReaderTest
  */
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class KernelCpuUidActiveTimeReaderTest {
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidActiveTimeReader mReader;
+    private KernelCpuUidTestBpfMapReader mBpfMapReader;
     private VerifiableCallback mCallback;
 
     private Random mRand = new Random(12345);
+    protected boolean mUseBpf;
     private final int mCpus = 4;
     private final String mHeadline = "cpus: 4\n";
     private final int[] mUids = {0, 1, 22, 333, 4444, 55555};
@@ -62,12 +68,22 @@
         return InstrumentationRegistry.getContext();
     }
 
+    @Parameters(name="useBpf={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {true}, {false} });
+    }
+
+    public KernelCpuUidActiveTimeReaderTest(boolean useBpf) {
+        mUseBpf = useBpf;
+    }
+
     @Before
     public void setUp() {
         mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
         mTestFile = new File(mTestDir, "test.file");
+        mBpfMapReader = new KernelCpuUidTestBpfMapReader();
         mReader = new KernelCpuUidActiveTimeReader(
-                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false);
+                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false);
         mCallback = new VerifiableCallback();
     }
 
@@ -80,7 +96,7 @@
     @Test
     public void testReadDelta() throws Exception {
         final long[][] times = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times));
+        setCpusAndData(times);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], getActiveTime(times[i]));
@@ -90,7 +106,7 @@
         // Verify that a second call will only return deltas.
         mCallback.clear();
         final long[][] newTimes1 = increaseTime(times);
-        writeToFile(mHeadline + uidLines(mUids, newTimes1));
+        setCpusAndData(newTimes1);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], getActiveTime(newTimes1[i]) - getActiveTime(times[i]));
@@ -105,7 +121,7 @@
         // Verify that calling with a null callback doesn't result in any crashes
         mCallback.clear();
         final long[][] newTimes2 = increaseTime(newTimes1);
-        writeToFile(mHeadline + uidLines(mUids, newTimes2));
+        setCpusAndData(newTimes2);
         mReader.readDelta(null);
         mCallback.verifyNoMoreInteractions();
 
@@ -113,19 +129,20 @@
         // the previous call had null callback.
         mCallback.clear();
         final long[][] newTimes3 = increaseTime(newTimes2);
+        setCpusAndData(newTimes3);
         writeToFile(mHeadline + uidLines(mUids, newTimes3));
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], getActiveTime(newTimes3[i]) - getActiveTime(newTimes2[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCpusAndData();
     }
 
     @Test
     public void testReadAbsolute() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCpusAndData(times1);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], getActiveTime(times1[i]));
@@ -135,19 +152,19 @@
         // Verify that a second call should still return absolute values
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCpusAndData(times2);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], getActiveTime(times2[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCpusAndData();
     }
 
     @Test
     public void testReadDeltaDecreasedTime() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCpusAndData(times1);
         mReader.readDelta(mCallback);
 
         // Verify that there should not be a callback for a particular UID if its time decreases.
@@ -155,19 +172,19 @@
         final long[][] times2 = increaseTime(times1);
         System.arraycopy(times1[0], 0, times2[0], 0, mCpus);
         times2[0][0] = 100;
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCpusAndData(times2);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], getActiveTime(times2[i]) - getActiveTime(times1[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCpusAndData();
 
         // Verify that the internal state was not modified.
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
         times3[0] = increaseTime(times1)[0];
-        writeToFile(mHeadline + uidLines(mUids, times3));
+        setCpusAndData(times3);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], getActiveTime(times3[0]) - getActiveTime(times1[0]));
         for (int i = 1; i < mUids.length; i++) {
@@ -179,26 +196,26 @@
     @Test
     public void testReadDeltaNegativeTime() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCpusAndData(times1);
         mReader.readDelta(mCallback);
 
         // Verify that there should not be a callback for a particular UID if its time is -ve.
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
         times2[0][0] *= -1;
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCpusAndData(times2);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], getActiveTime(times2[i]) - getActiveTime(times1[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCpusAndData();
 
         // Verify that the internal state was not modified.
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
         times3[0] = increaseTime(times1)[0];
-        writeToFile(mHeadline + uidLines(mUids, times3));
+        setCpusAndData(times3);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], getActiveTime(times3[0]) - getActiveTime(times1[0]));
         for (int i = 1; i < mUids.length; i++) {
@@ -207,6 +224,28 @@
         mCallback.verifyNoMoreInteractions();
     }
 
+    private void setCpusAndData(long[][] times) throws IOException {
+        if (mUseBpf) {
+            mBpfMapReader.setCpus(new long[]{ mCpus });
+            SparseArray<long[]> data = new SparseArray<>();
+            for (int i = 0; i < mUids.length; i++) {
+                data.put(mUids[i], times[i]);
+            }
+            mBpfMapReader.setData(data);
+        } else {
+            writeToFile(mHeadline + uidLines(mUids, times));
+        }
+    }
+
+    private void clearCpusAndData() {
+        if (mUseBpf) {
+            mBpfMapReader.setCpus(null);
+            mBpfMapReader.setData(new SparseArray<>());
+        } else {
+            assertTrue(mTestFile.delete());
+        }
+    }
+
     private String uidLines(int[] uids, long[][] times) {
         StringBuffer sb = new StringBuffer();
         for (int i = 0; i < uids.length; i++) {
@@ -261,4 +300,36 @@
             assertEquals(0, mData.size());
         }
     }
+
+    private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader {
+        private long[] mCpus;
+        private SparseArray<long[]> mNewData = new SparseArray<>();
+
+        public void setData(SparseArray<long[]> data) {
+            mNewData = data;
+        }
+
+        public void setCpus(long[] cpus) {
+            mCpus = cpus;
+        }
+
+        @Override
+        public final boolean startTrackingBpfTimes() {
+            return true;
+        }
+
+        @Override
+        protected final boolean readBpfData() {
+            if (!mUseBpf) {
+                return false;
+            }
+            mData = mNewData;
+            return true;
+        }
+
+        @Override
+        public final long[] getDataDimensions() {
+            return mCpus;
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java
new file mode 100644
index 0000000..257b388
--- /dev/null
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidBpfMapReaderTest.java
@@ -0,0 +1,237 @@
+/*
+ * 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.internal.os;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.Context;
+import android.util.SparseArray;
+
+import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+import org.junit.runner.RunWith;
+
+import com.android.internal.os.KernelCpuUidBpfMapReader.BpfMapIterator;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.IntStream;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class KernelCpuUidBpfMapReaderTest {
+    private Random mRand = new Random(12345);
+    private KernelCpuUidTestBpfMapReader mReader;
+
+    private Context getContext() {
+        return InstrumentationRegistry.getContext();
+    }
+
+    @Before
+    public void setUp() {
+        mReader =  new KernelCpuUidTestBpfMapReader();
+    }
+
+    /**
+     * Tests that reading returns null if readBpfData() fails.
+     */
+    @Test
+    public void testUnsuccessfulRead() {
+        assertEquals(null, mReader.open());
+    }
+
+    /**
+     * Tests that reading will always return null after 5 failures.
+     */
+    @Test
+    public void testReadErrorsLimit() {
+        for (int i = 0; i < 3; i++) {
+            try (BpfMapIterator iter = mReader.open()) {
+                assertNull(iter);
+            }
+        }
+
+        SparseArray<long[]> data = new SparseArray<>();
+        long[] times = {2};
+        data.put(1, new long[]{2});
+        mReader.setData(data);
+        testOpenAndReadData(data);
+
+        mReader.setData(null);
+        for (int i = 0; i < 3; i++) {
+            try (BpfMapIterator iter = mReader.open(true)) {
+                assertNull(iter);
+            }
+        }
+        mReader.setData(data);
+        try (BpfMapIterator iter = mReader.open(true)) {
+            assertNull(iter);
+        }
+    }
+
+    /** Tests getNextUid functionality. */
+    @Test
+    public void testGetNextUid() {
+        final SparseArray<long[]> data = getTestSparseArray(800, 50);
+        mReader.setData(data);
+        testOpenAndReadData(data);
+    }
+
+    @Test
+    public void testConcurrent() throws Exception {
+        final SparseArray<long[]> data = getTestSparseArray(200, 50);
+        final SparseArray<long[]> data1 = getTestSparseArray(180, 70);
+        final List<Throwable> errs = Collections.synchronizedList(new ArrayList<>());
+        mReader.setData(data);
+        // An additional thread for modifying the data.
+        ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(11);
+        final CountDownLatch ready = new CountDownLatch(10);
+        final CountDownLatch start = new CountDownLatch(1);
+        final CountDownLatch modify = new CountDownLatch(1);
+        final CountDownLatch done = new CountDownLatch(10);
+
+        for (int i = 0; i < 5; i++) {
+            threadPool.submit(() -> {
+                    ready.countDown();
+                    try {
+                        start.await();
+                        testOpenAndReadData(data);
+                    } catch (Throwable e) {
+                        errs.add(e);
+                    } finally {
+                        done.countDown();
+                    }
+            });
+            threadPool.submit(() -> {
+                    ready.countDown();
+                    try {
+                        start.await();
+                        // Wait for data modification.
+                        modify.await();
+                        testOpenAndReadData(data1);
+                    } catch (Throwable e) {
+                        errs.add(e);
+                    } finally {
+                        done.countDown();
+                    }
+             });
+        }
+
+        assertTrue("Prep timed out", ready.await(100, TimeUnit.MILLISECONDS));
+        start.countDown();
+
+        threadPool.schedule(() -> {
+                mReader.setData(data1);
+                modify.countDown();
+        }, 600, TimeUnit.MILLISECONDS);
+
+        assertTrue("Execution timed out", done.await(3, TimeUnit.SECONDS));
+        threadPool.shutdownNow();
+
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        errs.forEach(e -> e.printStackTrace(pw));
+
+        assertTrue("All Exceptions:\n" + sw.toString(), errs.isEmpty());
+    }
+
+    @Test
+    public void testRemoveUidsInRange() {
+        final SparseArray<long[]> data = getTestSparseArray(200, 50);
+        mReader.setData(data);
+        testOpenAndReadData(data);
+        SparseArray<long[]> changedData = new SparseArray<>();
+        for (int i = 6; i < 200; i++) {
+            changedData.put(i, data.get(i));
+        }
+        mReader.removeUidsInRange(0, 5);
+        testOpenAndReadData(changedData);
+    }
+
+    private void testOpenAndReadData(SparseArray<long[]> expectedData) {
+        try (BpfMapIterator iter = mReader.open()) {
+            long[] actual;
+            if (expectedData.size() > 0) {
+                actual = new long[expectedData.valueAt(0).length + 1];
+            } else {
+                actual = new long[0];
+            }
+            for (int i = 0; i < expectedData.size(); i++) {
+                assertTrue(iter.getNextUid(actual));
+                assertEquals(expectedData.keyAt(i), actual[0]);
+                assertArrayEquals(expectedData.valueAt(i), Arrays.copyOfRange(actual, 1, actual.length));
+            }
+            assertFalse(iter.getNextUid(actual));
+            assertFalse(iter.getNextUid(actual));
+        }
+    }
+
+
+    private SparseArray<long[]> getTestSparseArray(int uids, int numPerUid) {
+        SparseArray<long[]> data = new SparseArray<>();
+        for (int i = 0; i < uids; i++) {
+            data.put(i, mRand.longs(numPerUid, 0, Long.MAX_VALUE).toArray());
+        }
+        return data;
+    }
+
+
+    private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader {
+        private SparseArray<long[]> mNewData;
+
+        public final void setData(SparseArray<long[]> newData) {
+            mNewData = newData;
+        }
+
+        @Override
+        public final boolean startTrackingBpfTimes() {
+            return true;
+        }
+
+        @Override
+        public final boolean readBpfData() {
+            if (mNewData == null) {
+                return false;
+            }
+            mData = mNewData;
+            return true;
+        }
+
+        @Override
+        public final long[] getDataDimensions() {
+            return null;
+        }
+
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
index 2ea80da..a0dab28 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidClusterTimeReaderTest.java
@@ -27,7 +27,6 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidClusterTimeReader;
 
@@ -35,11 +34,15 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.IOException;
 import java.nio.file.Files;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Random;
 
 /**
@@ -48,28 +51,42 @@
  * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidClusterTimeReaderTest
  */
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class KernelCpuUidClusterTimeReaderTest {
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidClusterTimeReader mReader;
+    private KernelCpuUidTestBpfMapReader mBpfMapReader;
     private VerifiableCallback mCallback;
 
     private Random mRand = new Random(12345);
+    protected boolean mUseBpf;
     private final int mCpus = 6;
     private final String mHeadline = "policy0: 4 policy4: 2\n";
+    private final long[] mCores = {4, 2};
     private final int[] mUids = {0, 1, 22, 333, 4444, 55555};
 
     private Context getContext() {
         return InstrumentationRegistry.getContext();
     }
 
+    @Parameters(name="useBpf={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {true}, {false} });
+    }
+
+    public KernelCpuUidClusterTimeReaderTest(boolean useBpf) {
+        mUseBpf = useBpf;
+    }
+
     @Before
     public void setUp() {
         mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
         mTestFile = new File(mTestDir, "test.file");
+        mBpfMapReader = new KernelCpuUidTestBpfMapReader();
         mReader = new KernelCpuUidClusterTimeReader(
-                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false);
+                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader,
+                false);
         mCallback = new VerifiableCallback();
     }
 
@@ -82,7 +99,7 @@
     @Test
     public void testReadDelta() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCoresAndData(times1);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], clusterTime(times1[i]));
@@ -92,7 +109,7 @@
         // Verify that a second call will only return deltas.
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCoresAndData(times2);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i])));
@@ -107,7 +124,7 @@
         // Verify that calling with a null callback doesn't result in any crashes
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
-        writeToFile(mHeadline + uidLines(mUids, times3));
+        setCoresAndData(times3);
         mReader.readDelta(null);
         mCallback.verifyNoMoreInteractions();
 
@@ -115,19 +132,19 @@
         // the previous call had null callback.
         mCallback.clear();
         final long[][] times4 = increaseTime(times3);
-        writeToFile(mHeadline + uidLines(mUids, times4));
+        setCoresAndData(times4);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], subtract(clusterTime(times4[i]), clusterTime(times3[i])));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCoresAndData();
     }
 
     @Test
     public void testReadAbsolute() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCoresAndData(times1);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], clusterTime(times1[i]));
@@ -137,19 +154,19 @@
         // Verify that a second call should still return absolute values
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCoresAndData(times2);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], clusterTime(times2[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCoresAndData();
     }
 
     @Test
     public void testReadDeltaDecreasedTime() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCoresAndData(times1);
         mReader.readDelta(mCallback);
 
         // Verify that there should not be a callback for a particular UID if its time decreases.
@@ -157,19 +174,19 @@
         final long[][] times2 = increaseTime(times1);
         System.arraycopy(times1[0], 0, times2[0], 0, mCpus);
         times2[0][0] = 100;
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCoresAndData(times2);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i])));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCoresAndData();
 
         // Verify that the internal state was not modified.
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
         times3[0] = increaseTime(times1)[0];
-        writeToFile(mHeadline + uidLines(mUids, times3));
+        setCoresAndData(times3);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], subtract(clusterTime(times3[0]), clusterTime(times1[0])));
         for (int i = 1; i < mUids.length; i++) {
@@ -181,26 +198,26 @@
     @Test
     public void testReadDeltaNegativeTime() throws Exception {
         final long[][] times1 = increaseTime(new long[mUids.length][mCpus]);
-        writeToFile(mHeadline + uidLines(mUids, times1));
+        setCoresAndData(times1);
         mReader.readDelta(mCallback);
 
         // Verify that there should not be a callback for a particular UID if its time decreases.
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
         times2[0][0] *= -1;
-        writeToFile(mHeadline + uidLines(mUids, times2));
+        setCoresAndData(times2);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], subtract(clusterTime(times2[i]), clusterTime(times1[i])));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearCoresAndData();
 
         // Verify that the internal state was not modified.
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
         times3[0] = increaseTime(times1)[0];
-        writeToFile(mHeadline + uidLines(mUids, times3));
+        setCoresAndData(times3);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], subtract(clusterTime(times3[0]), clusterTime(times1[0])));
         for (int i = 1; i < mUids.length; i++) {
@@ -209,6 +226,28 @@
         mCallback.verifyNoMoreInteractions();
     }
 
+    private void setCoresAndData(long[][] times) throws IOException {
+        if (mUseBpf) {
+            mBpfMapReader.setClusterCores(mCores);
+            SparseArray<long[]> data = new SparseArray<>();
+            for (int i = 0; i < mUids.length; i++) {
+                data.put(mUids[i], times[i]);
+            }
+            mBpfMapReader.setData(data);
+        } else {
+            writeToFile(mHeadline + uidLines(mUids, times));
+        }
+    }
+
+    private void clearCoresAndData() {
+        if (mUseBpf) {
+            mBpfMapReader.setClusterCores(null);
+            mBpfMapReader.setData(new SparseArray<>());
+        } else {
+            assertTrue(mTestFile.delete());
+        }
+    }
+
     private long[] clusterTime(long[] times) {
         // Assumes 4 + 2 cores
         return new long[]{times[0] + times[1] / 2 + times[2] / 3 + times[3] / 4,
@@ -277,4 +316,36 @@
             assertEquals(0, mData.size());
         }
     }
+
+    private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader {
+        private long[] mClusterCores;
+        private SparseArray<long[]> mNewData = new SparseArray<>();
+
+        public void setData(SparseArray<long[]> data) {
+            mNewData = data;
+        }
+
+        public void setClusterCores(long[] cores) {
+            mClusterCores = cores;
+        }
+
+        @Override
+        public final boolean startTrackingBpfTimes() {
+            return true;
+        }
+
+        @Override
+        protected final boolean readBpfData() {
+            if (!mUseBpf) {
+                return false;
+            }
+            mData = mNewData;
+            return true;
+        }
+
+        @Override
+        public final long[] getDataDimensions() {
+            return mClusterCores;
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
index 0b6fed3..c60a6d6 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelCpuUidFreqTimeReaderTest.java
@@ -29,7 +29,6 @@
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.os.KernelCpuUidTimeReader.KernelCpuUidFreqTimeReader;
 
@@ -37,6 +36,8 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -45,6 +46,7 @@
 import java.io.IOException;
 import java.nio.file.Files;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Random;
 
 /**
@@ -53,14 +55,16 @@
  * $ atest FrameworksCoreTests:com.android.internal.os.KernelCpuUidFreqTimeReaderTest
  */
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class KernelCpuUidFreqTimeReaderTest {
     private File mTestDir;
     private File mTestFile;
     private KernelCpuUidFreqTimeReader mReader;
+    private KernelCpuUidTestBpfMapReader mBpfMapReader;
     private VerifiableCallback mCallback;
     @Mock
     private PowerProfile mPowerProfile;
+    private boolean mUseBpf;
 
     private Random mRand = new Random(12345);
     private final int[] mUids = {0, 1, 22, 333, 4444, 55555};
@@ -69,13 +73,23 @@
         return InstrumentationRegistry.getContext();
     }
 
+    @Parameters(name="useBpf={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {true}, {false} });
+    }
+
+    public KernelCpuUidFreqTimeReaderTest(boolean useBpf) {
+        mUseBpf = useBpf;
+    }
+
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mTestDir = getContext().getDir("test", Context.MODE_PRIVATE);
         mTestFile = new File(mTestDir, "test.file");
+        mBpfMapReader = new KernelCpuUidTestBpfMapReader();
         mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(),
-                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false);
+                new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false);
         mCallback = new VerifiableCallback();
     }
 
@@ -97,17 +111,17 @@
         final int[][] numFreqs = {{3, 6}, {4, 5}, {3, 5, 4}, {3}};
         for (int i = 0; i < freqs.length; ++i) {
             mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(),
-                    new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false);
+                    new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false);
             setCpuClusterFreqs(numClusters[i], numFreqs[i]);
-            writeToFile(freqsLine(freqs[i]));
+            setFreqs(freqs[i]);
             long[] actualFreqs = mReader.readFreqs(mPowerProfile);
             assertArrayEquals(freqs[i], actualFreqs);
             final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
                     Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
             assertFalse(errMsg, mReader.perClusterTimesAvailable());
 
-            // Verify that a second call won't read the proc file again
-            assertTrue(mTestFile.delete());
+            // Verify that a second call won't re-read the freqs
+            clearFreqsAndData();
             actualFreqs = mReader.readFreqs(mPowerProfile);
             assertArrayEquals(freqs[i], actualFreqs);
             assertFalse(errMsg, mReader.perClusterTimesAvailable());
@@ -125,17 +139,17 @@
         final int[][] numFreqs = {{4}, {3, 5}, {3, 5, 4}};
         for (int i = 0; i < freqs.length; ++i) {
             mReader = new KernelCpuUidFreqTimeReader(mTestFile.getAbsolutePath(),
-                    new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), false);
+                    new KernelCpuProcStringReader(mTestFile.getAbsolutePath()), mBpfMapReader, false);
             setCpuClusterFreqs(numClusters[i], numFreqs[i]);
-            writeToFile(freqsLine(freqs[i]));
+            setFreqs(freqs[i]);
             long[] actualFreqs = mReader.readFreqs(mPowerProfile);
             assertArrayEquals(freqs[i], actualFreqs);
             final String errMsg = String.format("Freqs=%s, nClusters=%d, nFreqs=%s",
                     Arrays.toString(freqs[i]), numClusters[i], Arrays.toString(numFreqs[i]));
             assertTrue(errMsg, mReader.perClusterTimesAvailable());
 
-            // Verify that a second call won't read the proc file again
-            assertTrue(mTestFile.delete());
+            // Verify that a second call won't re-read the freqs
+            clearFreqsAndData();
             actualFreqs = mReader.readFreqs(mPowerProfile);
             assertArrayEquals(freqs[i], actualFreqs);
             assertTrue(errMsg, mReader.perClusterTimesAvailable());
@@ -147,7 +161,7 @@
         final long[] freqs = {110, 123, 145, 167, 289, 997};
         final long[][] times = increaseTime(new long[mUids.length][freqs.length]);
 
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times));
+        setFreqsAndData(freqs, times);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], times[i]);
@@ -155,14 +169,14 @@
         mCallback.verifyNoMoreInteractions();
 
         // Verify that readDelta also reads the frequencies if not already available.
-        assertTrue(mTestFile.delete());
+        clearFreqsAndData();
         long[] actualFreqs = mReader.readFreqs(mPowerProfile);
         assertArrayEquals(freqs, actualFreqs);
 
         // Verify that a second call will only return deltas.
         mCallback.clear();
         final long[][] newTimes1 = increaseTime(times);
-        writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes1));
+        setFreqsAndData(freqs, newTimes1);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], subtract(newTimes1[i], times[i]));
@@ -177,7 +191,7 @@
         // Verify that calling with a null callback doesn't result in any crashes
         mCallback.clear();
         final long[][] newTimes2 = increaseTime(newTimes1);
-        writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes2));
+        setFreqsAndData(freqs, newTimes2);
         mReader.readDelta(null);
         mCallback.verifyNoMoreInteractions();
 
@@ -185,13 +199,13 @@
         // the previous call had null callback.
         mCallback.clear();
         final long[][] newTimes3 = increaseTime(newTimes2);
-        writeToFile(freqsLine(freqs) + uidLines(mUids, newTimes3));
+        setFreqsAndData(freqs, newTimes3);
         mReader.readDelta(mCallback);
         for (int i = 0; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], subtract(newTimes3[i], newTimes2[i]));
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearFreqsAndData();
     }
 
     @Test
@@ -199,7 +213,7 @@
         final long[] freqs = {110, 123, 145, 167, 289, 997};
         final long[][] times1 = increaseTime(new long[mUids.length][freqs.length]);
 
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times1));
+        setFreqsAndData(freqs, times1);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], times1[i]);
@@ -207,20 +221,20 @@
         mCallback.verifyNoMoreInteractions();
 
         // Verify that readDelta also reads the frequencies if not already available.
-        assertTrue(mTestFile.delete());
+        clearFreqsAndData();
         long[] actualFreqs = mReader.readFreqs(mPowerProfile);
         assertArrayEquals(freqs, actualFreqs);
 
         // Verify that a second call should still return absolute values
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times2));
+        setFreqsAndData(freqs, times2);
         mReader.readAbsolute(mCallback);
         for (int i = 0; i < mUids.length; i++) {
             mCallback.verify(mUids[i], times2[i]);
         }
         mCallback.verifyNoMoreInteractions();
-        assertTrue(mTestFile.delete());
+        clearFreqsAndData();
     }
 
     @Test
@@ -228,14 +242,14 @@
         final long[] freqs = {110, 123, 145, 167, 289, 997};
         final long[][] times1 = increaseTime(new long[mUids.length][freqs.length]);
 
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times1));
+        setFreqsAndData(freqs, times1);
         mReader.readDelta(mCallback);
 
         // Verify that there should not be a callback for a particular UID if its time decreases.
         mCallback.clear();
         final long[][] times2 = increaseTime(times1);
         times2[0][0] = 1000;
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times2));
+        setFreqsAndData(freqs, times2);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], subtract(times2[i], times1[i]));
@@ -246,7 +260,7 @@
         mCallback.clear();
         final long[][] times3 = increaseTime(times2);
         times3[0] = increaseTime(times1)[0];
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times3));
+        setFreqsAndData(freqs, times3);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], subtract(times3[0], times1[0]));
         for (int i = 1; i < mUids.length; i++) {
@@ -258,7 +272,7 @@
         mCallback.clear();
         final long[][] times4 = increaseTime(times3);
         times4[0][0] *= -1;
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times4));
+        setFreqsAndData(freqs, times4);
         mReader.readDelta(mCallback);
         for (int i = 1; i < mUids.length; ++i) {
             mCallback.verify(mUids[i], subtract(times4[i], times3[i]));
@@ -269,14 +283,44 @@
         mCallback.clear();
         final long[][] times5 = increaseTime(times4);
         times5[0] = increaseTime(times3)[0];
-        writeToFile(freqsLine(freqs) + uidLines(mUids, times5));
+        setFreqsAndData(freqs, times5);
         mReader.readDelta(mCallback);
         mCallback.verify(mUids[0], subtract(times5[0], times3[0]));
         for (int i = 1; i < mUids.length; i++) {
             mCallback.verify(mUids[i], subtract(times5[i], times4[i]));
         }
 
-        assertTrue(mTestFile.delete());
+        clearFreqsAndData();
+    }
+
+    private void setFreqs(long[] freqs) throws IOException {
+        if (mUseBpf) {
+            mBpfMapReader.setFreqs(freqs);
+        } else {
+            writeToFile(freqsLine(freqs));
+        }
+    }
+
+    private void setFreqsAndData(long[] freqs, long[][] times) throws IOException {
+        if (mUseBpf) {
+            mBpfMapReader.setFreqs(freqs);
+            SparseArray<long[]> data = new SparseArray<>();
+            for (int i = 0; i < mUids.length; i++) {
+                data.put(mUids[i], times[i]);
+            }
+            mBpfMapReader.setData(data);
+        } else {
+            writeToFile(freqsLine(freqs) + uidLines(mUids, times));
+        }
+    }
+
+    private void clearFreqsAndData() {
+        if (mUseBpf) {
+            mBpfMapReader.setFreqs(null);
+            mBpfMapReader.setData(new SparseArray<>());
+        } else {
+            assertTrue(mTestFile.delete());
+        }
     }
 
     private String freqsLine(long[] freqs) {
@@ -358,4 +402,36 @@
             assertEquals(0, mData.size());
         }
     }
+
+    private class KernelCpuUidTestBpfMapReader extends KernelCpuUidBpfMapReader {
+        private long[] mCpuFreqs;
+        private SparseArray<long[]> mNewData = new SparseArray<>();
+
+        public void setData(SparseArray<long[]> data) {
+            mNewData = data;
+        }
+
+        public void setFreqs(long[] freqs) {
+            mCpuFreqs = freqs;
+        }
+
+        @Override
+        public final boolean startTrackingBpfTimes() {
+            return true;
+        }
+
+        @Override
+        protected final boolean readBpfData() {
+            if (!mUseBpf) {
+                return false;
+            }
+            mData = mNewData;
+            return true;
+        }
+
+        @Override
+        public final long[] getDataDimensions() {
+            return mCpuFreqs;
+        }
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
index 479e19e..dac35e5 100644
--- a/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/KernelSingleUidTimeReaderTest.java
@@ -31,20 +31,33 @@
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.junit.runners.Parameterized.Parameters;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Arrays;
+import java.util.Collection;
 
 @SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(Parameterized.class)
 public class KernelSingleUidTimeReaderTest {
     private final static int TEST_UID = 2222;
     private final static int TEST_FREQ_COUNT = 5;
 
     private KernelSingleUidTimeReader mReader;
     private TestInjector mInjector;
+    protected boolean mUseBpf;
+
+    @Parameters(name="useBpf={0}")
+    public static Collection<Object[]> data() {
+        return Arrays.asList(new Object[][] { {true}, {false} });
+    }
+
+    public KernelSingleUidTimeReaderTest(boolean useBpf) {
+        mUseBpf = useBpf;
+    }
 
     @Before
     public void setUp() {
@@ -273,6 +286,7 @@
 
     class TestInjector extends Injector {
         private byte[] mData;
+        private long[] mBpfData;
         private boolean mThrowExcpetion;
 
         @Override
@@ -284,6 +298,14 @@
             }
         }
 
+        @Override
+        public long[] readBpfData(int uid) {
+            if (!mUseBpf || mBpfData == null) {
+                return new long[0];
+            }
+            return mBpfData;
+        }
+
         public void setData(long[] cpuTimes) {
             final ByteBuffer buffer = ByteBuffer.allocate(cpuTimes.length * Long.BYTES);
             buffer.order(ByteOrder.nativeOrder());
@@ -291,6 +313,7 @@
                 buffer.putLong(time / 10);
             }
             mData = buffer.array();
+            mBpfData = cpuTimes.clone();
         }
 
         public void letReadDataThrowException(boolean throwException) {
diff --git a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
index cdcf23f..3e40466 100644
--- a/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
+++ b/core/tests/coretests/src/com/android/internal/policy/DecorContextTest.java
@@ -53,7 +53,10 @@
 
     @Test
     public void testDecorContextWithDefaultDisplay() {
-        DecorContext context = new DecorContext(mContext.getApplicationContext(), mContext);
+        Display defaultDisplay = new Display(DisplayManagerGlobal.getInstance(), DEFAULT_DISPLAY,
+                new DisplayInfo(), DisplayAdjustments.DEFAULT_DISPLAY_ADJUSTMENTS);
+        DecorContext context = new DecorContext(mContext.getApplicationContext(),
+                mContext.createDisplayContext(defaultDisplay));
 
         assertDecorContextDisplay(DEFAULT_DISPLAY, context);
     }
diff --git a/data/etc/privapp-permissions-platform.xml b/data/etc/privapp-permissions-platform.xml
index 08b30f7..78c7b76d 100644
--- a/data/etc/privapp-permissions-platform.xml
+++ b/data/etc/privapp-permissions-platform.xml
@@ -410,6 +410,7 @@
     <privapp-permissions package="com.android.dynsystem">
         <permission name="android.permission.REBOOT"/>
         <permission name="android.permission.MANAGE_DYNAMIC_SYSTEM"/>
+        <permission name="android.permission.READ_OEM_UNLOCK_STATE"/>
     </privapp-permissions>
     <privapp-permissions package="com.android.settings">
         <permission name="android.permission.INSTALL_DYNAMIC_SYSTEM"/>
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 9c2e95f..c1e7a36 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -2243,6 +2243,19 @@
         return nativeCreateGraphicBufferHandle(mNativePtr);
     }
 
+    /**
+     * @return {@link HardwareBuffer} which is internally used by hardware bitmap
+     *
+     * Note: the HardwareBuffer does *not* have an associated {@link ColorSpace}.
+     * To render this object the same as its rendered with this Bitmap, you
+     * should also call {@link getColorSpace}.
+     *
+     * @hide
+     */
+    public HardwareBuffer getHardwareBuffer() {
+        return nativeGetHardwareBuffer(mNativePtr);
+    }
+
     //////////// native methods
 
     private static native Bitmap nativeCreate(int[] colors, int offset,
@@ -2308,6 +2321,7 @@
     private static native Bitmap nativeWrapHardwareBufferBitmap(HardwareBuffer buffer,
                                                                 long nativeColorSpace);
     private static native GraphicBuffer nativeCreateGraphicBufferHandle(long nativeBitmap);
+    private static native HardwareBuffer nativeGetHardwareBuffer(long nativeBitmap);
     private static native ColorSpace nativeComputeColorSpace(long nativePtr);
     private static native void nativeSetColorSpace(long nativePtr, long nativeColorSpace);
     private static native boolean nativeIsSRGB(long nativePtr);
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index c12159c..5858e39 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -280,7 +280,10 @@
      * {@link android.os.Build.VERSION_CODES#Q}, it is no longer required to be
      * convex.
      *
-     * @deprecated The path is no longer required to be convex. Use {@link #setPath} instead.
+     * @deprecated As of {@link android.os.Build.VERSION_CODES#Q}, the restriction
+     * that the path must be convex is removed. However, the API is misnamed until
+     * {@link android.os.Build.VERSION_CODES#R}, when {@link #setPath} is
+     * introduced. Use {@link #setPath} instead.
      */
     @Deprecated
     public void setConvexPath(@NonNull Path convexPath) {
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 914c046..56d951c 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -150,11 +150,7 @@
     AHardwareBuffer_Desc bufferDesc;
     AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
     SkImageInfo info = uirenderer::BufferDescriptionToImageInfo(bufferDesc, colorSpace);
-
-    // If the stride is 0 we have to use the width as an approximation (eg, compressed buffer)
-    const auto bufferStride = bufferDesc.stride > 0 ? bufferDesc.stride : bufferDesc.width;
-    const size_t rowBytes = info.bytesPerPixel() * bufferStride;
-    return sk_sp<Bitmap>(new Bitmap(hardwareBuffer, info, rowBytes, palette));
+    return createFrom(hardwareBuffer, info, bufferDesc, palette);
 }
 
 sk_sp<Bitmap> Bitmap::createFrom(AHardwareBuffer* hardwareBuffer, SkColorType colorType,
@@ -164,8 +160,14 @@
     AHardwareBuffer_describe(hardwareBuffer, &bufferDesc);
     SkImageInfo info = SkImageInfo::Make(bufferDesc.width, bufferDesc.height,
                                          colorType, alphaType, colorSpace);
+    return createFrom(hardwareBuffer, info, bufferDesc, palette);
+}
 
-    const size_t rowBytes = info.bytesPerPixel() * bufferDesc.stride;
+sk_sp<Bitmap> Bitmap::createFrom(AHardwareBuffer* hardwareBuffer, const SkImageInfo& info,
+                                 const AHardwareBuffer_Desc& bufferDesc, BitmapPalette palette) {
+    // If the stride is 0 we have to use the width as an approximation (eg, compressed buffer)
+    const auto bufferStride = bufferDesc.stride > 0 ? bufferDesc.stride : bufferDesc.width;
+    const size_t rowBytes = info.bytesPerPixel() * bufferStride;
     return sk_sp<Bitmap>(new Bitmap(hardwareBuffer, info, rowBytes, palette));
 }
 #endif
diff --git a/libs/hwui/hwui/Bitmap.h b/libs/hwui/hwui/Bitmap.h
index 3bfb780..b8b5994 100644
--- a/libs/hwui/hwui/Bitmap.h
+++ b/libs/hwui/hwui/Bitmap.h
@@ -169,6 +169,12 @@
 #ifdef __ANDROID__ // Layoutlib does not support hardware acceleration
     Bitmap(AHardwareBuffer* buffer, const SkImageInfo& info, size_t rowBytes,
            BitmapPalette palette);
+
+    // Common code for the two public facing createFrom(AHardwareBuffer*, ...)
+    // methods.
+    // bufferDesc is only used to compute rowBytes.
+    static sk_sp<Bitmap> createFrom(AHardwareBuffer* hardwareBuffer, const SkImageInfo& info,
+                                    const AHardwareBuffer_Desc& bufferDesc, BitmapPalette palette);
 #endif
 
     virtual ~Bitmap();
diff --git a/libs/hwui/protos/graphicsstats.proto b/libs/hwui/protos/graphicsstats.proto
index dd5676c..745393c 100644
--- a/libs/hwui/protos/graphicsstats.proto
+++ b/libs/hwui/protos/graphicsstats.proto
@@ -30,8 +30,9 @@
 
 message GraphicsStatsProto {
     enum PipelineType {
-        GL = 0;
-        VULKAN = 1;
+        UNKNOWN = 0;
+        GL = 1;
+        VULKAN = 2;
     }
 
     // The package name of the app
diff --git a/libs/usb/Android.bp b/libs/usb/Android.bp
index 027a748..e752b55 100644
--- a/libs/usb/Android.bp
+++ b/libs/usb/Android.bp
@@ -19,5 +19,3 @@
     srcs: ["src/**/*.java"],
     api_packages: ["com.android.future.usb"],
 }
-
-subdirs = ["tests/*"]
diff --git a/libs/usb/tests/AccessoryChat/Android.bp b/libs/usb/tests/AccessoryChat/Android.bp
index 63a670c..19ed3d3 100644
--- a/libs/usb/tests/AccessoryChat/Android.bp
+++ b/libs/usb/tests/AccessoryChat/Android.bp
@@ -1,4 +1,3 @@
-subdirs = ["accessorychat"]
 //
 // Copyright (C) 2011 The Android Open Source Project
 //
diff --git a/location/java/android/location/GnssAntennaInfo.java b/location/java/android/location/GnssAntennaInfo.java
index dfcaf81..b2f9a0f 100644
--- a/location/java/android/location/GnssAntennaInfo.java
+++ b/location/java/android/location/GnssAntennaInfo.java
@@ -16,72 +16,37 @@
 
 package android.location;
 
-import android.annotation.IntDef;
+import android.annotation.FloatRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 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.List;
+import java.util.Objects;
 
 /**
  * A class that contains information about a GNSS antenna. GNSS antenna characteristics can change
  * with device configuration, such as when a device is folded open or closed. Antenna information is
- * delivered to registered instances of {@link Callback}.
+ * delivered to registered instances of {@link Listener}.
  */
 public final class GnssAntennaInfo implements Parcelable {
     private final double mCarrierFrequencyMHz;
-    private final PhaseCenterOffsetCoordinates mPhaseCenterOffsetCoordinates;
-    private final PhaseCenterVariationCorrections mPhaseCenterVariationCorrections;
-    private final SignalGainCorrections mSignalGainCorrections;
+    private final PhaseCenterOffset mPhaseCenterOffset;
+    private final SphericalCorrections mPhaseCenterVariationCorrections;
+    private final SphericalCorrections mSignalGainCorrections;
 
     /**
      * Used for receiving GNSS antenna info from the GNSS engine. You can implement this interface
-     * and call {@link LocationManager#registerAntennaInfoCallback};
+     * and call {@link LocationManager#registerAntennaInfoListener};
      */
-    public abstract static class Callback {
+    public interface Listener {
         /**
-         * The status of GNSS antenna info.
-         *
-         * @hide
-         */
-        @Retention(RetentionPolicy.SOURCE)
-        @IntDef({STATUS_NOT_SUPPORTED, STATUS_READY, STATUS_LOCATION_DISABLED})
-        public @interface GnssAntennaInfoStatus {
-        }
-
-        /**
-         * The system does not support GNSS antenna info.
-         *
-         * This status will not change in the future.
-         */
-        public static final int STATUS_NOT_SUPPORTED = 0;
-
-        /**
-         * GNSS antenna info updates are being successfully tracked.
-         */
-        public static final int STATUS_READY = 1;
-
-        /**
-         * GNSS provider or Location is disabled, updated will not be received until they are
-         * enabled.
-         */
-        public static final int STATUS_LOCATION_DISABLED = 2;
-
-        /**
-         * Returns the latest GNSS antenna info. This event is triggered when a callback is
+         * Returns the latest GNSS antenna info. This event is triggered when a listener is
          * registered, and whenever the antenna info changes (due to a device configuration change).
          */
-        public void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos) {}
-
-        /**
-         * Returns the latest status of the GNSS antenna info sub-system.
-         */
-        public void onStatusChanged(@GnssAntennaInfoStatus int status) {}
+        void onGnssAntennaInfoReceived(@NonNull List<GnssAntennaInfo> gnssAntennaInfos);
     }
 
     /**
@@ -90,37 +55,31 @@
      * for mobiles - see sensor or form factor documents for details. Uncertainties are reported
      *  to 1-sigma.
      */
-    public static final class PhaseCenterOffsetCoordinates implements Parcelable {
-        private final double mPhaseCenterOffsetCoordinateXMillimeters;
-        private final double mPhaseCenterOffsetCoordinateXUncertaintyMillimeters;
-        private final double mPhaseCenterOffsetCoordinateYMillimeters;
-        private final double mPhaseCenterOffsetCoordinateYUncertaintyMillimeters;
-        private final double mPhaseCenterOffsetCoordinateZMillimeters;
-        private final double mPhaseCenterOffsetCoordinateZUncertaintyMillimeters;
+    public static final class PhaseCenterOffset implements Parcelable {
+        private final double mOffsetXMm;
+        private final double mOffsetXUncertaintyMm;
+        private final double mOffsetYMm;
+        private final double mOffsetYUncertaintyMm;
+        private final double mOffsetZMm;
+        private final double mOffsetZUncertaintyMm;
 
-        @VisibleForTesting
-        public PhaseCenterOffsetCoordinates(double phaseCenterOffsetCoordinateXMillimeters,
-                double phaseCenterOffsetCoordinateXUncertaintyMillimeters,
-                double phaseCenterOffsetCoordinateYMillimeters,
-                double phaseCenterOffsetCoordinateYUncertaintyMillimeters,
-                double phaseCenterOffsetCoordinateZMillimeters,
-                double phaseCenterOffsetCoordinateZUncertaintyMillimeters) {
-            mPhaseCenterOffsetCoordinateXMillimeters = phaseCenterOffsetCoordinateXMillimeters;
-            mPhaseCenterOffsetCoordinateYMillimeters = phaseCenterOffsetCoordinateYMillimeters;
-            mPhaseCenterOffsetCoordinateZMillimeters = phaseCenterOffsetCoordinateZMillimeters;
-            mPhaseCenterOffsetCoordinateXUncertaintyMillimeters =
-                    phaseCenterOffsetCoordinateXUncertaintyMillimeters;
-            mPhaseCenterOffsetCoordinateYUncertaintyMillimeters =
-                    phaseCenterOffsetCoordinateYUncertaintyMillimeters;
-            mPhaseCenterOffsetCoordinateZUncertaintyMillimeters =
-                    phaseCenterOffsetCoordinateZUncertaintyMillimeters;
+        public PhaseCenterOffset(
+                double offsetXMm, double offsetXUncertaintyMm,
+                double offsetYMm, double offsetYUncertaintyMm,
+                double offsetZMm, double offsetZUncertaintyMm) {
+            mOffsetXMm = offsetXMm;
+            mOffsetYMm = offsetYMm;
+            mOffsetZMm = offsetZMm;
+            mOffsetXUncertaintyMm = offsetXUncertaintyMm;
+            mOffsetYUncertaintyMm = offsetYUncertaintyMm;
+            mOffsetZUncertaintyMm = offsetZUncertaintyMm;
         }
 
-        public static final @NonNull Creator<PhaseCenterOffsetCoordinates> CREATOR =
-                new Creator<PhaseCenterOffsetCoordinates>() {
+        public static final @NonNull Creator<PhaseCenterOffset> CREATOR =
+                new Creator<PhaseCenterOffset>() {
                     @Override
-                    public PhaseCenterOffsetCoordinates createFromParcel(Parcel in) {
-                        return new PhaseCenterOffsetCoordinates(
+                    public PhaseCenterOffset createFromParcel(Parcel in) {
+                        return new PhaseCenterOffset(
                                 in.readDouble(),
                                 in.readDouble(),
                                 in.readDouble(),
@@ -131,33 +90,39 @@
                     }
 
                     @Override
-                    public PhaseCenterOffsetCoordinates[] newArray(int size) {
-                        return new PhaseCenterOffsetCoordinates[size];
+                    public PhaseCenterOffset[] newArray(int size) {
+                        return new PhaseCenterOffset[size];
                     }
                 };
 
-        public double getXCoordMillimeters() {
-            return mPhaseCenterOffsetCoordinateXMillimeters;
+        @FloatRange()
+        public double getXOffsetMm() {
+            return mOffsetXMm;
         }
 
-        public double getXCoordUncertaintyMillimeters() {
-            return mPhaseCenterOffsetCoordinateXUncertaintyMillimeters;
+        @FloatRange()
+        public double getXOffsetUncertaintyMm() {
+            return mOffsetXUncertaintyMm;
         }
 
-        public double getYCoordMillimeters() {
-            return mPhaseCenterOffsetCoordinateYMillimeters;
+        @FloatRange()
+        public double getYOffsetMm() {
+            return mOffsetYMm;
         }
 
-        public double getYCoordUncertaintyMillimeters() {
-            return mPhaseCenterOffsetCoordinateYUncertaintyMillimeters;
+        @FloatRange()
+        public double getYOffsetUncertaintyMm() {
+            return mOffsetYUncertaintyMm;
         }
 
-        public double getZCoordMillimeters() {
-            return mPhaseCenterOffsetCoordinateZMillimeters;
+        @FloatRange()
+        public double getZOffsetMm() {
+            return mOffsetZMm;
         }
 
-        public double getZCoordUncertaintyMillimeters() {
-            return mPhaseCenterOffsetCoordinateZUncertaintyMillimeters;
+        @FloatRange()
+        public double getZOffsetUncertaintyMm() {
+            return mOffsetZUncertaintyMm;
         }
 
         @Override
@@ -167,30 +132,27 @@
 
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
-            dest.writeDouble(mPhaseCenterOffsetCoordinateXMillimeters);
-            dest.writeDouble(mPhaseCenterOffsetCoordinateXUncertaintyMillimeters);
-            dest.writeDouble(mPhaseCenterOffsetCoordinateYMillimeters);
-            dest.writeDouble(mPhaseCenterOffsetCoordinateYUncertaintyMillimeters);
-            dest.writeDouble(mPhaseCenterOffsetCoordinateZMillimeters);
-            dest.writeDouble(mPhaseCenterOffsetCoordinateZUncertaintyMillimeters);
+            dest.writeDouble(mOffsetXMm);
+            dest.writeDouble(mOffsetXUncertaintyMm);
+            dest.writeDouble(mOffsetYMm);
+            dest.writeDouble(mOffsetYUncertaintyMm);
+            dest.writeDouble(mOffsetZMm);
+            dest.writeDouble(mOffsetZUncertaintyMm);
         }
 
         @Override
         public String toString() {
-            StringBuilder builder = new StringBuilder("PhaseCenteroffset:\n");
-            builder.append("X: " + mPhaseCenterOffsetCoordinateXMillimeters + " +/- "
-                    + mPhaseCenterOffsetCoordinateXUncertaintyMillimeters + "\n");
-            builder.append("Y: " + mPhaseCenterOffsetCoordinateYMillimeters + " +/- "
-                    + mPhaseCenterOffsetCoordinateYUncertaintyMillimeters + "\n");
-            builder.append("Z: " + mPhaseCenterOffsetCoordinateZMillimeters + " +/- "
-                    + mPhaseCenterOffsetCoordinateZUncertaintyMillimeters + "\n");
-            return builder.toString();
+            return "PhaseCenterOffset{"
+                    + "OffsetXMm=" + mOffsetXMm + " +/-" + mOffsetXUncertaintyMm
+                    + ", OffsetYMm=" + mOffsetYMm + " +/-" + mOffsetYUncertaintyMm
+                    + ", OffsetZMm=" + mOffsetZMm + " +/-" + mOffsetZUncertaintyMm
+                    + '}';
         }
     }
 
     /**
-     * Class containing information about the phase center variation (PCV) corrections. The PCV
-     * correction is added to the phase measurement to obtain the corrected value.
+     * Represents corrections on a spherical mapping. Corrections are added to measurements to
+     * obtain the corrected values.
      *
      * The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays.
      *
@@ -203,229 +165,7 @@
      * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
      * i.e., deltaPhi = 180 / (number of columns - 1).
      */
-    public static final class PhaseCenterVariationCorrections extends SphericalCorrections {
-
-        @VisibleForTesting
-        public PhaseCenterVariationCorrections(
-                @NonNull double[][] phaseCenterVariationCorrectionsMillimeters,
-                @NonNull double[][] phaseCenterVariationCorrectionUncertaintiesMillimeters) {
-            super(phaseCenterVariationCorrectionsMillimeters,
-                    phaseCenterVariationCorrectionUncertaintiesMillimeters);
-        }
-
-        private PhaseCenterVariationCorrections(@NonNull Parcel in) {
-            super(in);
-        }
-
-        /**
-         * Get the phase center variation correction in millimeters at the specified row and column
-         * in the underlying 2D array.
-         * @param row zero-based major index in the array
-         * @param column zero-based minor index in the array
-         * @return phase center correction in millimeters
-         */
-        public double getPhaseCenterVariationCorrectionMillimetersAt(int row, int column) {
-            return super.getCorrectionAt(row, column);
-        }
-
-        /**
-         * Get the phase center variation correction uncertainty in millimeters at the specified row
-         * and column in the underlying 2D array.
-         * @param row zero-based major index in the array
-         * @param column zero-based minor index in the array
-         * @return 1-sigma phase center correction uncertainty in millimeters
-         */
-        public double getPhaseCenterVariationCorrectionUncertaintyMillimetersAt(
-                int row, int column) {
-            return super.getCorrectionUncertaintyAt(row, column);
-        }
-
-        public @NonNull double[][] getRawCorrectionsArray() {
-            return super.getRawCorrectionsArray().clone();
-        }
-
-        public @NonNull double[][] getRawCorrectionUncertaintiesArray() {
-            return super.getRawCorrectionUncertaintiesArray().clone();
-        }
-
-        public int getNumRows() {
-            return super.getNumRows();
-        }
-
-        public int getNumColumns() {
-            return super.getNumColumns();
-        }
-
-        /**
-         * The fixed theta angle separation between successive rows.
-         */
-        public double getDeltaTheta() {
-            return super.getDeltaTheta();
-        }
-
-        /**
-         * The fixed phi angle separation between successive columns.
-         */
-        public double getDeltaPhi() {
-            return super.getDeltaPhi();
-        }
-
-        public static final @NonNull Creator<PhaseCenterVariationCorrections> CREATOR =
-                new Creator<PhaseCenterVariationCorrections>() {
-                    @Override
-                    public PhaseCenterVariationCorrections createFromParcel(Parcel in) {
-                        return new PhaseCenterVariationCorrections(in);
-                    }
-
-                    @Override
-                    public PhaseCenterVariationCorrections[] newArray(int size) {
-                        return new PhaseCenterVariationCorrections[size];
-                    }
-                };
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(@NonNull Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder("PhaseCenterVariationCorrections:\n");
-            builder.append(super.toString());
-            return builder.toString();
-        }
-    }
-
-    /**
-     * Class containing information about the signal gain (SG) corrections. The SG
-     * correction is added to the signal gain to obtain the corrected value.
-     *
-     * The corrections and associated (1-sigma) uncertainties are represented by respect 2D arrays.
-     *
-     * Each row (major indices) represents a fixed theta. The first row corresponds to a
-     * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
-     * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta
-     * = 360 / (number of rows).
-     *
-     * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending
-     * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
-     * i.e., deltaPhi = 180 / (number of columns - 1).
-     */
-    public static final class SignalGainCorrections extends SphericalCorrections {
-
-        @VisibleForTesting
-        public SignalGainCorrections(
-                @NonNull double[][] signalGainCorrectionsDbi,
-                @NonNull double[][] signalGainCorrectionUncertaintiesDbi) {
-            super(signalGainCorrectionsDbi,
-                    signalGainCorrectionUncertaintiesDbi);
-        }
-
-        private SignalGainCorrections(@NonNull Parcel in) {
-            super(in);
-        }
-
-        /**
-         * Get the signal gain correction in dbi at the specified row and column
-         * in the underlying 2D array.
-         * @param row zero-based major index in the array
-         * @param column zero-based minor index in the array
-         * @return signal gain correction in dbi
-         */
-        public double getSignalGainCorrectionDbiAt(int row, int column) {
-            return super.getCorrectionAt(row, column);
-        }
-
-        /**
-         * Get the signal gain correction correction uncertainty in dbi at the specified row
-         * and column in the underlying 2D array.
-         * @param row zero-based major index in the array
-         * @param column zero-based minor index in the array
-         * @return 1-sigma signal gain correction uncertainty in dbi
-         */
-        public double getSignalGainCorrectionUncertaintyDbiAt(int row, int column) {
-            return super.getCorrectionUncertaintyAt(row, column);
-        }
-
-        public @NonNull double[][] getRawCorrectionsArray() {
-            return super.getRawCorrectionsArray().clone();
-        }
-
-        public @NonNull double[][] getRawCorrectionUncertaintiesArray() {
-            return super.getRawCorrectionUncertaintiesArray().clone();
-        }
-
-        public int getNumRows() {
-            return super.getNumRows();
-        }
-
-        public int getNumColumns() {
-            return super.getNumColumns();
-        }
-
-        /**
-         * The fixed theta angle separation between successive rows.
-         */
-        public double getDeltaTheta() {
-            return super.getDeltaTheta();
-        }
-
-        /**
-         * The fixed phi angle separation between successive columns.
-         */
-        public double getDeltaPhi() {
-            return super.getDeltaPhi();
-        }
-
-        public static final @NonNull Creator<SignalGainCorrections> CREATOR =
-                new Creator<SignalGainCorrections>() {
-                    @Override
-                    public SignalGainCorrections createFromParcel(Parcel in) {
-                        return new SignalGainCorrections(in);
-                    }
-
-                    @Override
-                    public SignalGainCorrections[] newArray(int size) {
-                        return new SignalGainCorrections[size];
-                    }
-                };
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(@NonNull Parcel dest, int flags) {
-            super.writeToParcel(dest, flags);
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder("SignalGainCorrections:\n");
-            builder.append(super.toString());
-            return builder.toString();
-        }
-    }
-
-    /**
-     * Represents corrections on a spherical mapping.
-     *
-     * Each row (major indices) represents a fixed theta. The first row corresponds to a
-     * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
-     * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e., deltaTheta
-     * = 360 / (number of rows).
-     *
-     * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and ending
-     * at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith angles,
-     * i.e., deltaPhi = 180 / (number of columns - 1).
-     */
-    private abstract static class SphericalCorrections implements Parcelable {
+    public static final class SphericalCorrections implements Parcelable{
         private final double[][] mCorrections;
         private final double[][] mCorrectionUncertainties;
         private final double mDeltaTheta;
@@ -433,7 +173,7 @@
         private final int mNumRows;
         private final int mNumColumns;
 
-        SphericalCorrections(@NonNull double[][] corrections,
+        public SphericalCorrections(@NonNull double[][] corrections,
                 @NonNull double[][] correctionUncertainties) {
             if (corrections.length != correctionUncertainties.length
                     || corrections[0].length != correctionUncertainties[0].length) {
@@ -474,54 +214,84 @@
                 in.readDoubleArray(correctionUncertainties[row]);
             }
 
-            mNumRows = corrections.length;
-            mNumColumns = corrections[0].length;
+            mNumRows = numRows;
+            mNumColumns = numColumns;
             mCorrections = corrections;
             mCorrectionUncertainties = correctionUncertainties;
             mDeltaTheta = 360.0d / mNumRows;
             mDeltaPhi = 180.0d / (mNumColumns - 1);
         }
 
-        private double getCorrectionAt(int row, int column) {
-            return mCorrections[row][column];
-        }
-
-        private double getCorrectionUncertaintyAt(int row, int column) {
-            return mCorrectionUncertainties[row][column];
-        }
-
+        /**
+         * Array representing corrections on a spherical mapping. Corrections are added to
+         * measurements to obtain the corrected values.
+         *
+         * Each row (major indices) represents a fixed theta. The first row corresponds to a
+         * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
+         * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e.,
+         * deltaTheta = 360 / (number of rows).
+         *
+         * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and
+         * ending at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith
+         * angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         */
         @NonNull
-        private double[][] getRawCorrectionsArray() {
+        public double[][] getCorrectionsArray() {
             return mCorrections;
         }
 
+        /**
+         * Array representing uncertainty on corrections on a spherical mapping.
+         *
+         * Each row (major indices) represents a fixed theta. The first row corresponds to a
+         * theta angle of 0 degrees. The last row corresponds to a theta angle of (360 - deltaTheta)
+         * degrees, where deltaTheta is the regular spacing between azimuthal angles, i.e.,
+         * deltaTheta = 360 / (number of rows).
+         *
+         * The columns (minor indices) represent fixed zenith angles, beginning at 0 degrees and
+         * ending at 180 degrees. They are separated by deltaPhi, the regular spacing between zenith
+         * angles, i.e., deltaPhi = 180 / (number of columns - 1).
+         */
         @NonNull
-        private double[][] getRawCorrectionUncertaintiesArray() {
+        public double[][] getCorrectionUncertaintiesArray() {
             return mCorrectionUncertainties;
         }
 
-        private int getNumRows() {
-            return mNumRows;
-        }
-
-        private int getNumColumns() {
-            return mNumColumns;
-        }
-
         /**
          * The fixed theta angle separation between successive rows.
          */
-        private double getDeltaTheta() {
+        @FloatRange(from = 0.0f, to = 360.0f)
+        public double getDeltaTheta() {
             return mDeltaTheta;
         }
 
         /**
          * The fixed phi angle separation between successive columns.
          */
-        private double getDeltaPhi() {
+        @FloatRange(from = 0.0f, to = 180.0f)
+        public double getDeltaPhi() {
             return mDeltaPhi;
         }
 
+
+        public static final @NonNull Creator<SphericalCorrections> CREATOR =
+                new Creator<SphericalCorrections>() {
+                    @Override
+                    public SphericalCorrections createFromParcel(Parcel in) {
+                        return new SphericalCorrections(in);
+                    }
+
+                    @Override
+                    public SphericalCorrections[] newArray(int size) {
+                        return new SphericalCorrections[size];
+                    }
+                };
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
         @Override
         public void writeToParcel(@NonNull Parcel dest, int flags) {
             dest.writeInt(mNumRows);
@@ -534,62 +304,114 @@
             }
         }
 
-        private String arrayToString(double[][] array) {
-            StringBuilder builder = new StringBuilder();
-            for (int row = 0; row < mNumRows; row++) {
-                builder.append("[ ");
-                for (int column = 0; column < mNumColumns - 1; column++) {
-                    builder.append(array[row][column] + ", ");
-                }
-                builder.append(array[row][mNumColumns - 1] + " ]\n");
-            }
-            return builder.toString();
-        }
-
         @Override
         public String toString() {
-            StringBuilder builder = new StringBuilder();
-            builder.append("DeltaTheta: " + mDeltaTheta + "\n");
-            builder.append("DeltaPhi: " + mDeltaPhi + "\n");
-            builder.append("CorrectionsArray:\n");
-            builder.append(arrayToString(mCorrections));
-            builder.append("CorrectionUncertaintiesArray:\n");
-            builder.append(arrayToString(mCorrectionUncertainties));
-            return builder.toString();
+            return "SphericalCorrections{"
+                    + "Corrections=" + Arrays.toString(mCorrections)
+                    + ", CorrectionUncertainties=" + Arrays.toString(mCorrectionUncertainties)
+                    + ", DeltaTheta=" + mDeltaTheta
+                    + ", DeltaPhi=" + mDeltaPhi
+                    + '}';
         }
     }
 
-    @VisibleForTesting
-    public GnssAntennaInfo(
+    private GnssAntennaInfo(
             double carrierFrequencyMHz,
-            @NonNull PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates,
-            @Nullable PhaseCenterVariationCorrections phaseCenterVariationCorrections,
-            @Nullable SignalGainCorrections signalGainCorrectionDbi) {
-        if (phaseCenterOffsetCoordinates == null) {
+            @NonNull PhaseCenterOffset phaseCenterOffset,
+            @Nullable SphericalCorrections phaseCenterVariationCorrections,
+            @Nullable SphericalCorrections signalGainCorrectionDbi) {
+        if (phaseCenterOffset == null) {
             throw new IllegalArgumentException("Phase Center Offset Coordinates cannot be null.");
         }
         mCarrierFrequencyMHz = carrierFrequencyMHz;
-        mPhaseCenterOffsetCoordinates = phaseCenterOffsetCoordinates;
+        mPhaseCenterOffset = phaseCenterOffset;
         mPhaseCenterVariationCorrections = phaseCenterVariationCorrections;
         mSignalGainCorrections = signalGainCorrectionDbi;
     }
 
+    /**
+     * Builder class for GnssAntennaInfo.
+     */
+    public static class Builder {
+        private double mCarrierFrequencyMHz;
+        private PhaseCenterOffset mPhaseCenterOffset;
+        private SphericalCorrections mPhaseCenterVariationCorrections;
+        private SphericalCorrections mSignalGainCorrections;
+
+        /**
+         * Set antenna carrier frequency (MHz).
+         * @param carrierFrequencyMHz antenna carrier frequency (MHz)
+         * @return Builder builder object
+         */
+        @NonNull
+        public Builder setCarrierFrequencyMHz(@FloatRange(from = 0.0f) double carrierFrequencyMHz) {
+            mCarrierFrequencyMHz = carrierFrequencyMHz;
+            return this;
+        }
+
+        /**
+         * Set antenna phase center offset.
+         * @param phaseCenterOffset phase center offset object
+         * @return Builder builder object
+         */
+        @NonNull
+        public Builder setPhaseCenterOffset(@NonNull PhaseCenterOffset phaseCenterOffset) {
+            mPhaseCenterOffset = Objects.requireNonNull(phaseCenterOffset);
+            return this;
+        }
+
+        /**
+         * Set phase center variation corrections.
+         * @param phaseCenterVariationCorrections phase center variation corrections object
+         * @return Builder builder object
+         */
+        @NonNull
+        public Builder setPhaseCenterVariationCorrections(
+                @Nullable SphericalCorrections phaseCenterVariationCorrections) {
+            mPhaseCenterVariationCorrections = phaseCenterVariationCorrections;
+            return this;
+        }
+
+        /**
+         * Set signal gain corrections.
+         * @param signalGainCorrections signal gain corrections object
+         * @return Builder builder object
+         */
+        @NonNull
+        public Builder setSignalGainCorrections(
+                @Nullable SphericalCorrections signalGainCorrections) {
+            mSignalGainCorrections = signalGainCorrections;
+            return this;
+        }
+
+        /**
+         * Build GnssAntennaInfo object.
+         * @return instance of GnssAntennaInfo
+         */
+        @NonNull
+        public GnssAntennaInfo build() {
+            return new GnssAntennaInfo(mCarrierFrequencyMHz, mPhaseCenterOffset,
+                    mPhaseCenterVariationCorrections, mSignalGainCorrections);
+        }
+    }
+
+    @FloatRange(from = 0.0f)
     public double getCarrierFrequencyMHz() {
         return mCarrierFrequencyMHz;
     }
 
     @NonNull
-    public PhaseCenterOffsetCoordinates getPhaseCenterOffsetCoordinates() {
-        return mPhaseCenterOffsetCoordinates;
+    public PhaseCenterOffset getPhaseCenterOffset() {
+        return mPhaseCenterOffset;
     }
 
     @Nullable
-    public PhaseCenterVariationCorrections getPhaseCenterVariationCorrections() {
+    public SphericalCorrections getPhaseCenterVariationCorrections() {
         return mPhaseCenterVariationCorrections;
     }
 
     @Nullable
-    public SignalGainCorrections getSignalGainCorrections() {
+    public SphericalCorrections getSignalGainCorrections() {
         return mSignalGainCorrections;
     }
 
@@ -600,16 +422,18 @@
                                 double carrierFrequencyMHz = in.readDouble();
 
                                 ClassLoader classLoader = getClass().getClassLoader();
-                                PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates =
+                                PhaseCenterOffset phaseCenterOffset =
                                         in.readParcelable(classLoader);
-                                PhaseCenterVariationCorrections phaseCenterVariationCorrections =
+                                SphericalCorrections phaseCenterVariationCorrections =
                                         in.readParcelable(classLoader);
-                                SignalGainCorrections signalGainCorrections =
+                                SphericalCorrections signalGainCorrections =
                                         in.readParcelable(classLoader);
 
-                                return new GnssAntennaInfo(carrierFrequencyMHz,
-                                        phaseCenterOffsetCoordinates,
-                                        phaseCenterVariationCorrections, signalGainCorrections);
+                                return new GnssAntennaInfo(
+                                            carrierFrequencyMHz,
+                                            phaseCenterOffset,
+                                            phaseCenterVariationCorrections,
+                                            signalGainCorrections);
                             }
 
                             @Override
@@ -626,29 +450,18 @@
     @Override
     public void writeToParcel(@NonNull Parcel parcel, int flags) {
         parcel.writeDouble(mCarrierFrequencyMHz);
-
-        // Write Phase Center Offset
-        parcel.writeParcelable(mPhaseCenterOffsetCoordinates, flags);
-
-        // Write Phase Center Variation Corrections
+        parcel.writeParcelable(mPhaseCenterOffset, flags);
         parcel.writeParcelable(mPhaseCenterVariationCorrections, flags);
-
-        // Write Signal Gain Corrections
         parcel.writeParcelable(mSignalGainCorrections, flags);
     }
 
     @Override
     public String toString() {
-        StringBuilder builder = new StringBuilder("[ GnssAntennaInfo:\n");
-        builder.append("CarrierFrequencyMHz: " + mCarrierFrequencyMHz + "\n");
-        builder.append(mPhaseCenterOffsetCoordinates.toString());
-        builder.append(mPhaseCenterVariationCorrections == null
-                ? "PhaseCenterVariationCorrections: null\n"
-                : mPhaseCenterVariationCorrections.toString());
-        builder.append(mSignalGainCorrections == null
-                ? "SignalGainCorrections: null\n"
-                : mSignalGainCorrections.toString());
-        builder.append("]");
-        return builder.toString();
+        return "GnssAntennaInfo{"
+                + "CarrierFrequencyMHz=" + mCarrierFrequencyMHz
+                + ", PhaseCenterOffset=" + mPhaseCenterOffset
+                + ", PhaseCenterVariationCorrections=" + mPhaseCenterVariationCorrections
+                + ", SignalGainCorrections=" + mSignalGainCorrections
+                + '}';
     }
 }
diff --git a/location/java/android/location/GnssCapabilities.java b/location/java/android/location/GnssCapabilities.java
index 930180c..5734bf2 100644
--- a/location/java/android/location/GnssCapabilities.java
+++ b/location/java/android/location/GnssCapabilities.java
@@ -16,15 +16,11 @@
 
 package android.location;
 
-import android.annotation.NonNull;
 import android.annotation.SystemApi;
 
 /**
  * A container of supported GNSS chipset capabilities.
- *
- * @hide
  */
-@SystemApi
 public final class GnssCapabilities {
     /**
      * Bit mask indicating GNSS chipset supports low power mode.
@@ -105,7 +101,10 @@
 
     /**
      * Returns {@code true} if GNSS chipset supports low power mode, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasLowPowerMode() {
         return hasCapability(LOW_POWER_MODE);
     }
@@ -113,28 +112,40 @@
     /**
      * Returns {@code true} if GNSS chipset supports blacklisting satellites, {@code false}
      * otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasSatelliteBlacklist() {
         return hasCapability(SATELLITE_BLACKLIST);
     }
 
     /**
      * Returns {@code true} if GNSS chipset supports geofencing, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasGeofencing() {
         return hasCapability(GEOFENCING);
     }
 
     /**
      * Returns {@code true} if GNSS chipset supports measurements, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasMeasurements() {
         return hasCapability(MEASUREMENTS);
     }
 
     /**
      * Returns {@code true} if GNSS chipset supports navigation messages, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasNavMessages() {
         return hasCapability(NAV_MESSAGES);
     }
@@ -142,7 +153,10 @@
     /**
      * Returns {@code true} if GNSS chipset supports measurement corrections, {@code false}
      * otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasMeasurementCorrections() {
         return hasCapability(MEASUREMENT_CORRECTIONS);
     }
@@ -150,7 +164,10 @@
     /**
      * Returns {@code true} if GNSS chipset supports line-of-sight satellite identification
      * measurement corrections, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasMeasurementCorrectionsLosSats() {
         return hasCapability(MEASUREMENT_CORRECTIONS_LOS_SATS);
     }
@@ -158,7 +175,10 @@
     /**
      * Returns {@code true} if GNSS chipset supports per satellite excess-path-length measurement
      * corrections, {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasMeasurementCorrectionsExcessPathLength() {
         return hasCapability(MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH);
     }
@@ -166,7 +186,10 @@
     /**
      * Returns {@code true} if GNSS chipset supports reflecting planes measurement corrections,
      * {@code false} otherwise.
+     *
+     * @hide
      */
+    @SystemApi
     public boolean hasMeasurementCorrectionsReflectingPane() {
         return hasCapability(MEASUREMENT_CORRECTIONS_REFLECTING_PLANE);
     }
@@ -178,28 +201,6 @@
         return hasCapability(ANTENNA_INFO);
     }
 
-    @NonNull
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("GnssCapabilities: ( ");
-        if (hasLowPowerMode()) sb.append("LOW_POWER_MODE ");
-        if (hasSatelliteBlacklist()) sb.append("SATELLITE_BLACKLIST ");
-        if (hasGeofencing()) sb.append("GEOFENCING ");
-        if (hasGnssAntennaInfo()) sb.append("ANTENNA_INFO ");
-        if (hasMeasurements()) sb.append("MEASUREMENTS ");
-        if (hasNavMessages()) sb.append("NAV_MESSAGES ");
-        if (hasMeasurementCorrections()) sb.append("MEASUREMENT_CORRECTIONS ");
-        if (hasMeasurementCorrectionsLosSats()) sb.append("MEASUREMENT_CORRECTIONS_LOS_SATS ");
-        if (hasMeasurementCorrectionsExcessPathLength()) {
-            sb.append("MEASUREMENT_CORRECTIONS_EXCESS_PATH_LENGTH ");
-        }
-        if (hasMeasurementCorrectionsReflectingPane()) {
-            sb.append("MEASUREMENT_CORRECTIONS_REFLECTING_PLANE ");
-        }
-        sb.append(")");
-        return sb.toString();
-    }
-
     private boolean hasCapability(long capability) {
         return (mGnssCapabilities & capability) == capability;
     }
diff --git a/location/java/android/location/IGnssAntennaInfoListener.aidl b/location/java/android/location/IGnssAntennaInfoListener.aidl
index 30bf5467..603ed6a 100644
--- a/location/java/android/location/IGnssAntennaInfoListener.aidl
+++ b/location/java/android/location/IGnssAntennaInfoListener.aidl
@@ -23,5 +23,4 @@
  */
 oneway interface IGnssAntennaInfoListener {
     void onGnssAntennaInfoReceived(in List<GnssAntennaInfo> gnssAntennaInfo);
-    void onStatusChanged(in int status);
 }
\ No newline at end of file
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 03e1c75..19085bf 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -1813,13 +1813,7 @@
 
     /**
      * Returns the supported capabilities of the GNSS chipset.
-     *
-     * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present.
-     *
-     * @hide
      */
-    @SystemApi
-    @RequiresPermission(ACCESS_FINE_LOCATION)
     public @NonNull GnssCapabilities getGnssCapabilities() {
         try {
             long gnssCapabilities = mService.getGnssCapabilities(mContext.getPackageName());
@@ -2264,35 +2258,36 @@
     }
 
     /**
-     * Registers a Gnss Antenna Info callback.
+     * Registers a Gnss Antenna Info listener. Only expect results if
+     * {@link GnssCapabilities#hasGnssAntennaInfo()} shows that antenna info is supported.
      *
-     * @param executor the executor that the callback runs on.
-     * @param callback a {@link GnssAntennaInfo.Callback} object to register.
-     * @return {@code true} if the callback was added successfully, {@code false} otherwise.
+     * @param executor the executor that the listener runs on.
+     * @param listener a {@link GnssAntennaInfo.Listener} object to register.
+     * @return {@code true} if the listener was added successfully, {@code false} otherwise.
      *
      * @throws IllegalArgumentException if executor is null
-     * @throws IllegalArgumentException if callback is null
+     * @throws IllegalArgumentException if listener is null
      * @throws SecurityException if the ACCESS_FINE_LOCATION permission is not present
      */
     @RequiresPermission(ACCESS_FINE_LOCATION)
-    public boolean registerAntennaInfoCallback(
+    public boolean registerAntennaInfoListener(
             @NonNull @CallbackExecutor Executor executor,
-            @NonNull GnssAntennaInfo.Callback callback) {
+            @NonNull GnssAntennaInfo.Listener listener) {
         try {
-            return mGnssAntennaInfoListenerManager.addListener(callback, executor);
+            return mGnssAntennaInfoListenerManager.addListener(listener, executor);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
     }
 
     /**
-     * Unregisters a GNSS Antenna Info callback.
+     * Unregisters a GNSS Antenna Info listener.
      *
-     * @param callback a {@link GnssAntennaInfo.Callback} object to remove.
+     * @param listener a {@link GnssAntennaInfo.Listener} object to remove.
      */
-    public void unregisterAntennaInfoCallback(@NonNull GnssAntennaInfo.Callback callback) {
+    public void unregisterAntennaInfoListener(@NonNull GnssAntennaInfo.Listener listener) {
         try {
-            mGnssAntennaInfoListenerManager.removeListener(callback);
+            mGnssAntennaInfoListenerManager.removeListener(listener);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -3043,7 +3038,7 @@
     }
 
     private class GnssAntennaInfoListenerManager extends
-            AbstractListenerManager<Void, GnssAntennaInfo.Callback> {
+            AbstractListenerManager<Void, GnssAntennaInfo.Listener> {
 
         @Nullable
         private IGnssAntennaInfoListener mListenerTransport;
@@ -3075,11 +3070,6 @@
             public void onGnssAntennaInfoReceived(final List<GnssAntennaInfo> gnssAntennaInfos) {
                 execute((callback) -> callback.onGnssAntennaInfoReceived(gnssAntennaInfos));
             }
-
-            @Override
-            public void onStatusChanged(int status) {
-                execute((listener) -> listener.onStatusChanged(status));
-            }
         }
 
     }
diff --git a/location/java/android/location/LocationManagerInternal.java b/location/java/android/location/LocationManagerInternal.java
index 085602c..6006d50 100644
--- a/location/java/android/location/LocationManagerInternal.java
+++ b/location/java/android/location/LocationManagerInternal.java
@@ -27,22 +27,6 @@
 public abstract class LocationManagerInternal {
 
     /**
-     * Requests that a provider change its allowed state. A provider may or may not honor this
-     * request, and if the provider does change its state as a result, that may happen
-     * asynchronously after some delay.
-     *
-     * <p>Setting a provider's state to allowed implies that any consents or terms and conditions
-     * that may be necessary to allow the provider are agreed to. Setting a providers state to
-     * disallowed implies that any consents or terms and conditions have their agreement revoked.
-     *
-     * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
-     * @param allowed  Whether the location provider is being requested to allow or disallow
-     *                 itself
-     * @throws IllegalArgumentException if provider is null
-     */
-    public abstract void requestSetProviderAllowed(@NonNull String provider, boolean allowed);
-
-    /**
      * Returns true if the given provider is enabled for the given user.
      *
      * @param provider A location provider as listed by {@link LocationManager#getAllProviders()}
diff --git a/location/java/com/android/internal/location/ILocationProvider.aidl b/location/java/com/android/internal/location/ILocationProvider.aidl
index b7817ff..4246c6c 100644
--- a/location/java/com/android/internal/location/ILocationProvider.aidl
+++ b/location/java/com/android/internal/location/ILocationProvider.aidl
@@ -37,6 +37,4 @@
 
     @UnsupportedAppUsage
     oneway void sendExtraCommand(String command, in Bundle extras);
-
-    oneway void requestSetAllowed(boolean allowed);
 }
diff --git a/location/lib/api/current.txt b/location/lib/api/current.txt
index 49fcaab..9cc30d0 100644
--- a/location/lib/api/current.txt
+++ b/location/lib/api/current.txt
@@ -17,7 +17,6 @@
     method @Deprecated protected int onGetStatus(android.os.Bundle);
     method @Deprecated protected long onGetStatusUpdateTime();
     method protected void onInit();
-    method protected void onRequestSetAllowed(boolean);
     method protected boolean onSendExtraCommand(@Nullable String, @Nullable android.os.Bundle);
     method protected abstract void onSetRequest(com.android.location.provider.ProviderRequestUnbundled, android.os.WorkSource);
     method public void reportLocation(android.location.Location);
diff --git a/location/lib/java/com/android/location/provider/LocationProviderBase.java b/location/lib/java/com/android/location/provider/LocationProviderBase.java
index bd29d8a..d3fb58f 100644
--- a/location/lib/java/com/android/location/provider/LocationProviderBase.java
+++ b/location/lib/java/com/android/location/provider/LocationProviderBase.java
@@ -315,17 +315,6 @@
         return false;
     }
 
-    /**
-     * Invoked when the system wishes to request that the provider sets its allowed state as
-     * desired. This implies that the caller is providing/retracting consent for any terms and
-     * conditions or consents associated with the provider.
-     *
-     * <p>It is generally only necessary to override this function if the provider has some barriers
-     * or gates for enabling/disabling itself, in which case this function should handle those
-     * appropriately. A provider that is always allowed has no need to override this function.
-     */
-    protected void onRequestSetAllowed(boolean allowed) {}
-
     private final class Service extends ILocationProvider.Stub {
 
         @Override
@@ -356,10 +345,5 @@
         public void sendExtraCommand(String command, Bundle extras) {
             onSendExtraCommand(command, extras);
         }
-
-        @Override
-        public void requestSetAllowed(boolean allowed) {
-            onRequestSetAllowed(allowed);
-        }
     }
 }
diff --git a/media/java/android/media/AudioDevice.aidl b/media/java/android/media/AudioDeviceAttributes.aidl
similarity index 94%
rename from media/java/android/media/AudioDevice.aidl
rename to media/java/android/media/AudioDeviceAttributes.aidl
index 02071e5..82d4226 100644
--- a/media/java/android/media/AudioDevice.aidl
+++ b/media/java/android/media/AudioDeviceAttributes.aidl
@@ -15,4 +15,4 @@
 
 package android.media;
 
-parcelable AudioDevice;
+parcelable AudioDeviceAttributes;
diff --git a/media/java/android/media/AudioDevice.java b/media/java/android/media/AudioDeviceAttributes.java
similarity index 82%
rename from media/java/android/media/AudioDevice.java
rename to media/java/android/media/AudioDeviceAttributes.java
index 31ecc7b..f5b0806 100644
--- a/media/java/android/media/AudioDevice.java
+++ b/media/java/android/media/AudioDeviceAttributes.java
@@ -28,8 +28,8 @@
 
 /**
  * @hide
- * Class to represent device type (speaker, headset...), address (if known) and role (input, output)
- * of an audio device.
+ * Class to represent the attributes of an audio device: its type (speaker, headset...), address
+ * (if known) and role (input, output).
  * <p>Unlike {@link AudioDeviceInfo}, the device
  * doesn't need to be connected to be uniquely identified, it can
  * for instance represent a specific A2DP headset even after a
@@ -39,7 +39,7 @@
  * permission, APIs using one rely on MODIFY_AUDIO_ROUTING.
  */
 @SystemApi
-public final class AudioDevice implements Parcelable {
+public final class AudioDeviceAttributes implements Parcelable {
 
     /**
      * A role identifying input devices, such as microphones.
@@ -78,7 +78,7 @@
      *                   type and address.
      */
     @SystemApi
-    public AudioDevice(@NonNull AudioDeviceInfo deviceInfo) {
+    public AudioDeviceAttributes(@NonNull AudioDeviceInfo deviceInfo) {
         Objects.requireNonNull(deviceInfo);
         mRole = deviceInfo.isSink() ? ROLE_OUTPUT : ROLE_INPUT;
         mType = deviceInfo.getType();
@@ -93,7 +93,7 @@
      * @param address the address of the device, or an empty string for devices without one
      */
     @SystemApi
-    public AudioDevice(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
+    public AudioDeviceAttributes(@Role int role, @AudioDeviceInfo.AudioDeviceType int type,
                               @NonNull String address) {
         Objects.requireNonNull(address);
         if (role != ROLE_OUTPUT && role != ROLE_INPUT) {
@@ -111,7 +111,7 @@
         mAddress = address;
     }
 
-    /*package*/ AudioDevice(int nativeType, @NonNull String address) {
+    /*package*/ AudioDeviceAttributes(int nativeType, @NonNull String address) {
         mRole = (nativeType & AudioSystem.DEVICE_BIT_IN) != 0 ? ROLE_INPUT : ROLE_OUTPUT;
         mType = AudioDeviceInfo.convertInternalDeviceToDeviceType(nativeType);
         mAddress = address;
@@ -157,7 +157,7 @@
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
 
-        AudioDevice that = (AudioDevice) o;
+        AudioDeviceAttributes that = (AudioDeviceAttributes) o;
         return ((mRole == that.mRole)
                 && (mType == that.mType)
                 && mAddress.equals(that.mAddress));
@@ -170,7 +170,7 @@
 
     @Override
     public String toString() {
-        return new String("AudioDevice:"
+        return new String("AudioDeviceAttributes:"
                 + " role:" + roleToString(mRole)
                 + " type:" + (mRole == ROLE_OUTPUT ? AudioSystem.getOutputDeviceName(
                         AudioDeviceInfo.convertDeviceTypeToInternalDevice(mType))
@@ -191,25 +191,25 @@
         dest.writeString(mAddress);
     }
 
-    private AudioDevice(@NonNull Parcel in) {
+    private AudioDeviceAttributes(@NonNull Parcel in) {
         mRole = in.readInt();
         mType = in.readInt();
         mAddress = in.readString();
     }
 
-    public static final @NonNull Parcelable.Creator<AudioDevice> CREATOR =
-            new Parcelable.Creator<AudioDevice>() {
+    public static final @NonNull Parcelable.Creator<AudioDeviceAttributes> CREATOR =
+            new Parcelable.Creator<AudioDeviceAttributes>() {
         /**
-         * Rebuilds an AudioDevice previously stored with writeToParcel().
-         * @param p Parcel object to read the AudioDevice from
-         * @return a new AudioDevice created from the data in the parcel
+         * Rebuilds an AudioDeviceAttributes previously stored with writeToParcel().
+         * @param p Parcel object to read the AudioDeviceAttributes from
+         * @return a new AudioDeviceAttributes created from the data in the parcel
          */
-        public AudioDevice createFromParcel(Parcel p) {
-            return new AudioDevice(p);
+        public AudioDeviceAttributes createFromParcel(Parcel p) {
+            return new AudioDeviceAttributes(p);
         }
 
-        public AudioDevice[] newArray(int size) {
-            return new AudioDevice[size];
+        public AudioDeviceAttributes[] newArray(int size) {
+            return new AudioDeviceAttributes[size];
         }
     };
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 112bb9c..383202b 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -1597,7 +1597,7 @@
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public boolean setPreferredDeviceForStrategy(@NonNull AudioProductStrategy strategy,
-            @NonNull AudioDevice device) {
+            @NonNull AudioDeviceAttributes device) {
         Objects.requireNonNull(strategy);
         Objects.requireNonNull(device);
         try {
@@ -1612,7 +1612,7 @@
     /**
      * @hide
      * Removes the preferred audio device previously set with
-     * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)}.
+     * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}.
      * @param strategy the audio strategy whose routing will be affected
      * @return true if the operation was successful, false otherwise (invalid strategy, or no
      *     device set for example)
@@ -1633,14 +1633,14 @@
     /**
      * @hide
      * Return the preferred device for an audio strategy, previously set with
-     * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)}
+     * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)}
      * @param strategy the strategy to query
      * @return the preferred device for that strategy, or null if none was ever set or if the
      *    strategy is invalid
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
-    public @Nullable AudioDevice getPreferredDeviceForStrategy(
+    public @Nullable AudioDeviceAttributes getPreferredDeviceForStrategy(
             @NonNull AudioProductStrategy strategy) {
         Objects.requireNonNull(strategy);
         try {
@@ -1654,7 +1654,13 @@
      * @hide
      * Interface to be notified of changes in the preferred audio device set for a given audio
      * strategy.
-     * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDevice)
+     * <p>Note that this listener will only be invoked whenever
+     * {@link #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)} or
+     * {@link #removePreferredDeviceForStrategy(AudioProductStrategy)} causes a change in
+     * preferred device. It will not be invoked directly after registration with
+     * {@link #addOnPreferredDeviceForStrategyChangedListener(Executor, OnPreferredDeviceForStrategyChangedListener)}
+     * to indicate which strategies had preferred devices at the time of registration.</p>
+     * @see #setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceAttributes)
      * @see #removePreferredDeviceForStrategy(AudioProductStrategy)
      * @see #getPreferredDeviceForStrategy(AudioProductStrategy)
      */
@@ -1668,7 +1674,7 @@
          *              preferred audio device
          */
         void onPreferredDeviceForStrategyChanged(@NonNull AudioProductStrategy strategy,
-                @Nullable AudioDevice device);
+                @Nullable AudioDeviceAttributes device);
     }
 
     /**
@@ -1768,7 +1774,8 @@
             extends IStrategyPreferredDeviceDispatcher.Stub {
 
         @Override
-        public void dispatchPrefDeviceChanged(int strategyId, @Nullable AudioDevice device) {
+        public void dispatchPrefDeviceChanged(int strategyId,
+                                              @Nullable AudioDeviceAttributes device) {
             // make a shallow copy of listeners so callback is not executed under lock
             final ArrayList<PrefDevListenerInfo> prefDevListeners;
             synchronized (mPrefDevListenerLock) {
@@ -4553,7 +4560,7 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
-    public @NonNull List<AudioDevice> getDevicesForAttributes(
+    public @NonNull List<AudioDeviceAttributes> getDevicesForAttributes(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
         final IAudioService service = getService();
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 53379b87..8b973a1 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -1096,18 +1096,18 @@
      * @return an empty list if there was an issue with the request, a list of audio devices
      *   otherwise (typically one device, except for duplicated paths).
      */
-    public static @NonNull ArrayList<AudioDevice> getDevicesForAttributes(
+    public static @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
-        final AudioDevice[] devices = new AudioDevice[MAX_DEVICE_ROUTING];
+        final AudioDeviceAttributes[] devices = new AudioDeviceAttributes[MAX_DEVICE_ROUTING];
         final int res = getDevicesForAttributes(attributes, devices);
-        final ArrayList<AudioDevice> routeDevices = new ArrayList<>();
+        final ArrayList<AudioDeviceAttributes> routeDevices = new ArrayList<>();
         if (res != SUCCESS) {
             Log.e(TAG, "error " + res + " in getDevicesForAttributes for " + attributes);
             return routeDevices;
         }
 
-        for (AudioDevice device : devices) {
+        for (AudioDeviceAttributes device : devices) {
             if (device != null) {
                 routeDevices.add(device);
             }
@@ -1117,12 +1117,12 @@
 
     /**
      * Maximum number of audio devices a track is ever routed to, determines the size of the
-     * array passed to {@link #getDevicesForAttributes(AudioAttributes, AudioDevice[])}
+     * array passed to {@link #getDevicesForAttributes(AudioAttributes, AudioDeviceAttributes[])}
      */
     private static final int MAX_DEVICE_ROUTING = 4;
 
     private static native int getDevicesForAttributes(@NonNull AudioAttributes aa,
-                                                      @NonNull AudioDevice[] devices);
+                                                      @NonNull AudioDeviceAttributes[] devices);
 
     /** @hide returns true if master mono is enabled. */
     public static native boolean getMasterMono();
@@ -1257,7 +1257,7 @@
      * @return {@link #SUCCESS} if successfully set
      */
     public static int setPreferredDeviceForStrategy(
-            int strategy, @NonNull AudioDevice device) {
+            int strategy, @NonNull AudioDeviceAttributes device) {
         return setPreferredDeviceForStrategy(strategy,
                 AudioDeviceInfo.convertDeviceTypeToInternalDevice(device.getType()),
                 device.getAddress());
@@ -1288,7 +1288,7 @@
      *     and written to the array
      */
     public static native int getPreferredDeviceForStrategy(int strategy,
-                                                           AudioDevice[] device);
+                                                           AudioDeviceAttributes[] device);
 
     // Items shared with audio service
 
diff --git a/media/java/android/media/DrmInitData.java b/media/java/android/media/DrmInitData.java
index cc35f14..d803311 100644
--- a/media/java/android/media/DrmInitData.java
+++ b/media/java/android/media/DrmInitData.java
@@ -37,7 +37,9 @@
      *
      * @param schemeUuid The DRM scheme's UUID.
      * @return The initialization data for the scheme, or null if the scheme is not supported.
+     * @deprecated Use {@link #getSchemeInitDataCount} and {@link #getSchemeInitDataAt} instead.
      */
+    @Deprecated
     public abstract SchemeInitData get(UUID schemeUuid);
 
     /**
diff --git a/media/java/android/media/IAudioService.aidl b/media/java/android/media/IAudioService.aidl
index 27bf3fe..5f320cd 100644
--- a/media/java/android/media/IAudioService.aidl
+++ b/media/java/android/media/IAudioService.aidl
@@ -18,7 +18,7 @@
 
 import android.bluetooth.BluetoothDevice;
 import android.media.AudioAttributes;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioFocusInfo;
 import android.media.AudioPlaybackConfiguration;
 import android.media.AudioRecordingConfiguration;
@@ -275,13 +275,13 @@
 
     boolean isCallScreeningModeSupported();
 
-    int setPreferredDeviceForStrategy(in int strategy, in AudioDevice device);
+    int setPreferredDeviceForStrategy(in int strategy, in AudioDeviceAttributes device);
 
     int removePreferredDeviceForStrategy(in int strategy);
 
-    AudioDevice getPreferredDeviceForStrategy(in int strategy);
+    AudioDeviceAttributes getPreferredDeviceForStrategy(in int strategy);
 
-    List<AudioDevice> getDevicesForAttributes(in AudioAttributes attributes);
+    List<AudioDeviceAttributes> getDevicesForAttributes(in AudioAttributes attributes);
 
     int setAllowedCapturePolicy(in int capturePolicy);
 
diff --git a/media/java/android/media/IMediaRoute2ProviderService.aidl b/media/java/android/media/IMediaRoute2ProviderService.aidl
index cd0def3..6cd2547 100644
--- a/media/java/android/media/IMediaRoute2ProviderService.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderService.aidl
@@ -29,13 +29,13 @@
     // MediaRoute2ProviderService#MediaRoute2ProviderServiceStub for readability.
     void setCallback(IMediaRoute2ProviderServiceCallback callback);
     void updateDiscoveryPreference(in RouteDiscoveryPreference discoveryPreference);
-    void setRouteVolume(String routeId, int volume);
+    void setRouteVolume(String routeId, int volume, long requestId);
 
     void requestCreateSession(String packageName, String routeId, long requestId,
             in @nullable Bundle sessionHints);
-    void selectRoute(String sessionId, String routeId);
-    void deselectRoute(String sessionId, String routeId);
-    void transferToRoute(String sessionId, String routeId);
-    void setSessionVolume(String sessionId, int volume);
-    void releaseSession(String sessionId);
+    void selectRoute(String sessionId, String routeId, long requestId);
+    void deselectRoute(String sessionId, String routeId, long requestId);
+    void transferToRoute(String sessionId, String routeId, long requestId);
+    void setSessionVolume(String sessionId, int volume, long requestId);
+    void releaseSession(String sessionId, long requestId);
 }
diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
index e35b0c4..ab42d75 100644
--- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
@@ -31,4 +31,5 @@
     void notifySessionCreationFailed(long requestId);
     void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
     void notifySessionReleased(in RoutingSessionInfo sessionInfo);
+    void notifyRequestFailed(long requestId, int reason);
 }
diff --git a/media/java/android/media/IMediaRouter2Manager.aidl b/media/java/android/media/IMediaRouter2Manager.aidl
index ffad659..a2f9ee9 100644
--- a/media/java/android/media/IMediaRouter2Manager.aidl
+++ b/media/java/android/media/IMediaRouter2Manager.aidl
@@ -30,4 +30,5 @@
     void notifyRoutesAdded(in List<MediaRoute2Info> routes);
     void notifyRoutesRemoved(in List<MediaRoute2Info> routes);
     void notifyRoutesChanged(in List<MediaRoute2Info> routes);
+    void notifyRequestFailed(int requestId, int reason);
 }
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index cbec323..c7cb07d 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -71,16 +71,17 @@
     void registerManager(IMediaRouter2Manager manager, String packageName);
     void unregisterManager(IMediaRouter2Manager manager);
     void setRouteVolumeWithManager(IMediaRouter2Manager manager, in MediaRoute2Info route,
-            int volume);
+            int volume, int requestId);
 
     void requestCreateSessionWithManager(IMediaRouter2Manager manager, String packageName,
             in @nullable MediaRoute2Info route, int requestId);
     void selectRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            in MediaRoute2Info route);
+            in MediaRoute2Info route, int requestId);
     void deselectRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            in MediaRoute2Info route);
+            in MediaRoute2Info route, int requestId);
     void transferToRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            in MediaRoute2Info route);
-    void setSessionVolumeWithManager(IMediaRouter2Manager manager, String sessionId, int volume);
-    void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId);
+            in MediaRoute2Info route, int requestId);
+    void setSessionVolumeWithManager(IMediaRouter2Manager manager, String sessionId, int volume,
+            int requestId);
+    void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId, int requestId);
 }
diff --git a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl b/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
index 6db9e52..b1f99e6 100644
--- a/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
+++ b/media/java/android/media/IStrategyPreferredDeviceDispatcher.aidl
@@ -16,7 +16,7 @@
 
 package android.media;
 
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 
 /**
  * AIDL for AudioService to signal audio strategy-preferred device updates.
@@ -25,6 +25,6 @@
  */
 oneway interface IStrategyPreferredDeviceDispatcher {
 
-    void dispatchPrefDeviceChanged(int strategyId, in AudioDevice device);
+    void dispatchPrefDeviceChanged(int strategyId, in AudioDeviceAttributes device);
 
 }
diff --git a/media/java/android/media/MediaCas.java b/media/java/android/media/MediaCas.java
index cefc9db..3a771bb 100644
--- a/media/java/android/media/MediaCas.java
+++ b/media/java/android/media/MediaCas.java
@@ -19,14 +19,20 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.Context;
 import android.hardware.cas.V1_0.HidlCasPluginDescriptor;
 import android.hardware.cas.V1_0.ICas;
 import android.hardware.cas.V1_0.IMediaCasService;
 import android.hardware.cas.V1_2.ICasListener;
+import android.hardware.cas.V1_2.Status;
 import android.media.MediaCasException.*;
 import android.media.tv.TvInputService.PriorityHintUseCaseType;
+import android.media.tv.tunerresourcemanager.CasSessionRequest;
+import android.media.tv.tunerresourcemanager.ResourceClientProfile;
+import android.media.tv.tunerresourcemanager.TunerResourceManager;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.HandlerThread;
 import android.os.IHwBinder;
 import android.os.Looper;
@@ -39,6 +45,9 @@
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
 
 /**
  * MediaCas can be used to obtain keys for descrambling protected media streams, in
@@ -110,6 +119,10 @@
     private EventHandler mEventHandler;
     private @PriorityHintUseCaseType int mPriorityHint;
     private String mTvInputServiceSessionId;
+    private int mClientId;
+    private int mCasSystemId;
+    private TunerResourceManager mTunerResourceManager = null;
+    private final Map<Session, Integer> mSessionMap = new HashMap<>();
 
     /**
      * Scrambling modes used to open cas sessions.
@@ -329,6 +342,10 @@
                         createFromSessionId(sessionId), msg.arg1, msg.arg2,
                         bundle.getByteArray(DATA_KEY));
             } else if (msg.what == MSG_CAS_STATUS_EVENT) {
+                if ((msg.arg1 == PLUGIN_STATUS_SESSION_NUMBER_CHANGED)
+                        && (mTunerResourceManager != null)) {
+                    mTunerResourceManager.updateCasInfo(mCasSystemId, msg.arg2);
+                }
                 mListener.onPluginStatusUpdate(MediaCas.this, msg.arg1, msg.arg2);
             } else if (msg.what == MSG_CAS_RESOURCE_LOST) {
                 mListener.onResourceLost(MediaCas.this);
@@ -364,6 +381,19 @@
                     EventHandler.MSG_CAS_STATUS_EVENT, status, arg));
         }
     };
+
+    private final TunerResourceManager.ResourcesReclaimListener mResourceListener =
+            new TunerResourceManager.ResourcesReclaimListener() {
+            @Override
+            public void onReclaimResources() {
+                synchronized (mSessionMap) {
+                    mSessionMap.forEach((casSession, sessionResourceId) -> casSession.close());
+                }
+                mEventHandler.sendMessage(mEventHandler.obtainMessage(
+                        EventHandler.MSG_CAS_RESOURCE_LOST));
+            }
+        };
+
     /**
      * Describe a CAS plugin with its CA_system_ID and string name.
      *
@@ -429,11 +459,21 @@
      */
     public final class Session implements AutoCloseable {
         final ArrayList<Byte> mSessionId;
+        boolean mIsClosed = false;
 
         Session(@NonNull ArrayList<Byte> sessionId) {
             mSessionId = new ArrayList<Byte>(sessionId);
         }
 
+        private void validateSessionInternalStates() {
+            if (mICas == null) {
+                throw new IllegalStateException();
+            }
+            if (mIsClosed) {
+                MediaCasStateException.throwExceptionIfNeeded(Status.ERROR_CAS_SESSION_NOT_OPENED);
+            }
+        }
+
         /**
          * Query if an object equal current Session object.
          *
@@ -459,7 +499,7 @@
          */
         public void setPrivateData(@NonNull byte[] data)
                 throws MediaCasException {
-            validateInternalStates();
+            validateSessionInternalStates();
 
             try {
                 MediaCasException.throwExceptionIfNeeded(
@@ -483,7 +523,7 @@
          */
         public void processEcm(@NonNull byte[] data, int offset, int length)
                 throws MediaCasException {
-            validateInternalStates();
+            validateSessionInternalStates();
 
             try {
                 MediaCasException.throwExceptionIfNeeded(
@@ -522,7 +562,7 @@
          */
         public void sendSessionEvent(int event, int arg, @Nullable byte[] data)
                 throws MediaCasException {
-            validateInternalStates();
+            validateSessionInternalStates();
 
             if (mICasV11 == null) {
                 Log.d(TAG, "Send Session Event isn't supported by cas@1.0 interface");
@@ -546,7 +586,7 @@
          */
         @NonNull
         public byte[] getSessionId() {
-            validateInternalStates();
+            validateSessionInternalStates();
             return toBytes(mSessionId);
         }
 
@@ -558,11 +598,12 @@
          */
         @Override
         public void close() {
-            validateInternalStates();
-
+            validateSessionInternalStates();
             try {
                 MediaCasStateException.throwExceptionIfNeeded(
                         mICas.closeSession(mSessionId));
+                mIsClosed = true;
+                removeSessionFromResourceMap(this);
             } catch (RemoteException e) {
                 cleanupAndRethrowIllegalState();
             }
@@ -664,6 +705,7 @@
     /**
      * Instantiate a CA system of the specified system id.
      *
+     * @param context the context of the caller.
      * @param casSystemId The system id of the CA system.
      * @param tvInputServiceSessionId The Id of the session opened in TV Input Service (TIS)
      *        {@link android.media.tv.TvInputService#onCreateSession(String, String)}
@@ -672,11 +714,23 @@
      * @throws UnsupportedCasException if the device does not support the
      * specified CA system.
      */
-    public MediaCas(int casSystemId, @Nullable String tvInputServiceSessionId,
-            @PriorityHintUseCaseType int priorityHint)  throws UnsupportedCasException {
+    public MediaCas(@NonNull Context context, int casSystemId,
+            @Nullable String tvInputServiceSessionId,
+            @PriorityHintUseCaseType int priorityHint) throws UnsupportedCasException {
         this(casSystemId);
-        mPriorityHint = priorityHint;
-        mTvInputServiceSessionId = tvInputServiceSessionId;
+
+        Objects.requireNonNull(context, "context must not be null");
+        mCasSystemId = casSystemId;
+        mTunerResourceManager = (TunerResourceManager)
+                context.getSystemService(Context.TV_TUNER_RESOURCE_MGR_SERVICE);
+        if (mTunerResourceManager != null) {
+            int[] clientId = new int[1];
+            ResourceClientProfile profile =
+                    new ResourceClientProfile(tvInputServiceSessionId, priorityHint);
+            mTunerResourceManager.registerClientProfile(
+                    profile, new HandlerExecutor(mEventHandler), mResourceListener, clientId);
+            mClientId = clientId[0];
+        }
     }
 
     IHwBinder getBinder() {
@@ -813,6 +867,40 @@
         }
     }
 
+    private int getSessionResourceId() throws MediaCasException {
+        validateInternalStates();
+
+        int[] sessionResourceId = new int[1];
+        sessionResourceId[0] = -1;
+        if (mTunerResourceManager != null) {
+            CasSessionRequest casSessionRequest = new CasSessionRequest(mClientId, mCasSystemId);
+            if (!mTunerResourceManager.requestCasSession(casSessionRequest, sessionResourceId)) {
+                throw new MediaCasException.ResourceBusyException(
+                    "insufficient resource to Open Session");
+            }
+        }
+        return  sessionResourceId[0];
+    }
+
+    private void addSessionToResourceMap(Session session, int sessionResourceId) {
+
+        if (sessionResourceId != -1) {
+            synchronized (mSessionMap) {
+                mSessionMap.put(session, sessionResourceId);
+            }
+        }
+    }
+
+    private void removeSessionFromResourceMap(Session session) {
+
+        synchronized (mSessionMap) {
+            if (mSessionMap.get(session) != null) {
+                mTunerResourceManager.releaseCasSession(mSessionMap.get(session));
+                mSessionMap.remove(session);
+            }
+        }
+    }
+
     /**
      * Open a session to descramble one or more streams scrambled by the
      * conditional access system.
@@ -824,12 +912,13 @@
      * @throws MediaCasStateException for CAS-specific state exceptions.
      */
     public Session openSession() throws MediaCasException {
-        validateInternalStates();
+        int sessionResourceId = getSessionResourceId();
 
         try {
             OpenSessionCallback cb = new OpenSessionCallback();
             mICas.openSession(cb);
             MediaCasException.throwExceptionIfNeeded(cb.mStatus);
+            addSessionToResourceMap(cb.mSession, sessionResourceId);
             return cb.mSession;
         } catch (RemoteException e) {
             cleanupAndRethrowIllegalState();
@@ -853,7 +942,7 @@
     @Nullable
     public Session openSession(@SessionUsage int sessionUsage, @ScramblingMode int scramblingMode)
             throws MediaCasException {
-        validateInternalStates();
+        int sessionResourceId = getSessionResourceId();
 
         if (mICasV12 == null) {
             Log.d(TAG, "Open Session with scrambling mode is only supported by cas@1.2+ interface");
@@ -864,6 +953,7 @@
             OpenSession_1_2_Callback cb = new OpenSession_1_2_Callback();
             mICasV12.openSession_1_2(sessionUsage, scramblingMode, cb);
             MediaCasException.throwExceptionIfNeeded(cb.mStatus);
+            addSessionToResourceMap(cb.mSession, sessionResourceId);
             return cb.mSession;
         } catch (RemoteException e) {
             cleanupAndRethrowIllegalState();
@@ -987,6 +1077,16 @@
                 mICas = null;
             }
         }
+
+        if (mTunerResourceManager != null) {
+            mTunerResourceManager.unregisterClientProfile(mClientId);
+            mTunerResourceManager = null;
+        }
+
+        if (mHandlerThread != null) {
+            mHandlerThread.quit();
+            mHandlerThread = null;
+        }
     }
 
     @Override
diff --git a/media/java/android/media/MediaCodec.java b/media/java/android/media/MediaCodec.java
index abc7e0b..f2b4db1 100644
--- a/media/java/android/media/MediaCodec.java
+++ b/media/java/android/media/MediaCodec.java
@@ -1959,7 +1959,7 @@
      * If this codec is to be used with {@link LinearBlock} and/or {@link
      * GraphicBlock}, pass this flag.
      * <p>
-     * When this flag is set, the following APIs throw IllegalStateException.
+     * When this flag is set, the following APIs throw {@link IncompatibleWithBlockModelException}.
      * <ul>
      * <li>{@link #getInputBuffer}
      * <li>{@link #getInputImage}
@@ -1986,6 +1986,12 @@
     public @interface ConfigureFlag {}
 
     /**
+     * Thrown when the codec is configured for block model and an incompatible API is called.
+     */
+    public class IncompatibleWithBlockModelException extends RuntimeException {
+    }
+
+    /**
      * Configures a component.
      *
      * @param format The format of the input data (decoder) or the desired
@@ -2526,7 +2532,7 @@
         throws CryptoException {
         synchronized(mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
             invalidateByteBuffer(mCachedInputBuffers, index);
             mDequeuedInputBuffers.remove(index);
@@ -2778,7 +2784,7 @@
             int flags) throws CryptoException {
         synchronized(mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
             invalidateByteBuffer(mCachedInputBuffers, index);
             mDequeuedInputBuffers.remove(index);
@@ -2813,7 +2819,7 @@
     public final int dequeueInputBuffer(long timeoutUs) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         int res = native_dequeueInputBuffer(timeoutUs);
@@ -2848,7 +2854,7 @@
         public boolean isMappable() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The linear block is invalid");
                 }
                 return mMappable;
             }
@@ -2867,10 +2873,10 @@
         public @NonNull ByteBuffer map() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The linear block is invalid");
                 }
                 if (!mMappable) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The linear block is not mappable");
                 }
                 if (mMapped == null) {
                     mMapped = native_map();
@@ -2896,7 +2902,7 @@
         public void recycle() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The linear block is invalid");
                 }
                 if (mMapped != null) {
                     mMapped.setAccessible(false);
@@ -3002,7 +3008,7 @@
         public boolean isMappable() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The graphic block is invalid");
                 }
                 return mMappable;
             }
@@ -3021,10 +3027,10 @@
         public @NonNull Image map() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The graphic block is invalid");
                 }
                 if (!mMappable) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The graphic block is not mappable");
                 }
                 if (mMapped == null) {
                     mMapped = native_map();
@@ -3050,7 +3056,7 @@
         public void recycle() {
             synchronized (mLock) {
                 if (!mValid) {
-                    throw new IllegalStateException();
+                    throw new IllegalStateException("The graphic block is invalid");
                 }
                 if (mMapped != null) {
                     mMapped.close();
@@ -3127,8 +3133,9 @@
             if (buffer == null) {
                 buffer = new GraphicBlock();
             }
-            if (width < 0 || height < 0) {
-                throw new IllegalArgumentException();
+            if (width <= 0 || height <= 0) {
+                throw new IllegalArgumentException(
+                        "non-positive width or height: " + width + "x" + height);
             }
             synchronized (buffer.mLock) {
                 buffer.native_obtain(width, height, format, usage, codecNames);
@@ -3177,16 +3184,8 @@
          * @param block The linear block object
          * @param offset The byte offset into the input buffer at which the data starts.
          * @param size The number of bytes of valid input data.
-         * @param presentationTimeUs The presentation timestamp in microseconds for this
-         *                           buffer. This is normally the media time at which this
-         *                           buffer should be presented (rendered). When using an output
-         *                           surface, this will be propagated as the {@link
-         *                           SurfaceTexture#getTimestamp timestamp} for the frame (after
-         *                           conversion to nanoseconds).
-         * @param flags A bitmask of flags
-         *              {@link #BUFFER_FLAG_CODEC_CONFIG} and {@link #BUFFER_FLAG_END_OF_STREAM}.
-         *              While not prohibited, most codecs do not use the
-         *              {@link #BUFFER_FLAG_KEY_FRAME} flag for input buffers.
+         * @param cryptoInfo Metadata describing the structure of the encrypted input sample.
+         *                   may be null if clear.
          * @return this object
          * @throws IllegalStateException if a buffer is already set
          */
@@ -3194,59 +3193,17 @@
                 @NonNull LinearBlock block,
                 int offset,
                 int size,
-                long presentationTimeUs,
-                @BufferFlag int flags) {
+                @Nullable MediaCodec.CryptoInfo cryptoInfo) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             if (mLinearBlock != null || mGraphicBlock != null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("Cannot set block twice");
             }
             mLinearBlock = block;
             mOffset = offset;
             mSize = size;
-            mPresentationTimeUs = presentationTimeUs;
-            mFlags = flags;
-            return this;
-        }
-
-        /**
-         * Set an encrypted linear block to this queue request. Exactly one
-         * buffer must be set for a queue request before calling {@link #queue}.
-         *
-         * @param block The linear block object
-         * @param offset The byte offset into the input buffer at which the data starts.
-         * @param presentationTimeUs The presentation timestamp in microseconds for this
-         *                           buffer. This is normally the media time at which this
-         *                           buffer should be presented (rendered). When using an output
-         *                           surface, this will be propagated as the {@link
-         *                           SurfaceTexture#getTimestamp timestamp} for the frame (after
-         *                           conversion to nanoseconds).
-         * @param cryptoInfo Metadata describing the structure of the encrypted input sample.
-         * @param flags A bitmask of flags
-         *              {@link #BUFFER_FLAG_CODEC_CONFIG} and {@link #BUFFER_FLAG_END_OF_STREAM}.
-         *              While not prohibited, most codecs do not use the
-         *              {@link #BUFFER_FLAG_KEY_FRAME} flag for input buffers.
-         * @return this object
-         * @throws IllegalStateException if a buffer is already set
-         */
-        public @NonNull QueueRequest setEncryptedLinearBlock(
-                @NonNull LinearBlock block,
-                int offset,
-                @NonNull MediaCodec.CryptoInfo cryptoInfo,
-                long presentationTimeUs,
-                @BufferFlag int flags) {
-            if (!isAccessible()) {
-                throw new IllegalStateException();
-            }
-            if (mLinearBlock != null || mGraphicBlock != null) {
-                throw new IllegalStateException();
-            }
-            mLinearBlock = block;
-            mOffset = offset;
             mCryptoInfo = cryptoInfo;
-            mPresentationTimeUs = presentationTimeUs;
-            mFlags = flags;
             return this;
         }
 
@@ -3255,45 +3212,72 @@
          * be set for a queue request before calling {@link #queue}.
          *
          * @param block The graphic block object
+         * @return this object
+         * @throws IllegalStateException if a buffer is already set
+         */
+        public @NonNull QueueRequest setGraphicBlock(
+                @NonNull GraphicBlock block) {
+            if (!isAccessible()) {
+                throw new IllegalStateException("The request is stale");
+            }
+            if (mLinearBlock != null || mGraphicBlock != null) {
+                throw new IllegalStateException("Cannot set block twice");
+            }
+            mGraphicBlock = block;
+            return this;
+        }
+
+        /**
+         * Set timestamp to this queue request.
+         *
          * @param presentationTimeUs The presentation timestamp in microseconds for this
          *                           buffer. This is normally the media time at which this
          *                           buffer should be presented (rendered). When using an output
          *                           surface, this will be propagated as the {@link
          *                           SurfaceTexture#getTimestamp timestamp} for the frame (after
          *                           conversion to nanoseconds).
+         * @return this object
+         */
+        public @NonNull QueueRequest setPresentationTimeUs(long presentationTimeUs) {
+            if (!isAccessible()) {
+                throw new IllegalStateException("The request is stale");
+            }
+            mPresentationTimeUs = presentationTimeUs;
+            return this;
+        }
+
+        /**
+         * Set flags to this queue request.
+         *
          * @param flags A bitmask of flags
          *              {@link #BUFFER_FLAG_CODEC_CONFIG} and {@link #BUFFER_FLAG_END_OF_STREAM}.
          *              While not prohibited, most codecs do not use the
          *              {@link #BUFFER_FLAG_KEY_FRAME} flag for input buffers.
          * @return this object
-         * @throws IllegalStateException if a buffer is already set
          */
-        public @NonNull QueueRequest setGraphicBlock(
-                @NonNull GraphicBlock block,
-                long presentationTimeUs,
-                @BufferFlag int flags) {
+        public @NonNull QueueRequest setFlags(@BufferFlag int flags) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
-            if (mLinearBlock != null || mGraphicBlock != null) {
-                throw new IllegalStateException();
-            }
-            mGraphicBlock = block;
-            mPresentationTimeUs = presentationTimeUs;
             mFlags = flags;
             return this;
         }
 
         /**
-         * Add a integer parameter. See {@link MediaFormat} for the list of
-         * supported tunings. If there was {@link MediaCodec#setParameters}
+         * Add an integer parameter.
+         * See {@link MediaFormat} for an exhaustive list of supported keys with
+         * values of type int, that can also be set with {@link MediaFormat#setInteger}.
+         *
+         * If there was {@link MediaCodec#setParameters}
          * call with the same key which is not processed by the codec yet, the
          * value set from this method will override the unprocessed value.
+         *
+         * @return this object
          */
         public @NonNull QueueRequest setIntegerParameter(
                 @NonNull String key, int value) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             mTuningKeys.add(key);
             mTuningValues.add(Integer.valueOf(value));
@@ -3301,15 +3285,20 @@
         }
 
         /**
-         * Add a long parameter. See {@link MediaFormat} for the list of
-         * supported tunings. If there was {@link MediaCodec#setParameters}
+         * Add a long parameter.
+         * See {@link MediaFormat} for an exhaustive list of supported keys with
+         * values of type long, that can also be set with {@link MediaFormat#setLong}.
+         *
+         * If there was {@link MediaCodec#setParameters}
          * call with the same key which is not processed by the codec yet, the
          * value set from this method will override the unprocessed value.
+         *
+         * @return this object
          */
         public @NonNull QueueRequest setLongParameter(
                 @NonNull String key, long value) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             mTuningKeys.add(key);
             mTuningValues.add(Long.valueOf(value));
@@ -3317,15 +3306,20 @@
         }
 
         /**
-         * Add a float parameter. See {@link MediaFormat} for the list of
-         * supported tunings. If there was {@link MediaCodec#setParameters}
+         * Add a float parameter.
+         * See {@link MediaFormat} for an exhaustive list of supported keys with
+         * values of type float, that can also be set with {@link MediaFormat#setFloat}.
+         *
+         * If there was {@link MediaCodec#setParameters}
          * call with the same key which is not processed by the codec yet, the
          * value set from this method will override the unprocessed value.
+         *
+         * @return this object
          */
         public @NonNull QueueRequest setFloatParameter(
                 @NonNull String key, float value) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             mTuningKeys.add(key);
             mTuningValues.add(Float.valueOf(value));
@@ -3333,15 +3327,20 @@
         }
 
         /**
-         * Add a {@link ByteBuffer} parameter. See {@link MediaFormat} for the list of
-         * supported tunings. If there was {@link MediaCodec#setParameters}
+         * Add a {@link ByteBuffer} parameter.
+         * See {@link MediaFormat} for an exhaustive list of supported keys with
+         * values of byte buffer, that can also be set with {@link MediaFormat#setByteBuffer}.
+         *
+         * If there was {@link MediaCodec#setParameters}
          * call with the same key which is not processed by the codec yet, the
          * value set from this method will override the unprocessed value.
+         *
+         * @return this object
          */
         public @NonNull QueueRequest setByteBufferParameter(
                 @NonNull String key, @NonNull ByteBuffer value) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             mTuningKeys.add(key);
             mTuningValues.add(value);
@@ -3349,15 +3348,20 @@
         }
 
         /**
-         * Add a string parameter. See {@link MediaFormat} for the list of
-         * supported tunings. If there was {@link MediaCodec#setParameters}
+         * Add a string parameter.
+         * See {@link MediaFormat} for an exhaustive list of supported keys with
+         * values of type string, that can also be set with {@link MediaFormat#setString}.
+         *
+         * If there was {@link MediaCodec#setParameters}
          * call with the same key which is not processed by the codec yet, the
          * value set from this method will override the unprocessed value.
+         *
+         * @return this object
          */
         public @NonNull QueueRequest setStringParameter(
                 @NonNull String key, @NonNull String value) {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             mTuningKeys.add(key);
             mTuningValues.add(value);
@@ -3369,10 +3373,10 @@
          */
         public void queue() {
             if (!isAccessible()) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The request is stale");
             }
             if (mLinearBlock == null && mGraphicBlock == null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("No block is set");
             }
             setAccessible(false);
             if (mLinearBlock != null) {
@@ -3447,7 +3451,7 @@
     private final ArrayList<QueueRequest> mQueueRequests = new ArrayList<>();
 
     /**
-     * Return a clear {@link QueueRequest} object for an input slot index.
+     * Return a {@link QueueRequest} object for an input slot index.
      *
      * @param index input slot index from
      *              {@link Callback#onInputBufferAvailable}
@@ -3459,17 +3463,19 @@
     public @NonNull QueueRequest getQueueRequest(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_BLOCK) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The codec is not configured for block model");
             }
             if (index < 0 || index >= mQueueRequests.size()) {
-                throw new IllegalArgumentException();
+                throw new IndexOutOfBoundsException("Expected range of index: [0,"
+                        + (mQueueRequests.size() - 1) + "]; actual: " + index);
             }
             QueueRequest request = mQueueRequests.get(index);
             if (request == null) {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException("Unavailable index: " + index);
             }
             if (!request.isAccessible()) {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException(
+                        "The request is stale at index " + index);
             }
             return request.clear();
         }
@@ -3529,7 +3535,7 @@
             @NonNull BufferInfo info, long timeoutUs) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         int res = native_dequeueOutputBuffer(info, timeoutUs);
@@ -3644,7 +3650,8 @@
                     frame.clear();
                     break;
                 default:
-                    throw new IllegalStateException();
+                    throw new IllegalStateException(
+                            "Unrecognized buffer mode: " + mBufferMode);
             }
         }
         releaseOutputBuffer(
@@ -3910,7 +3917,7 @@
     public ByteBuffer[] getInputBuffers() {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
             if (mCachedInputBuffers == null) {
                 throw new IllegalStateException();
@@ -3946,7 +3953,7 @@
     public ByteBuffer[] getOutputBuffers() {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
             if (mCachedOutputBuffers == null) {
                 throw new IllegalStateException();
@@ -3978,7 +3985,7 @@
     public ByteBuffer getInputBuffer(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         ByteBuffer newBuffer = getBuffer(true /* input */, index);
@@ -4012,7 +4019,7 @@
     public Image getInputImage(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         Image newImage = getImage(true /* input */, index);
@@ -4046,7 +4053,7 @@
     public ByteBuffer getOutputBuffer(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         ByteBuffer newBuffer = getBuffer(false /* input */, index);
@@ -4079,7 +4086,7 @@
     public Image getOutputImage(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_LEGACY) {
-                throw new IllegalStateException();
+                throw new IncompatibleWithBlockModelException();
             }
         }
         Image newImage = getImage(false /* input */, index);
@@ -4106,7 +4113,7 @@
          */
         public @Nullable LinearBlock getLinearBlock() {
             if (mGraphicBlock != null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("This output frame is not linear");
             }
             return mLinearBlock;
         }
@@ -4118,7 +4125,7 @@
          */
         public @Nullable GraphicBlock getGraphicBlock() {
             if (mLinearBlock != null) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("This output frame is not graphic");
             }
             return mGraphicBlock;
         }
@@ -4139,7 +4146,7 @@
 
         /**
          * Returns a read-only {@link MediaFormat} for this frame. The returned
-         * object is valid only while the client is holding the output frame.
+         * object is valid only until the client calls {@link MediaCodec#releaseOutputBuffer}.
          */
         public @NonNull MediaFormat getFormat() {
             return mFormat;
@@ -4151,7 +4158,7 @@
          * Client can find out what the change is by querying {@link MediaFormat}
          * object returned from {@link #getFormat}.
          */
-        public void getChangedKeys(@NonNull Set<String> keys) {
+        public void retrieveChangedKeys(@NonNull Set<String> keys) {
             keys.clear();
             keys.addAll(mChangedKeys);
         }
@@ -4211,17 +4218,19 @@
     public @NonNull OutputFrame getOutputFrame(int index) {
         synchronized (mBufferLock) {
             if (mBufferMode != BUFFER_MODE_BLOCK) {
-                throw new IllegalStateException();
+                throw new IllegalStateException("The codec is not configured for block model");
             }
             if (index < 0 || index >= mOutputFrames.size()) {
-                throw new IllegalArgumentException();
+                throw new IndexOutOfBoundsException("Expected range of index: [0,"
+                        + (mQueueRequests.size() - 1) + "]; actual: " + index);
             }
             OutputFrame frame = mOutputFrames.get(index);
             if (frame == null) {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException("Unavailable index: " + index);
             }
             if (!frame.isAccessible()) {
-                throw new IllegalArgumentException();
+                throw new IllegalArgumentException(
+                        "The output frame is stale at index " + index);
             }
             if (!frame.isLoaded()) {
                 native_getOutputFrame(frame, index);
diff --git a/media/java/android/media/MediaRoute2Info.java b/media/java/android/media/MediaRoute2Info.java
index 0e88c75..bf04fe8 100644
--- a/media/java/android/media/MediaRoute2Info.java
+++ b/media/java/android/media/MediaRoute2Info.java
@@ -411,11 +411,10 @@
 
     /**
      * Returns true if the route info has all of the required field.
-     * A route info only obtained from {@link com.android.server.media.MediaRouterService}
-     * is valid.
+     * A route is valid if and only if it is obtained from
+     * {@link com.android.server.media.MediaRouterService}.
      * @hide
      */
-    //TODO: Reconsider the validity of a route info when fields are added.
     public boolean isValid() {
         if (TextUtils.isEmpty(getId()) || TextUtils.isEmpty(getName())
                 || TextUtils.isEmpty(getProviderId())) {
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index e205bbb..aa0eda1 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.annotation.CallSuper;
+import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
@@ -37,6 +38,8 @@
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
@@ -51,7 +54,7 @@
  * Media apps which use {@link MediaRouter2} can request to play their media on the routes.
  * </p><p>
  * When {@link MediaRouter2 media router} wants to play media on a route,
- * {@link #onCreateSession(String, String, long, Bundle)} will be called to handle the request.
+ * {@link #onCreateSession(long, String, String, Bundle)} will be called to handle the request.
  * A session can be considered as a group of currently selected routes for each connection.
  * Create and manage the sessions by yourself, and notify the {@link RoutingSessionInfo
  * session infos} when there are any changes.
@@ -61,6 +64,8 @@
  * a {@link MediaRouter2 media router} by an application. See
  * {@link #onDiscoveryPreferenceChanged(RouteDiscoveryPreference)} for the details.
  * </p>
+ * Use {@link #notifyRequestFailed(long, int)} to notify the failure with previously received
+ * request ID.
  */
 public abstract class MediaRoute2ProviderService extends Service {
     private static final String TAG = "MR2ProviderService";
@@ -79,7 +84,53 @@
      *
      * @see #notifySessionCreated(RoutingSessionInfo, long)
      */
-    public static final long REQUEST_ID_UNKNOWN = 0;
+    public static final long REQUEST_ID_NONE = 0;
+
+    /**
+     * The request has failed due to unknown reason.
+     *
+     * @see #notifyRequestFailed(long, int)
+     */
+    public static final int REASON_UNKNOWN_ERROR = 0;
+
+    /**
+     * The request has failed since this service rejected the request.
+     *
+     * @see #notifyRequestFailed(long, int)
+     */
+    public static final int REASON_REJECTED = 1;
+
+    /**
+     * The request has failed due to a network error.
+     *
+     * @see #notifyRequestFailed(long, int)
+     */
+    public static final int REASON_NETWORK_ERROR = 2;
+
+    /**
+     * The request has failed since the requested route is no longer available.
+     *
+     * @see #notifyRequestFailed(long, int)
+     */
+    public static final int REASON_ROUTE_NOT_AVAILABLE = 3;
+
+    /**
+     * The request has failed since the request is not valid. For example, selecting a route
+     * which is not selectable.
+     *
+     * @see #notifyRequestFailed(long, int)
+     */
+    public static final int REASON_INVALID_COMMAND = 4;
+
+    /**
+     * @hide
+     */
+    @IntDef(prefix = "REASON_", value = {
+            REASON_UNKNOWN_ERROR, REASON_REJECTED, REASON_NETWORK_ERROR, REASON_ROUTE_NOT_AVAILABLE,
+            REASON_INVALID_COMMAND
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface Reason {}
 
     private final Handler mHandler;
     private final Object mSessionLock = new Object();
@@ -104,7 +155,6 @@
     @Override
     @Nullable
     public IBinder onBind(@NonNull Intent intent) {
-        //TODO: Allow binding from media router service only?
         if (SERVICE_INTERFACE.equals(intent.getAction())) {
             if (mStub == null) {
                 mStub = new MediaRoute2ProviderServiceStub();
@@ -117,20 +167,23 @@
     /**
      * Called when a volume setting is requested on a route of the provider
      *
+     * @param requestId the id of this request
      * @param routeId the id of the route
      * @param volume the target volume
-     * @see MediaRoute2Info#getVolumeMax()
+     * @see MediaRoute2Info.Builder#setVolume(int)
      */
-    public abstract void onSetRouteVolume(@NonNull String routeId, int volume);
+    public abstract void onSetRouteVolume(long requestId, @NonNull String routeId, int volume);
 
     /**
      * Called when {@link MediaRouter2.RoutingController#setVolume(int)} is called on
      * a routing session of the provider
      *
+     * @param requestId the id of this request
      * @param sessionId the id of the routing session
      * @param volume the target volume
+     * @see RoutingSessionInfo.Builder#setVolume(int)
      */
-    public abstract void onSetSessionVolume(@NonNull String sessionId, int volume);
+    public abstract void onSetSessionVolume(long requestId, @NonNull String sessionId, int volume);
 
     /**
      * Gets information of the session with the given id.
@@ -162,14 +215,15 @@
     /**
      * Notifies clients of that the session is created and ready for use.
      * <p>
-     * If this session is created without any creation request, use {@link #REQUEST_ID_UNKNOWN}
+     * If this session is created without any creation request, use {@link #REQUEST_ID_NONE}
      * as the request ID.
      *
      * @param sessionInfo information of the new session.
      *                    The {@link RoutingSessionInfo#getId() id} of the session must be unique.
      * @param requestId id of the previous request to create this session provided in
-     *                  {@link #onCreateSession(String, String, long, Bundle)}
-     * @see #onCreateSession(String, String, long, Bundle)
+     *                  {@link #onCreateSession(long, String, String, Bundle)}. Can be
+     *                  {@link #REQUEST_ID_NONE} if this session is created without any request.
+     * @see #onCreateSession(long, String, String, Bundle)
      * @see #getSessionInfo(String)
      */
     public final void notifySessionCreated(@NonNull RoutingSessionInfo sessionInfo,
@@ -202,8 +256,8 @@
      * Notifies clients of that the session could not be created.
      *
      * @param requestId id of the previous request to create the session provided in
-     *                  {@link #onCreateSession(String, String, long, Bundle)}.
-     * @see #onCreateSession(String, String, long, Bundle)
+     *                  {@link #onCreateSession(long, String, String, Bundle)}.
+     * @see #onCreateSession(long, String, String, Bundle)
      */
     public final void notifySessionCreationFailed(long requestId) {
         if (mRemoteCallback == null) {
@@ -247,7 +301,7 @@
      * Notifies that the session is released.
      *
      * @param sessionId id of the released session.
-     * @see #onReleaseSession(String)
+     * @see #onReleaseSession(long, String)
      */
     public final void notifySessionReleased(@NonNull String sessionId) {
         if (TextUtils.isEmpty(sessionId)) {
@@ -274,6 +328,29 @@
     }
 
     /**
+     * Notifies to the client that the request has failed.
+     *
+     * @param requestId the ID of the previous request
+     * @param reason the reason why the request has failed
+     *
+     * @see #REASON_UNKNOWN_ERROR
+     * @see #REASON_REJECTED
+     * @see #REASON_NETWORK_ERROR
+     * @see #REASON_ROUTE_NOT_AVAILABLE
+     * @see #REASON_INVALID_COMMAND
+     */
+    public final void notifyRequestFailed(long requestId, @Reason int reason) {
+        if (mRemoteCallback == null) {
+            return;
+        }
+        try {
+            mRemoteCallback.notifyRequestFailed(requestId, reason);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed to notify that the request has failed.");
+        }
+    }
+
+    /**
      * Called when the service receives a request to create a session.
      * <p>
      * You should create and maintain your own session and notifies the client of
@@ -289,9 +366,9 @@
      * If you can't create the session or want to reject the request, call
      * {@link #notifySessionCreationFailed(long)} with the given {@code requestId}.
      *
+     * @param requestId the id of this request
      * @param packageName the package name of the application that selected the route
      * @param routeId the id of the route initially being connected
-     * @param requestId the id of this session creation request
      * @param sessionHints an optional bundle of app-specific arguments sent by
      *                     {@link MediaRouter2}, or null if none. The contents of this bundle
      *                     may affect the result of session creation.
@@ -300,8 +377,8 @@
      * @see RoutingSessionInfo.Builder#addSelectedRoute(String)
      * @see RoutingSessionInfo.Builder#setControlHints(Bundle)
      */
-    public abstract void onCreateSession(@NonNull String packageName, @NonNull String routeId,
-            long requestId, @Nullable Bundle sessionHints);
+    public abstract void onCreateSession(long requestId, @NonNull String packageName,
+            @NonNull String routeId, @Nullable Bundle sessionHints);
 
     /**
      * Called when the session should be released. A client of the session or system can request
@@ -313,44 +390,48 @@
      * Note: Calling {@link #notifySessionReleased(String)} will <em>NOT</em> trigger
      * this method to be called.
      *
+     * @param requestId the id of this request
      * @param sessionId id of the session being released.
      * @see #notifySessionReleased(String)
      * @see #getSessionInfo(String)
      */
-    public abstract void onReleaseSession(@NonNull String sessionId);
+    public abstract void onReleaseSession(long requestId, @NonNull String sessionId);
 
-    //TODO: make a way to reject the request
     /**
      * Called when a client requests selecting a route for the session.
      * After the route is selected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
      * to update session info.
      *
+     * @param requestId the id of this request
      * @param sessionId id of the session
      * @param routeId id of the route
      */
-    public abstract void onSelectRoute(@NonNull String sessionId, @NonNull String routeId);
+    public abstract void onSelectRoute(long requestId, @NonNull String sessionId,
+            @NonNull String routeId);
 
-    //TODO: make a way to reject the request
     /**
      * Called when a client requests deselecting a route from the session.
      * After the route is deselected, call {@link #notifySessionUpdated(RoutingSessionInfo)}
      * to update session info.
      *
+     * @param requestId the id of this request
      * @param sessionId id of the session
      * @param routeId id of the route
      */
-    public abstract void onDeselectRoute(@NonNull String sessionId, @NonNull String routeId);
+    public abstract void onDeselectRoute(long requestId, @NonNull String sessionId,
+            @NonNull String routeId);
 
-    //TODO: make a way to reject the request
     /**
      * Called when a client requests transferring a session to a route.
      * After the transfer is finished, call {@link #notifySessionUpdated(RoutingSessionInfo)}
      * to update session info.
      *
+     * @param requestId the id of this request
      * @param sessionId id of the session
      * @param routeId id of the route
      */
-    public abstract void onTransferToRoute(@NonNull String sessionId, @NonNull String routeId);
+    public abstract void onTransferToRoute(long requestId, @NonNull String sessionId,
+            @NonNull String routeId);
 
     /**
      * Called when the {@link RouteDiscoveryPreference discovery preference} has changed.
@@ -440,12 +521,12 @@
         }
 
         @Override
-        public void setRouteVolume(String routeId, int volume) {
+        public void setRouteVolume(String routeId, int volume, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetRouteVolume,
-                    MediaRoute2ProviderService.this, routeId, volume));
+                    MediaRoute2ProviderService.this, requestId, routeId, volume));
         }
 
         @Override
@@ -455,12 +536,12 @@
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onCreateSession,
-                    MediaRoute2ProviderService.this, packageName, routeId, requestId,
+                    MediaRoute2ProviderService.this, requestId, packageName, routeId,
                     requestCreateSession));
         }
 
         @Override
-        public void selectRoute(@NonNull String sessionId, String routeId) {
+        public void selectRoute(String sessionId, String routeId, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
@@ -469,11 +550,11 @@
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSelectRoute,
-                    MediaRoute2ProviderService.this, sessionId, routeId));
+                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
         }
 
         @Override
-        public void deselectRoute(@NonNull String sessionId, String routeId) {
+        public void deselectRoute(String sessionId, String routeId, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
@@ -482,11 +563,11 @@
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onDeselectRoute,
-                    MediaRoute2ProviderService.this, sessionId, routeId));
+                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
         }
 
         @Override
-        public void transferToRoute(@NonNull String sessionId, String routeId) {
+        public void transferToRoute(String sessionId, String routeId, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
@@ -495,20 +576,20 @@
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onTransferToRoute,
-                    MediaRoute2ProviderService.this, sessionId, routeId));
+                    MediaRoute2ProviderService.this, requestId, sessionId, routeId));
         }
 
         @Override
-        public void setSessionVolume(String sessionId, int volume) {
+        public void setSessionVolume(String sessionId, int volume, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onSetSessionVolume,
-                    MediaRoute2ProviderService.this, sessionId, volume));
+                    MediaRoute2ProviderService.this, requestId, sessionId, volume));
         }
 
         @Override
-        public void releaseSession(@NonNull String sessionId) {
+        public void releaseSession(String sessionId, long requestId) {
             if (!checkCallerisSystem()) {
                 return;
             }
@@ -517,7 +598,7 @@
                 return;
             }
             mHandler.sendMessage(obtainMessage(MediaRoute2ProviderService::onReleaseSession,
-                    MediaRoute2ProviderService.this, sessionId));
+                    MediaRoute2ProviderService.this, requestId, sessionId));
         }
     }
 }
diff --git a/media/java/android/media/MediaRouter2.java b/media/java/android/media/MediaRouter2.java
index 6281ccd..079fee8 100644
--- a/media/java/android/media/MediaRouter2.java
+++ b/media/java/android/media/MediaRouter2.java
@@ -21,6 +21,7 @@
 import android.annotation.CallbackExecutor;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
@@ -363,7 +364,7 @@
     /**
      * Transfers the current media to the given route.
      * If it's necessary a new {@link RoutingController} is created or it is handled within
-     * the current controller.
+     * the current routing controller.
      *
      * @param route the route you want to transfer the current media to. Pass {@code null} to
      *              stop routing of the current media.
@@ -393,8 +394,11 @@
             return;
         }
 
-        // TODO: Check the given route exists
         // TODO: Check thread-safety
+        if (!mRoutes.containsKey(route.getId())) {
+            notifyTransferFailed(route);
+            return;
+        }
         if (controller.getRoutingSessionInfo().getTransferableRoutes().contains(route.getId())) {
             controller.transferToRoute(route);
             return;
@@ -718,8 +722,7 @@
             RoutingController newController) {
         for (TransferCallbackRecord record: mTransferCallbackRecords) {
             record.mExecutor.execute(
-                    () -> record.mTransferCallback.onTransferred(oldController,
-                            newController));
+                    () -> record.mTransferCallback.onTransferred(oldController, newController));
         }
     }
 
@@ -814,7 +817,7 @@
          * @return An optional bundle of app-specific arguments to send to the provider,
          *         or null if none. The contents of this bundle may affect the result of
          *         controller creation.
-         * @see MediaRoute2ProviderService#onCreateSession(String, String, long, Bundle)
+         * @see MediaRoute2ProviderService#onCreateSession(long, String, String, Bundle)
          */
         @Nullable
         Bundle onGetControllerHints(@NonNull MediaRoute2Info route);
@@ -863,6 +866,20 @@
         }
 
         /**
+         * Gets the original session id set by
+         * {@link RoutingSessionInfo.Builder#Builder(String, String)}.
+         *
+         * @hide
+         */
+        @NonNull
+        @TestApi
+        public String getOriginalId() {
+            synchronized (mControllerLock) {
+                return mSessionInfo.getOriginalId();
+            }
+        }
+
+        /**
          * @return the control hints used to control routing session if available.
          */
         @Nullable
@@ -877,9 +894,11 @@
          */
         @NonNull
         public List<MediaRoute2Info> getSelectedRoutes() {
+            List<String> selectedRouteIds;
             synchronized (mControllerLock) {
-                return getRoutesWithIdsLocked(mSessionInfo.getSelectedRoutes());
+                selectedRouteIds = mSessionInfo.getSelectedRoutes();
             }
+            return getRoutesWithIds(selectedRouteIds);
         }
 
         /**
@@ -887,9 +906,11 @@
          */
         @NonNull
         public List<MediaRoute2Info> getSelectableRoutes() {
+            List<String> selectableRouteIds;
             synchronized (mControllerLock) {
-                return getRoutesWithIdsLocked(mSessionInfo.getSelectableRoutes());
+                selectableRouteIds = mSessionInfo.getSelectableRoutes();
             }
+            return getRoutesWithIds(selectableRouteIds);
         }
 
         /**
@@ -897,9 +918,11 @@
          */
         @NonNull
         public List<MediaRoute2Info> getDeselectableRoutes() {
+            List<String> deselectableRouteIds;
             synchronized (mControllerLock) {
-                return getRoutesWithIdsLocked(mSessionInfo.getDeselectableRoutes());
+                deselectableRouteIds = mSessionInfo.getDeselectableRoutes();
             }
+            return getRoutesWithIds(deselectableRouteIds);
         }
 
         /**
@@ -1203,20 +1226,12 @@
             }
         }
 
-        // TODO: This method uses two locks (mLock outside, sLock inside).
-        //       Check if there is any possiblity of deadlock.
-        private List<MediaRoute2Info> getRoutesWithIdsLocked(List<String> routeIds) {
-            List<MediaRoute2Info> routes = new ArrayList<>();
+        private List<MediaRoute2Info> getRoutesWithIds(List<String> routeIds) {
             synchronized (sRouterLock) {
-                // TODO: Maybe able to change using Collection.stream()?
-                for (String routeId : routeIds) {
-                    MediaRoute2Info route = mRoutes.get(routeId);
-                    if (route != null) {
-                        routes.add(route);
-                    }
-                }
+                return routeIds.stream().map(mRoutes::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
             }
-            return Collections.unmodifiableList(routes);
         }
     }
 
diff --git a/media/java/android/media/MediaRouter2Manager.java b/media/java/android/media/MediaRouter2Manager.java
index 8a08d14..ff2c863 100644
--- a/media/java/android/media/MediaRouter2Manager.java
+++ b/media/java/android/media/MediaRouter2Manager.java
@@ -337,7 +337,8 @@
         }
         if (client != null) {
             try {
-                mMediaRouterService.setRouteVolumeWithManager(client, route, volume);
+                int requestId = mNextRequestId.getAndIncrement();
+                mMediaRouterService.setRouteVolumeWithManager(client, route, volume, requestId);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to send control request.", ex);
             }
@@ -368,8 +369,9 @@
         }
         if (client != null) {
             try {
+                int requestId = mNextRequestId.getAndIncrement();
                 mMediaRouterService.setSessionVolumeWithManager(
-                        client, sessionInfo.getId(), volume);
+                        client, sessionInfo.getId(), volume, requestId);
             } catch (RemoteException ex) {
                 Log.e(TAG, "Unable to send control request.", ex);
             }
@@ -443,6 +445,12 @@
         }
     }
 
+    void notifyRequestFailed(int reason) {
+        for (CallbackRecord record : mCallbackRecords) {
+            record.mExecutor.execute(() -> record.mCallback.onRequestFailed(reason));
+        }
+    }
+
     void updatePreferredFeatures(String packageName, List<String> preferredFeatures) {
         List<String> prevFeatures = mPreferredFeaturesMap.put(packageName, preferredFeatures);
         if ((prevFeatures == null && preferredFeatures.size() == 0)
@@ -453,6 +461,10 @@
             record.mExecutor.execute(() -> record.mCallback
                     .onControlCategoriesChanged(packageName, preferredFeatures));
         }
+        for (CallbackRecord record : mCallbackRecords) {
+            record.mExecutor.execute(() -> record.mCallback
+                    .onPreferredFeaturesChanged(packageName, preferredFeatures));
+        }
     }
 
     /**
@@ -589,7 +601,9 @@
             }
             if (client != null) {
                 try {
-                    mMediaRouterService.selectRouteWithManager(mClient, getSessionId(), route);
+                    int requestId = mNextRequestId.getAndIncrement();
+                    mMediaRouterService.selectRouteWithManager(
+                            mClient, getSessionId(), route, requestId);
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to select route for session.", ex);
                 }
@@ -631,7 +645,9 @@
             }
             if (client != null) {
                 try {
-                    mMediaRouterService.deselectRouteWithManager(mClient, getSessionId(), route);
+                    int requestId = mNextRequestId.getAndIncrement();
+                    mMediaRouterService.deselectRouteWithManager(
+                            mClient, getSessionId(), route, requestId);
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to remove route from session.", ex);
                 }
@@ -674,7 +690,9 @@
             }
             if (client != null) {
                 try {
-                    mMediaRouterService.transferToRouteWithManager(mClient, getSessionId(), route);
+                    int requestId = mNextRequestId.getAndIncrement();
+                    mMediaRouterService.transferToRouteWithManager(
+                            mClient, getSessionId(), route, requestId);
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to transfer to route for session.", ex);
                 }
@@ -692,7 +710,9 @@
             }
             if (client != null) {
                 try {
-                    mMediaRouterService.releaseSessionWithManager(mClient, getSessionId());
+                    int requestId = mNextRequestId.getAndIncrement();
+                    mMediaRouterService.releaseSessionWithManager(
+                            mClient, getSessionId(), requestId);
                 } catch (RemoteException ex) {
                     Log.e(TAG, "Unable to notify of controller release", ex);
                 }
@@ -760,6 +780,7 @@
          */
         public void onSessionsUpdated() {}
 
+        //TODO: remove this
         /**
          * Called when the preferred route features of an app is changed.
          *
@@ -768,6 +789,27 @@
          */
         public void onControlCategoriesChanged(@NonNull String packageName,
                 @NonNull List<String> preferredFeatures) {}
+
+        /**
+         * Called when the preferred route features of an app is changed.
+         *
+         * @param packageName the package name of the application
+         * @param preferredFeatures the list of preferred route features set by an application.
+         */
+        public void onPreferredFeaturesChanged(@NonNull String packageName,
+                @NonNull List<String> preferredFeatures) {}
+
+        /**
+         * Called when a previous request has failed.
+         *
+         * @param reason the reason that the request has failed. Can be one of followings:
+         *               {@link MediaRoute2ProviderService#REASON_UNKNOWN_ERROR},
+         *               {@link MediaRoute2ProviderService#REASON_REJECTED},
+         *               {@link MediaRoute2ProviderService#REASON_NETWORK_ERROR},
+         *               {@link MediaRoute2ProviderService#REASON_ROUTE_NOT_AVAILABLE},
+         *               {@link MediaRoute2ProviderService#REASON_INVALID_COMMAND},
+         */
+        public void onRequestFailed(int reason) {}
     }
 
     final class CallbackRecord {
@@ -811,6 +853,13 @@
         }
 
         @Override
+        public void notifyRequestFailed(int requestId, int reason) {
+            // Note: requestId is not used.
+            mHandler.sendMessage(obtainMessage(MediaRouter2Manager::notifyRequestFailed,
+                    MediaRouter2Manager.this, reason));
+        }
+
+        @Override
         public void notifyPreferredFeaturesChanged(String packageName, List<String> features) {
             mHandler.sendMessage(obtainMessage(MediaRouter2Manager::updatePreferredFeatures,
                     MediaRouter2Manager.this, packageName, features));
diff --git a/media/java/android/media/RingtoneManager.java b/media/java/android/media/RingtoneManager.java
index d058243..8deb0c4 100644
--- a/media/java/android/media/RingtoneManager.java
+++ b/media/java/android/media/RingtoneManager.java
@@ -512,15 +512,19 @@
      * @return The position of the {@link Uri}, or -1 if it cannot be found.
      */
     public int getRingtonePosition(Uri ringtoneUri) {
-        if (ringtoneUri == null) return -1;
-        final long ringtoneId = ContentUris.parseId(ringtoneUri);
-        
-        final Cursor cursor = getCursor();
-        cursor.moveToPosition(-1);
-        while (cursor.moveToNext()) {
-            if (ringtoneId == cursor.getLong(ID_COLUMN_INDEX)) {
-                return cursor.getPosition();
+        try {
+            if (ringtoneUri == null) return -1;
+            final long ringtoneId = ContentUris.parseId(ringtoneUri);
+
+            final Cursor cursor = getCursor();
+            cursor.moveToPosition(-1);
+            while (cursor.moveToNext()) {
+                if (ringtoneId == cursor.getLong(ID_COLUMN_INDEX)) {
+                    return cursor.getPosition();
+                }
             }
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "NumberFormatException while getting ringtone position, returning -1", e);
         }
         return -1;
     }
diff --git a/media/java/android/media/audiofx/AudioEffect.java b/media/java/android/media/audiofx/AudioEffect.java
index 6157ef4..2587350 100644
--- a/media/java/android/media/audiofx/AudioEffect.java
+++ b/media/java/android/media/audiofx/AudioEffect.java
@@ -25,7 +25,7 @@
 import android.annotation.TestApi;
 import android.app.ActivityThread;
 import android.compat.annotation.UnsupportedAppUsage;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceInfo;
 import android.media.AudioSystem;
 import android.os.Build;
@@ -476,12 +476,12 @@
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.MODIFY_DEFAULT_AUDIO_EFFECTS)
-    public AudioEffect(@NonNull UUID uuid, @NonNull AudioDevice device) {
+    public AudioEffect(@NonNull UUID uuid, @NonNull AudioDeviceAttributes device) {
         this(EFFECT_TYPE_NULL, Objects.requireNonNull(uuid), 0, -2, Objects.requireNonNull(device));
     }
 
     private AudioEffect(UUID type, UUID uuid, int priority,
-            int audioSession, @Nullable AudioDevice device)
+            int audioSession, @Nullable AudioDeviceAttributes device)
             throws IllegalArgumentException, UnsupportedOperationException,
             RuntimeException {
         int[] id = new int[1];
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 62c7e51..b579144 100755
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -111,37 +111,32 @@
     public @interface PriorityHintUseCaseType {}
 
     /**
-     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
-     * Background.
-     * TODO Link: Tuner#Tuner(Context, string, int).
+     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+     * int)}: Background. TODO Link: Tuner#Tuner(Context, string, int).
      */
     public static final int PRIORITY_HINT_USE_CASE_TYPE_BACKGROUND = 100;
 
     /**
-     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
-     * Scan.
-     * TODO Link: Tuner#Tuner(Context, string, int).
+     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+     * int)}: Scan. TODO Link: Tuner#Tuner(Context, string, int).
      */
     public static final int PRIORITY_HINT_USE_CASE_TYPE_SCAN = 200;
 
     /**
-     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
-     * Playback.
-     * TODO Link: Tuner#Tuner(Context, string, int).
+     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+     * int)}: Playback. TODO Link: Tuner#Tuner(Context, string, int).
      */
     public static final int PRIORITY_HINT_USE_CASE_TYPE_PLAYBACK = 300;
 
     /**
-     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
-     * Live.
-     * TODO Link: Tuner#Tuner(Context, string, int).
+     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+     * int)}: Live. TODO Link: Tuner#Tuner(Context, string, int).
      */
     public static final int PRIORITY_HINT_USE_CASE_TYPE_LIVE = 400;
 
     /**
-     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(int, String , int)}:
-     * Record.
-     * TODO Link: Tuner#Tuner(Context, string, int).
+     * Use case of priority hint for {@link android.media.MediaCas#MediaCas(Context, int, String,
+     * int)}: Record. TODO Link: Tuner#Tuner(Context, string, int).
      */
     public static final int PRIORITY_HINT_USE_CASE_TYPE_RECORD = 500;
 
diff --git a/media/java/android/media/tv/tuner/DemuxCapabilities.java b/media/java/android/media/tv/tuner/DemuxCapabilities.java
index 364516c..0f5bf08 100644
--- a/media/java/android/media/tv/tuner/DemuxCapabilities.java
+++ b/media/java/android/media/tv/tuner/DemuxCapabilities.java
@@ -18,7 +18,7 @@
 
 import android.annotation.BytesLong;
 import android.annotation.IntDef;
-import android.annotation.Nullable;
+import android.annotation.NonNull;
 import android.annotation.Size;
 import android.annotation.SystemApi;
 import android.media.tv.tuner.filter.Filter;
@@ -159,7 +159,7 @@
      * {@link FilterConfiguration}.
      * <p>The ith element represents the filter's capability as the source for the ith type.
      */
-    @Nullable
+    @NonNull
     @Size(5)
     public int[] getLinkCapabilities() {
         return mLinkCaps;
diff --git a/media/java/android/media/tv/tuner/Descrambler.java b/media/java/android/media/tv/tuner/Descrambler.java
index f46d3ce..40add56 100644
--- a/media/java/android/media/tv/tuner/Descrambler.java
+++ b/media/java/android/media/tv/tuner/Descrambler.java
@@ -17,12 +17,15 @@
 package android.media.tv.tuner;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.media.tv.tuner.TunerConstants.Result;
 import android.media.tv.tuner.filter.Filter;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
 
 /**
  * This class is used to interact with descramblers.
@@ -75,6 +78,7 @@
      * @param filter an optional filter instance to identify upper stream.
      * @return result status of the operation.
      */
+    @Result
     public int addPid(@PidType int pidType, int pid, @Nullable Filter filter) {
         return nativeAddPid(pidType, pid, filter);
     }
@@ -89,6 +93,7 @@
      * @param filter an optional filter instance to identify upper stream.
      * @return result status of the operation.
      */
+    @Result
     public int removePid(@PidType int pidType, int pid, @Nullable Filter filter) {
         return nativeRemovePid(pidType, pid, filter);
     }
@@ -102,7 +107,9 @@
      * @param keyToken the token to be used to link the key slot.
      * @return result status of the operation.
      */
-    public int setKeyToken(@Nullable byte[] keyToken) {
+    @Result
+    public int setKeyToken(@NonNull byte[] keyToken) {
+        Objects.requireNonNull(keyToken, "key token must not be null");
         return nativeSetKeyToken(keyToken);
     }
 
diff --git a/media/java/android/media/tv/tuner/Tuner.java b/media/java/android/media/tv/tuner/Tuner.java
index bd00201..012b8d6 100644
--- a/media/java/android/media/tv/tuner/Tuner.java
+++ b/media/java/android/media/tv/tuner/Tuner.java
@@ -38,6 +38,7 @@
 import android.media.tv.tuner.frontend.FrontendInfo;
 import android.media.tv.tuner.frontend.FrontendSettings;
 import android.media.tv.tuner.frontend.FrontendStatus;
+import android.media.tv.tuner.frontend.FrontendStatus.FrontendStatusType;
 import android.media.tv.tuner.frontend.OnTuneEventListener;
 import android.media.tv.tuner.frontend.ScanCallback;
 import android.os.Handler;
@@ -45,6 +46,7 @@
 import android.os.Message;
 
 import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.Executor;
 
 /**
@@ -88,6 +90,10 @@
     private ScanCallback mScanCallback;
     @Nullable
     private Executor mScanCallbackExecutor;
+    @Nullable
+    private OnResourceLostListener mOnResourceLostListener;
+    @Nullable
+    private Executor mOnResourceLostListenerExecutor;
 
     /**
      * Constructs a Tuner instance.
@@ -97,14 +103,37 @@
      * @param useCase the use case of this Tuner instance.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
-    public Tuner(@NonNull Context context, @NonNull String tvInputSessionId,
-            @TvInputService.PriorityHintUseCaseType int useCase,
-            @Nullable OnResourceLostListener listener) {
+    public Tuner(@NonNull Context context, @Nullable String tvInputSessionId,
+            @TvInputService.PriorityHintUseCaseType int useCase) {
         nativeSetup();
         mContext = context;
     }
 
     /**
+     * Sets the listener for resource lost.
+     *
+     * @param executor the executor on which the listener should be invoked.
+     * @param listener the listener that will be run.
+     */
+    @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+    public void setResourceLostListener(@NonNull @CallbackExecutor Executor executor,
+            @NonNull OnResourceLostListener listener) {
+        Objects.requireNonNull(executor, "OnResourceLostListener must not be null");
+        Objects.requireNonNull(listener, "executor must not be null");
+        mOnResourceLostListener = listener;
+        mOnResourceLostListenerExecutor = executor;
+    }
+
+    /**
+     * Removes the listener for resource lost.
+     */
+    @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
+    public void clearResourceLostListener() {
+        mOnResourceLostListener = null;
+        mOnResourceLostListenerExecutor = null;
+    }
+
+    /**
      * Shares the frontend resource with another Tuner instance
      *
      * @param tuner the Tuner instance to share frontend resource with.
@@ -387,7 +416,7 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Result
-    public int setLna(boolean enable) {
+    public int setLnaEnabled(boolean enable) {
         TunerUtils.checkTunerPermission(mContext);
         return nativeSetLna(enable);
     }
@@ -398,10 +427,10 @@
      * <p>This retrieve the statuses of the frontend for given status types.
      *
      * @param statusTypes an array of status types which the caller requests.
-     * @return statuses which response the caller's requests.
+     * @return statuses which response the caller's requests. {@code null} if the operation failed.
      */
     @Nullable
-    public FrontendStatus getFrontendStatus(@NonNull int[] statusTypes) {
+    public FrontendStatus getFrontendStatus(@NonNull @FrontendStatusType int[] statusTypes) {
         return nativeGetFrontendStatus(statusTypes);
     }
 
@@ -482,6 +511,10 @@
 
     /**
      * Gets Demux capabilities.
+     *
+     * @param context the context of the caller.
+     * @return A {@link DemuxCapabilities} instance that represents the demux capabilities.
+     *         {@code null} if the operation failed.
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Nullable
@@ -637,13 +670,15 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Nullable
-    public Lnb openLnb(@CallbackExecutor @Nullable Executor executor, @Nullable LnbCallback cb) {
+    public Lnb openLnb(@CallbackExecutor @NonNull Executor executor, @NonNull LnbCallback cb) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(cb, "LnbCallback must not be null");
         TunerUtils.checkTunerPermission(mContext);
         return openLnbByName(null, executor, cb);
     }
 
     /**
-     * Opens an LNB (low-noise block downconverter) object.
+     * Opens an LNB (low-noise block downconverter) object specified by the give name.
      *
      * @param name the LNB name.
      * @param executor the executor on which callback will be invoked. The default event handler
@@ -653,8 +688,10 @@
      */
     @RequiresPermission(android.Manifest.permission.ACCESS_TV_TUNER)
     @Nullable
-    public Lnb openLnbByName(@Nullable String name, @CallbackExecutor @Nullable Executor executor,
+    public Lnb openLnbByName(@NonNull String name, @CallbackExecutor @NonNull Executor executor,
             @NonNull LnbCallback cb) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(cb, "LnbCallback must not be null");
         TunerUtils.checkTunerPermission(mContext);
         // TODO: use resource manager to get LNB ID.
         return new Lnb(0);
@@ -718,8 +755,10 @@
     @Nullable
     public DvrRecorder openDvrRecorder(
             @BytesLong long bufferSize,
-            @CallbackExecutor @Nullable Executor executor,
-            @Nullable OnRecordStatusChangedListener l) {
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OnRecordStatusChangedListener l) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(l, "OnRecordStatusChangedListener must not be null");
         TunerUtils.checkTunerPermission(mContext);
         DvrRecorder dvr = nativeOpenDvrRecorder(bufferSize);
         return dvr;
@@ -739,8 +778,10 @@
     @Nullable
     public DvrPlayback openDvrPlayback(
             @BytesLong long bufferSize,
-            @CallbackExecutor @Nullable Executor executor,
-            @Nullable OnPlaybackStatusChangedListener l) {
+            @CallbackExecutor @NonNull Executor executor,
+            @NonNull OnPlaybackStatusChangedListener l) {
+        Objects.requireNonNull(executor, "executor must not be null");
+        Objects.requireNonNull(l, "OnPlaybackStatusChangedListener must not be null");
         TunerUtils.checkTunerPermission(mContext);
         DvrPlayback dvr = nativeOpenDvrPlayback(bufferSize);
         return dvr;
diff --git a/media/java/android/media/tv/tuner/TunerUtils.java b/media/java/android/media/tv/tuner/TunerUtils.java
index 5ecb8f0..2258ee5 100644
--- a/media/java/android/media/tv/tuner/TunerUtils.java
+++ b/media/java/android/media/tv/tuner/TunerUtils.java
@@ -16,6 +16,7 @@
 
 package android.media.tv.tuner;
 
+import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.hardware.tv.tuner.V1_0.Constants;
@@ -165,5 +166,33 @@
                 "Invalid filter types. Main type=" + mainType + ", subtype=" + subtype);
     }
 
+    /**
+     * Gets an throwable instance for the corresponding result.
+     */
+    @Nullable
+    public static void throwExceptionForResult(
+            @TunerConstants.Result int r, @Nullable String msg) {
+        if (msg == null) {
+            msg = "";
+        }
+        switch (r) {
+            case TunerConstants.RESULT_INVALID_ARGUMENT:
+                throw new IllegalArgumentException(msg);
+            case TunerConstants.RESULT_INVALID_STATE:
+                throw new IllegalStateException(msg);
+            case TunerConstants.RESULT_NOT_INITIALIZED:
+                throw new IllegalStateException("Invalid state: not initialized. " + msg);
+            case TunerConstants.RESULT_OUT_OF_MEMORY:
+                throw new OutOfMemoryError(msg);
+            case TunerConstants.RESULT_UNAVAILABLE:
+                throw new IllegalStateException("Invalid state: resource unavailable. " + msg);
+            case TunerConstants.RESULT_UNKNOWN_ERROR:
+                throw new RuntimeException("Unknown error" + msg);
+            default:
+                break;
+        }
+        throw new RuntimeException("Unexpected result " + r + ".  " + msg);
+    }
+
     private TunerUtils() {}
 }
diff --git a/media/java/android/media/tv/tuner/filter/TimeFilter.java b/media/java/android/media/tv/tuner/filter/TimeFilter.java
index a926d59..371ccc4 100644
--- a/media/java/android/media/tv/tuner/filter/TimeFilter.java
+++ b/media/java/android/media/tv/tuner/filter/TimeFilter.java
@@ -17,7 +17,9 @@
 package android.media.tv.tuner.filter;
 
 import android.annotation.SystemApi;
+import android.media.tv.tuner.TunerConstants;
 import android.media.tv.tuner.TunerConstants.Result;
+import android.media.tv.tuner.TunerUtils;
 
 /**
  *  A timer filter is used to filter data based on timestamps.
@@ -51,6 +53,8 @@
     private native Long nativeGetSourceTime();
     private native int nativeClose();
 
+    private long mNativeContext;
+
     private boolean mEnable = false;
 
     // Called by JNI code
@@ -139,6 +143,9 @@
      */
     @Override
     public void close() {
-        nativeClose();
+        int res = nativeClose();
+        if (res != TunerConstants.RESULT_SUCCESS) {
+            TunerUtils.throwExceptionForResult(res, "Failed to close time filter.");
+        }
     }
 }
diff --git a/media/java/android/media/tv/tuner/frontend/ScanCallback.java b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
index 8105c74..63bc248 100644
--- a/media/java/android/media/tv/tuner/frontend/ScanCallback.java
+++ b/media/java/android/media/tv/tuner/frontend/ScanCallback.java
@@ -53,7 +53,7 @@
     void onInputStreamIds(@NonNull int[] inputStreamIds);
 
     /** Locked signal standard for DVBS. */
-    void onDvbsStandard(@DvbsFrontendSettings.Standard int dvbsStandandard);
+    void onDvbsStandard(@DvbsFrontendSettings.Standard int dvbsStandard);
 
     /** Locked signal standard. for DVBT */
     void onDvbtStandard(@DvbtFrontendSettings.Standard int dvbtStandard);
diff --git a/media/jni/Android.bp b/media/jni/Android.bp
index c17b1b7..47ec7e6 100644
--- a/media/jni/Android.bp
+++ b/media/jni/Android.bp
@@ -160,8 +160,3 @@
         "-Wunreachable-code",
     ],
 }
-
-subdirs = [
-    "audioeffect",
-    "soundpool",
-]
diff --git a/media/jni/android_media_tv_Tuner.cpp b/media/jni/android_media_tv_Tuner.cpp
index f4d2d03..4f31f6c 100644
--- a/media/jni/android_media_tv_Tuner.cpp
+++ b/media/jni/android_media_tv_Tuner.cpp
@@ -118,10 +118,12 @@
 struct fields_t {
     jfieldID tunerContext;
     jfieldID filterContext;
+    jfieldID timeFilterContext;
     jfieldID descramblerContext;
     jfieldID dvrContext;
     jmethodID frontendInitID;
     jmethodID filterInitID;
+    jmethodID timeFilterInitID;
     jmethodID dvrInitID;
     jmethodID onFrontendEventID;
     jmethodID onFilterStatusID;
@@ -237,6 +239,25 @@
     return mFilterSp;
 }
 
+/////////////// TimeFilter ///////////////////////
+
+TimeFilter::TimeFilter(sp<ITimeFilter> sp, jobject obj) : mTimeFilterSp(sp) {
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    mTimeFilterObj = env->NewWeakGlobalRef(obj);
+}
+
+TimeFilter::~TimeFilter() {
+    ALOGD("~TimeFilter");
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+
+    env->DeleteWeakGlobalRef(mTimeFilterObj);
+    mTimeFilterObj = NULL;
+}
+
+sp<ITimeFilter> TimeFilter::getITimeFilter() {
+    return mTimeFilterSp;
+}
+
 /////////////// FrontendCallback ///////////////////////
 
 FrontendCallback::FrontendCallback(jweak tunerObj, FrontendId id) : mObject(tunerObj), mId(id) {}
@@ -841,6 +862,36 @@
     return filterObj;
 }
 
+jobject JTuner::openTimeFilter() {
+    if (mDemux == NULL) {
+        if (!openDemux()) {
+            return NULL;
+        }
+    }
+    sp<ITimeFilter> iTimeFilterSp;
+    Result res;
+    mDemux->openTimeFilter(
+            [&](Result r, const sp<ITimeFilter>& filter) {
+                iTimeFilterSp = filter;
+                res = r;
+            });
+
+    if (res != Result::SUCCESS || iTimeFilterSp == NULL) {
+        return NULL;
+    }
+
+    JNIEnv *env = AndroidRuntime::getJNIEnv();
+    jobject timeFilterObj =
+            env->NewObject(
+                    env->FindClass("android/media/tv/tuner/filter/TimeFilter"),
+                    gFields.timeFilterInitID);
+    sp<TimeFilter> timeFilterSp = new TimeFilter(iTimeFilterSp, timeFilterObj);
+    timeFilterSp->incStrong(timeFilterObj);
+    env->SetLongField(timeFilterObj, gFields.timeFilterContext, (jlong)timeFilterSp.get());
+
+    return timeFilterObj;
+}
+
 jobject JTuner::openDvr(DvrType type, int bufferSize) {
     ALOGD("JTuner::openDvr");
     if (mDemux == NULL) {
@@ -1420,6 +1471,10 @@
     gFields.onFilterStatusID =
             env->GetMethodID(filterClazz, "onFilterStatus", "(I)V");
 
+    jclass timeFilterClazz = env->FindClass("android/media/tv/tuner/filter/TimeFilter");
+    gFields.timeFilterContext = env->GetFieldID(timeFilterClazz, "mNativeContext", "J");
+    gFields.timeFilterInitID = env->GetMethodID(timeFilterClazz, "<init>", "()V");
+
     jclass descramblerClazz = env->FindClass("android/media/tv/tuner/Descrambler");
     gFields.descramblerContext = env->GetFieldID(descramblerClazz, "mNativeContext", "J");
     gFields.descramblerInitID =
@@ -1515,18 +1570,35 @@
 static jobject android_media_tv_Tuner_open_filter(
         JNIEnv *env, jobject thiz, jint type, jint subType, jlong bufferSize) {
     sp<JTuner> tuner = getTuner(env, thiz);
+    DemuxFilterMainType mainType = static_cast<DemuxFilterMainType>(type);
     DemuxFilterType filterType {
-        .mainType = static_cast<DemuxFilterMainType>(type),
+        .mainType = mainType,
     };
 
-    // TODO: other sub types
-    filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+    switch(mainType) {
+        case DemuxFilterMainType::TS:
+            filterType.subType.tsFilterType(static_cast<DemuxTsFilterType>(subType));
+            break;
+        case DemuxFilterMainType::MMTP:
+            filterType.subType.mmtpFilterType(static_cast<DemuxMmtpFilterType>(subType));
+            break;
+        case DemuxFilterMainType::IP:
+            filterType.subType.ipFilterType(static_cast<DemuxIpFilterType>(subType));
+            break;
+        case DemuxFilterMainType::TLV:
+            filterType.subType.tlvFilterType(static_cast<DemuxTlvFilterType>(subType));
+            break;
+        case DemuxFilterMainType::ALP:
+            filterType.subType.alpFilterType(static_cast<DemuxAlpFilterType>(subType));
+            break;
+    }
 
     return tuner->openFilter(filterType, bufferSize);
 }
 
-static jobject android_media_tv_Tuner_open_time_filter(JNIEnv, jobject) {
-    return NULL;
+static jobject android_media_tv_Tuner_open_time_filter(JNIEnv *env, jobject thiz) {
+    sp<JTuner> tuner = getTuner(env, thiz);
+    return tuner->openTimeFilter();
 }
 
 static DemuxFilterSectionBits getFilterSectionBits(JNIEnv *env, const jobject& settings) {
@@ -1987,26 +2059,98 @@
     return 0;
 }
 
-// TODO: implement TimeFilter functions
+static sp<TimeFilter> getTimeFilter(JNIEnv *env, jobject filter) {
+    return (TimeFilter *)env->GetLongField(filter, gFields.timeFilterContext);
+}
+
 static int android_media_tv_Tuner_time_filter_set_timestamp(
-        JNIEnv, jobject, jlong) {
-    return 0;
+        JNIEnv *env, jobject filter, jlong timestamp) {
+    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed set timestamp: time filter not found");
+        return (int) Result::INVALID_STATE;
+    }
+    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
+    Result r = iFilterSp->setTimeStamp(static_cast<uint64_t>(timestamp));
+    return (int) r;
 }
 
-static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv, jobject) {
-    return 0;
+static int android_media_tv_Tuner_time_filter_clear_timestamp(JNIEnv *env, jobject filter) {
+    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed clear timestamp: time filter not found");
+        return (int) Result::INVALID_STATE;
+    }
+    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
+    Result r = iFilterSp->clearTimeStamp();
+    return (int) r;
 }
 
-static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv, jobject) {
-    return NULL;
+static jobject android_media_tv_Tuner_time_filter_get_timestamp(JNIEnv *env, jobject filter) {
+    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed get timestamp: time filter not found");
+        return NULL;
+    }
+
+    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
+    Result res;
+    uint64_t timestamp;
+    iFilterSp->getTimeStamp(
+            [&](Result r, uint64_t t) {
+                res = r;
+                timestamp = t;
+            });
+    if (res != Result::SUCCESS) {
+        return NULL;
+    }
+
+    jclass longClazz = env->FindClass("java/lang/Long");
+    jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
+
+    jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
+    return longObj;
 }
 
-static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv, jobject) {
-    return NULL;
+static jobject android_media_tv_Tuner_time_filter_get_source_time(JNIEnv *env, jobject filter) {
+    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed get source time: time filter not found");
+        return NULL;
+    }
+
+    sp<ITimeFilter> iFilterSp = filterSp->getITimeFilter();
+    Result res;
+    uint64_t timestamp;
+    iFilterSp->getSourceTime(
+            [&](Result r, uint64_t t) {
+                res = r;
+                timestamp = t;
+            });
+    if (res != Result::SUCCESS) {
+        return NULL;
+    }
+
+    jclass longClazz = env->FindClass("java/lang/Long");
+    jmethodID longInit = env->GetMethodID(longClazz, "<init>", "(J)V");
+
+    jobject longObj = env->NewObject(longClazz, longInit, static_cast<jlong>(timestamp));
+    return longObj;
 }
 
-static int android_media_tv_Tuner_time_filter_close(JNIEnv, jobject) {
-    return 0;
+static int android_media_tv_Tuner_time_filter_close(JNIEnv *env, jobject filter) {
+    sp<TimeFilter> filterSp = getTimeFilter(env, filter);
+    if (filterSp == NULL) {
+        ALOGD("Failed close time filter: time filter not found");
+        return (int) Result::INVALID_STATE;
+    }
+
+    Result r = filterSp->getITimeFilter()->close();
+    if (r == Result::SUCCESS) {
+        filterSp->decStrong(filter);
+        env->SetLongField(filter, gFields.timeFilterContext, 0);
+    }
+    return (int) r;
 }
 
 static jobject android_media_tv_Tuner_open_descrambler(JNIEnv *env, jobject thiz) {
diff --git a/media/jni/android_media_tv_Tuner.h b/media/jni/android_media_tv_Tuner.h
index d899bbd..c5590b9 100644
--- a/media/jni/android_media_tv_Tuner.h
+++ b/media/jni/android_media_tv_Tuner.h
@@ -54,6 +54,7 @@
 using ::android::hardware::tv::tuner::V1_0::IFrontendCallback;
 using ::android::hardware::tv::tuner::V1_0::ILnb;
 using ::android::hardware::tv::tuner::V1_0::ILnbCallback;
+using ::android::hardware::tv::tuner::V1_0::ITimeFilter;
 using ::android::hardware::tv::tuner::V1_0::ITuner;
 using ::android::hardware::tv::tuner::V1_0::LnbEventType;
 using ::android::hardware::tv::tuner::V1_0::LnbId;
@@ -127,6 +128,14 @@
     jweak mFilterObj;
 };
 
+struct TimeFilter : public RefBase {
+    TimeFilter(sp<ITimeFilter> sp, jweak obj);
+    ~TimeFilter();
+    sp<ITimeFilter> getITimeFilter();
+    sp<ITimeFilter> mTimeFilterSp;
+    jweak mTimeFilterObj;
+};
+
 struct JTuner : public RefBase {
     JTuner(JNIEnv *env, jobject thiz);
     sp<ITuner> getTunerService();
@@ -142,6 +151,7 @@
     jobject getLnbIds();
     jobject openLnbById(int id);
     jobject openFilter(DemuxFilterType type, int bufferSize);
+    jobject openTimeFilter();
     jobject openDescrambler();
     jobject openDvr(DvrType type, int bufferSize);
 
diff --git a/media/native/Android.bp b/media/native/Android.bp
deleted file mode 100644
index b44c296..0000000
--- a/media/native/Android.bp
+++ /dev/null
@@ -1 +0,0 @@
-subdirs = ["*"]
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
index e80562b..bcff6a1 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/MediaRouter2ManagerTest.java
@@ -19,6 +19,8 @@
 import static android.media.MediaRoute2Info.FEATURE_LIVE_AUDIO;
 import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_FIXED;
 import static android.media.MediaRoute2Info.PLAYBACK_VOLUME_VARIABLE;
+import static android.media.MediaRoute2ProviderService.REASON_REJECTED;
+import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
 
 import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.FEATURE_SAMPLE;
 import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.FEATURE_SPECIAL;
@@ -32,6 +34,7 @@
 import static com.android.mediaroutertest.SampleMediaRoute2ProviderService.VOLUME_MAX;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -55,7 +58,6 @@
 import org.junit.runner.RunWith;
 
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -69,6 +71,7 @@
 @SmallTest
 public class MediaRouter2ManagerTest {
     private static final String TAG = "MediaRouter2ManagerTest";
+    private static final int WAIT_TIME_MS = 2000;
     private static final int TIMEOUT_MS = 5000;
 
     private Context mContext;
@@ -111,6 +114,11 @@
         releaseAllSessions();
         // unregister callbacks
         clearCallbacks();
+
+        SampleMediaRoute2ProviderService instance = SampleMediaRoute2ProviderService.getInstance();
+        if (instance != null) {
+            instance.setProxy(null);
+        }
     }
 
     @Test
@@ -296,7 +304,7 @@
         String selectedSystemRouteId =
                 MediaRouter2Utils.getOriginalId(
                 mManager.getActiveSessions().get(0).getSelectedRoutes().get(0));
-        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(Collections.emptyList());
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
         MediaRoute2Info volRoute = routes.get(selectedSystemRouteId);
         assertNotNull(volRoute);
 
@@ -398,6 +406,53 @@
         }
     }
 
+    /**
+     * Tests that {@link android.media.MediaRoute2ProviderService#notifyRequestFailed(long, int)}
+     * should invoke the callback only when the right requestId is used.
+     */
+    @Test
+    public void testOnRequestFailedCalledForProperRequestId() throws Exception {
+        Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
+        MediaRoute2Info volRoute = routes.get(ROUTE_ID_VARIABLE_VOLUME);
+
+        SampleMediaRoute2ProviderService instance = SampleMediaRoute2ProviderService.getInstance();
+        assertNotNull(instance);
+
+        final List<Long> requestIds = new ArrayList<>();
+        final CountDownLatch onSetRouteVolumeLatch = new CountDownLatch(1);
+        instance.setProxy(new SampleMediaRoute2ProviderService.Proxy() {
+            @Override
+            public void onSetRouteVolume(String routeId, int volume, long requestId) {
+                requestIds.add(requestId);
+                onSetRouteVolumeLatch.countDown();
+            }
+        });
+
+        addManagerCallback(new MediaRouter2Manager.Callback() {});
+        mManager.setRouteVolume(volRoute, 0);
+        assertTrue(onSetRouteVolumeLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+        assertFalse(requestIds.isEmpty());
+
+        final int failureReason = REASON_REJECTED;
+        final CountDownLatch onRequestFailedLatch = new CountDownLatch(1);
+        addManagerCallback(new MediaRouter2Manager.Callback() {
+            @Override
+            public void onRequestFailed(int reason) {
+                if (reason == failureReason) {
+                    onRequestFailedLatch.countDown();
+                }
+            }
+        });
+
+        final long invalidRequestId = REQUEST_ID_NONE;
+        instance.notifyRequestFailed(invalidRequestId, failureReason);
+        assertFalse(onRequestFailedLatch.await(WAIT_TIME_MS, TimeUnit.MILLISECONDS));
+
+        final long validRequestId = requestIds.get(0);
+        instance.notifyRequestFailed(validRequestId, failureReason);
+        assertTrue(onRequestFailedLatch.await(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+    }
+
     @Test
     public void testVolumeHandling() throws Exception {
         Map<String, MediaRoute2Info> routes = waitAndGetRoutesWithManager(FEATURES_ALL);
@@ -429,10 +484,11 @@
             }
 
             @Override
-            public void onControlCategoriesChanged(String packageName,
+            public void onPreferredFeaturesChanged(String packageName,
                     List<String> preferredFeatures) {
                 if (TextUtils.equals(mPackageName, packageName)
-                        && preferredFeatures.equals(routeFeatures)) {
+                        && preferredFeatures.size() == routeFeatures.size()
+                        && preferredFeatures.containsAll(routeFeatures)) {
                     featuresLatch.countDown();
                 }
             }
diff --git a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
index 3faefdb..9071c85 100644
--- a/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
+++ b/media/tests/MediaRouter/src/com/android/mediaroutertest/SampleMediaRoute2ProviderService.java
@@ -75,6 +75,7 @@
 
     @GuardedBy("sLock")
     private static SampleMediaRoute2ProviderService sInstance;
+    private Proxy mProxy;
 
     private void initializeRoutes() {
         MediaRoute2Info route1 = new MediaRoute2Info.Builder(ROUTE_ID1, ROUTE_NAME1)
@@ -179,7 +180,13 @@
     }
 
     @Override
-    public void onSetRouteVolume(String routeId, int volume) {
+    public void onSetRouteVolume(long requestId, String routeId, int volume) {
+        Proxy proxy = mProxy;
+        if (proxy != null) {
+            proxy.onSetRouteVolume(routeId, volume, requestId);
+            return;
+        }
+
         MediaRoute2Info route = mRoutes.get(routeId);
         if (route == null) {
             return;
@@ -192,7 +199,7 @@
     }
 
     @Override
-    public void onSetSessionVolume(String sessionId, int volume) {
+    public void onSetSessionVolume(long requestId, String sessionId, int volume) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         if (sessionInfo == null) {
             return;
@@ -205,7 +212,7 @@
     }
 
     @Override
-    public void onCreateSession(String packageName, String routeId, long requestId,
+    public void onCreateSession(long requestId, String packageName, String routeId,
             @Nullable Bundle sessionHints) {
         MediaRoute2Info route = mRoutes.get(routeId);
         if (route == null || TextUtils.equals(ROUTE_ID3_SESSION_CREATION_FAILED, routeId)) {
@@ -238,7 +245,7 @@
     }
 
     @Override
-    public void onReleaseSession(String sessionId) {
+    public void onReleaseSession(long requestId, String sessionId) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         if (sessionInfo == null) {
             return;
@@ -258,7 +265,7 @@
     }
 
     @Override
-    public void onSelectRoute(String sessionId, String routeId) {
+    public void onSelectRoute(long requestId, String sessionId, String routeId) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         MediaRoute2Info route = mRoutes.get(routeId);
         if (route == null || sessionInfo == null) {
@@ -280,7 +287,7 @@
     }
 
     @Override
-    public void onDeselectRoute(String sessionId, String routeId) {
+    public void onDeselectRoute(long requestId, String sessionId, String routeId) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         MediaRoute2Info route = mRoutes.get(routeId);
 
@@ -308,7 +315,7 @@
     }
 
     @Override
-    public void onTransferToRoute(String sessionId, String routeId) {
+    public void onTransferToRoute(long requestId, String sessionId, String routeId) {
         RoutingSessionInfo sessionInfo = getSessionInfo(sessionId);
         MediaRoute2Info route = mRoutes.get(routeId);
 
@@ -347,10 +354,18 @@
         }
 
         String sessionId = mRouteIdToSessionId.get(routeId);
-        onDeselectRoute(sessionId, routeId);
+        onDeselectRoute(REQUEST_ID_NONE, sessionId, routeId);
     }
 
     void publishRoutes() {
         notifyRoutes(mRoutes.values());
     }
+
+    public void setProxy(@Nullable Proxy proxy) {
+        mProxy = proxy;
+    }
+
+    public static class Proxy {
+        public void onSetRouteVolume(String routeId, int volume, long requestId) {}
+    }
 }
diff --git a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
index cbfbf77..afdbce0 100644
--- a/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
+++ b/media/tests/TunerTest/src/com/android/mediatunertest/TunerTest.java
@@ -48,13 +48,13 @@
 
     @Test
     public void testTunerConstructor() throws Exception {
-        Tuner tuner = new Tuner(mContext, "123", 1, null);
+        Tuner tuner = new Tuner(mContext, "123", 1);
         assertNotNull(tuner);
     }
 
     @Test
     public void testOpenDescrambler() throws Exception {
-        Tuner tuner = new Tuner(mContext, "123", 1, null);
+        Tuner tuner = new Tuner(mContext, "123", 1);
         Descrambler descrambler = tuner.openDescrambler();
         assertNotNull(descrambler);
     }
diff --git a/native/android/surface_control.cpp b/native/android/surface_control.cpp
index ba793e8..0af6cbf 100644
--- a/native/android/surface_control.cpp
+++ b/native/android/surface_control.cpp
@@ -547,16 +547,11 @@
 }
 
 void ASurfaceTransaction_setFrameRate(ASurfaceTransaction* aSurfaceTransaction,
-                                      ASurfaceControl* aSurfaceControl, float frameRate) {
+                                      ASurfaceControl* aSurfaceControl, float frameRate,
+                                      int8_t compatibility) {
     CHECK_NOT_NULL(aSurfaceTransaction);
     CHECK_NOT_NULL(aSurfaceControl);
-
-    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
-    if (frameRate < 0) {
-        ALOGE("Failed to set frame ate - invalid frame rate");
-        return;
-    }
-
     Transaction* transaction = ASurfaceTransaction_to_Transaction(aSurfaceTransaction);
-    transaction->setFrameRate(surfaceControl, frameRate);
+    sp<SurfaceControl> surfaceControl = ASurfaceControl_to_SurfaceControl(aSurfaceControl);
+    transaction->setFrameRate(surfaceControl, frameRate, compatibility);
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
index 585acfe..a0d5a1b 100644
--- a/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/CarSystemUIModule.java
@@ -43,9 +43,11 @@
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.volume.CarVolumeDialogComponent;
@@ -74,10 +76,14 @@
 
     @Singleton
     @Provides
-    static HeadsUpManagerPhone provideHeadsUpManagerPhone(Context context,
+    static HeadsUpManagerPhone provideHeadsUpManagerPhone(
+            Context context,
             StatusBarStateController statusBarStateController,
-            KeyguardBypassController bypassController) {
-        return new HeadsUpManagerPhone(context, statusBarStateController, bypassController);
+            KeyguardBypassController bypassController,
+            NotificationGroupManager groupManager,
+            ConfigurationController configurationController) {
+        return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
+                groupManager, configurationController);
     }
 
     @Binds
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index 5af3ad5..a4eada4 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -128,6 +128,7 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -324,6 +325,7 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             DismissCallbackRegistry dismissCallbackRegistry,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
             /* Car Settings injected components. */
             CarServiceProvider carServiceProvider,
             Lazy<PowerManagerHelper> powerManagerHelperLazy,
@@ -405,7 +407,8 @@
                 keyguardDismissUtil,
                 extensionController,
                 userInfoControllerImpl,
-                dismissCallbackRegistry);
+                dismissCallbackRegistry,
+                statusBarTouchableRegionManager);
         mUserSwitcherController = userSwitcherController;
         mScrimController = scrimController;
         mLockscreenLockIconController = lockscreenLockIconController;
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
index 7f64990..7294965 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarStatusBarModule.java
@@ -87,6 +87,7 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
 import com.android.systemui.statusbar.phone.dagger.StatusBarComponent;
 import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneDependenciesModule;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -197,6 +198,7 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             DismissCallbackRegistry dismissCallbackRegistry,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
             CarServiceProvider carServiceProvider,
             Lazy<PowerManagerHelper> powerManagerHelperLazy,
             FullscreenUserSwitcher fullscreenUserSwitcher,
@@ -277,6 +279,7 @@
                 extensionController,
                 userInfoControllerImpl,
                 dismissCallbackRegistry,
+                statusBarTouchableRegionManager,
                 carServiceProvider,
                 powerManagerHelperLazy,
                 fullscreenUserSwitcher,
diff --git a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
index c9ac765..873d7d7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
+++ b/packages/CarSystemUI/src/com/android/systemui/volume/CarVolumeDialogImpl.java
@@ -25,8 +25,11 @@
 import android.app.KeyguardManager;
 import android.car.Car;
 import android.car.media.CarAudioManager;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.res.TypedArray;
 import android.content.res.XmlResourceParser;
 import android.graphics.Color;
@@ -38,6 +41,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.UserHandle;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -171,6 +175,17 @@
                 mCarAudioManager.registerCarVolumeCallback(mVolumeChangeCallback);
             };
 
+    private final BroadcastReceiver mHomeButtonPressedBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
+                return;
+            }
+
+            dismissH(Events.DISMISS_REASON_VOLUME_CONTROLLER);
+        }
+    };
+
     public CarVolumeDialogImpl(Context context) {
         mContext = context;
         mKeyguard = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
@@ -204,12 +219,18 @@
     @Override
     public void init(int windowType, Callback callback) {
         initDialog();
+
+        mContext.registerReceiverAsUser(mHomeButtonPressedBroadcastReceiver, UserHandle.CURRENT,
+                new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), /* broadcastPermission= */
+                null, /* scheduler= */ null);
     }
 
     @Override
     public void destroy() {
         mHandler.removeCallbacksAndMessages(/* token= */ null);
 
+        mContext.unregisterReceiver(mHomeButtonPressedBroadcastReceiver);
+
         cleanupAudioManager();
     }
 
diff --git a/packages/DynamicSystemInstallationService/AndroidManifest.xml b/packages/DynamicSystemInstallationService/AndroidManifest.xml
index d718eae..b4d520d 100644
--- a/packages/DynamicSystemInstallationService/AndroidManifest.xml
+++ b/packages/DynamicSystemInstallationService/AndroidManifest.xml
@@ -7,6 +7,7 @@
     <uses-permission android:name="android.permission.MANAGE_DYNAMIC_SYSTEM" />
     <uses-permission android:name="android.permission.REBOOT" />
     <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.READ_OEM_UNLOCK_STATE" />
 
     <application
         android:allowBackup="false"
diff --git a/packages/DynamicSystemInstallationService/res/values/strings.xml b/packages/DynamicSystemInstallationService/res/values/strings.xml
index 7595d2b..e124be6 100644
--- a/packages/DynamicSystemInstallationService/res/values/strings.xml
+++ b/packages/DynamicSystemInstallationService/res/values/strings.xml
@@ -18,6 +18,8 @@
     <string name="notification_install_inprogress">Install in progress</string>
     <!-- Displayed on notification: Dynamic System installation failed [CHAR LIMIT=128] -->
     <string name="notification_install_failed">Install failed</string>
+    <!-- Displayed on notification: Image validation failed [CHAR LIMIT=128] -->
+    <string name="notification_image_validation_failed">Image validation failed. Abort installation.</string>
     <!-- Displayed on notification: We are running in Dynamic System [CHAR LIMIT=128] -->
     <string name="notification_dynsystem_in_use">Currently running a dynamic system. Restart to use the original Android version.</string>
 
@@ -25,10 +27,11 @@
     <string name="notification_action_cancel">Cancel</string>
     <!-- Action on notification: Discard installation [CHAR LIMIT=16] -->
     <string name="notification_action_discard">Discard</string>
-    <!-- Action on notification: Uninstall Dynamic System [CHAR LIMIT=16] -->
-    <string name="notification_action_uninstall">Uninstall</string>
     <!-- Action on notification: Restart to Dynamic System [CHAR LIMIT=16] -->
     <string name="notification_action_reboot_to_dynsystem">Restart</string>
+    <!-- Action on notification: Restart to original Android version [CHAR LIMIT=16] -->
+    <string name="notification_action_reboot_to_origin">Restart</string>
+
 
     <!-- Toast when installed Dynamic System is discarded [CHAR LIMIT=64] -->
     <string name="toast_dynsystem_discarded">Discarded dynamic system</string>
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 9bae223..37a77be 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
@@ -80,6 +80,7 @@
     static final String KEY_ENABLE_WHEN_COMPLETED = "KEY_ENABLE_WHEN_COMPLETED";
     static final String KEY_DSU_SLOT = "KEY_DSU_SLOT";
     static final String DEFAULT_DSU_SLOT = "dsu";
+    static final String KEY_PUBKEY = "KEY_PUBKEY";
 
     /*
      * Intent actions
@@ -267,6 +268,7 @@
         long userdataSize = intent.getLongExtra(DynamicSystemClient.KEY_USERDATA_SIZE, 0);
         mEnableWhenCompleted = intent.getBooleanExtra(KEY_ENABLE_WHEN_COMPLETED, false);
         String dsuSlot = intent.getStringExtra(KEY_DSU_SLOT);
+        String publicKey = intent.getStringExtra(KEY_PUBKEY);
 
         if (TextUtils.isEmpty(dsuSlot)) {
             dsuSlot = DEFAULT_DSU_SLOT;
@@ -274,7 +276,7 @@
         // TODO: better constructor or builder
         mInstallTask =
                 new InstallationAsyncTask(
-                        url, dsuSlot, systemSize, userdataSize, this, mDynSystem, this);
+                        url, dsuSlot, publicKey, systemSize, userdataSize, this, mDynSystem, this);
 
         mInstallTask.execute();
 
@@ -408,6 +410,10 @@
     }
 
     private Notification buildNotification(int status, int cause) {
+        return buildNotification(status, cause, null);
+    }
+
+    private Notification buildNotification(int status, int cause, Throwable detail) {
         Notification.Builder builder = new Notification.Builder(this, NOTIFICATION_CHANNEL_ID)
                 .setSmallIcon(R.drawable.ic_system_update_googblue_24dp)
                 .setProgress(0, 0, false);
@@ -456,14 +462,19 @@
                         .setStyle(new Notification.BigTextStyle().bigText(msgInUse));
 
                 builder.addAction(new Notification.Action.Builder(
-                        null, getString(R.string.notification_action_uninstall),
+                        null, getString(R.string.notification_action_reboot_to_origin),
                         createPendingIntent(ACTION_REBOOT_TO_NORMAL)).build());
 
                 break;
 
             case STATUS_NOT_STARTED:
                 if (cause != CAUSE_NOT_SPECIFIED && cause != CAUSE_INSTALL_CANCELLED) {
-                    builder.setContentText(getString(R.string.notification_install_failed));
+                    if (detail instanceof InstallationAsyncTask.ImageValidationException) {
+                        builder.setContentText(
+                                getString(R.string.notification_image_validation_failed));
+                    } else {
+                        builder.setContentText(getString(R.string.notification_install_failed));
+                    }
                 } else {
                     // no need to notify the user if the task is not started, or cancelled.
                 }
@@ -525,7 +536,7 @@
                 break;
         }
 
-        Log.d(TAG, "status=" + statusString + ", cause=" + causeString);
+        Log.d(TAG, "status=" + statusString + ", cause=" + causeString + ", detail=" + detail);
 
         boolean notifyOnNotificationBar = true;
 
@@ -538,7 +549,7 @@
         }
 
         if (notifyOnNotificationBar) {
-            mNM.notify(NOTIFICATION_ID, buildNotification(status, cause));
+            mNM.notify(NOTIFICATION_ID, buildNotification(status, cause, detail));
         }
 
         for (int i = mClients.size() - 1; i >= 0; i--) {
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
index 438c435..f8952ac 100644
--- a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
+++ b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/InstallationAsyncTask.java
@@ -17,11 +17,13 @@
 package com.android.dynsystem;
 
 import android.content.Context;
+import android.gsi.AvbPublicKey;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.MemoryFile;
 import android.os.ParcelFileDescriptor;
 import android.os.image.DynamicSystemManager;
+import android.service.persistentdata.PersistentDataBlockManager;
 import android.util.Log;
 import android.webkit.URLUtil;
 
@@ -51,18 +53,46 @@
     private static final List<String> UNSUPPORTED_PARTITIONS =
             Arrays.asList("vbmeta", "boot", "userdata", "dtbo", "super_empty", "system_other");
 
-    private class UnsupportedUrlException extends RuntimeException {
+    private class UnsupportedUrlException extends Exception {
         private UnsupportedUrlException(String message) {
             super(message);
         }
     }
 
-    private class UnsupportedFormatException extends RuntimeException {
+    private class UnsupportedFormatException extends Exception {
         private UnsupportedFormatException(String message) {
             super(message);
         }
     }
 
+    static class ImageValidationException extends Exception {
+        ImageValidationException(String message) {
+            super(message);
+        }
+
+        ImageValidationException(Throwable cause) {
+            super(cause);
+        }
+    }
+
+    static class RevocationListFetchException extends ImageValidationException {
+        RevocationListFetchException(Throwable cause) {
+            super(cause);
+        }
+    }
+
+    static class KeyRevokedException extends ImageValidationException {
+        KeyRevokedException(String message) {
+            super(message);
+        }
+    }
+
+    static class PublicKeyException extends ImageValidationException {
+        PublicKeyException(String message) {
+            super(message);
+        }
+    }
+
     /** UNSET means the installation is not completed */
     static final int RESULT_UNSET = 0;
     static final int RESULT_OK = 1;
@@ -97,12 +127,14 @@
 
     private final String mUrl;
     private final String mDsuSlot;
+    private final String mPublicKey;
     private final long mSystemSize;
     private final long mUserdataSize;
     private final Context mContext;
     private final DynamicSystemManager mDynSystem;
     private final ProgressListener mListener;
     private final boolean mIsNetworkUrl;
+    private final boolean mIsDeviceBootloaderUnlocked;
     private DynamicSystemManager.Session mInstallationSession;
     private KeyRevocationList mKeyRevocationList;
 
@@ -115,6 +147,7 @@
     InstallationAsyncTask(
             String url,
             String dsuSlot,
+            String publicKey,
             long systemSize,
             long userdataSize,
             Context context,
@@ -122,12 +155,20 @@
             ProgressListener listener) {
         mUrl = url;
         mDsuSlot = dsuSlot;
+        mPublicKey = publicKey;
         mSystemSize = systemSize;
         mUserdataSize = userdataSize;
         mContext = context;
         mDynSystem = dynSystem;
         mListener = listener;
         mIsNetworkUrl = URLUtil.isNetworkUrl(mUrl);
+        PersistentDataBlockManager pdbManager =
+                (PersistentDataBlockManager)
+                        mContext.getSystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE);
+        mIsDeviceBootloaderUnlocked =
+                (pdbManager != null)
+                        && (pdbManager.getFlashLockState()
+                                == PersistentDataBlockManager.FLASH_LOCK_UNLOCKED);
     }
 
     @Override
@@ -157,8 +198,6 @@
                 return null;
             }
 
-            // TODO(yochiang): do post-install public key check (revocation list / boot-ramdisk)
-
             mDynSystem.finishInstallation();
         } catch (Exception e) {
             Log.e(TAG, e.toString(), e);
@@ -242,23 +281,26 @@
                     String.format(Locale.US, "Unsupported URL: %s", mUrl));
         }
 
-        // TODO(yochiang): Bypass this check if device is unlocked
         try {
             String listUrl = mContext.getString(R.string.key_revocation_list_url);
             mKeyRevocationList = KeyRevocationList.fromUrl(new URL(listUrl));
         } catch (IOException | JSONException e) {
-            Log.d(TAG, "Failed to fetch Dynamic System Key Revocation List");
             mKeyRevocationList = new KeyRevocationList();
-            keyRevocationThrowOrWarning(e);
+            imageValidationThrowOrWarning(new RevocationListFetchException(e));
+        }
+        if (mKeyRevocationList.isRevoked(mPublicKey)) {
+            imageValidationThrowOrWarning(new KeyRevokedException(mPublicKey));
         }
     }
 
-    private void keyRevocationThrowOrWarning(Exception e) throws Exception {
-        if (mIsNetworkUrl) {
-            throw e;
-        } else {
-            // If DSU is being installed from a local file URI, then be permissive
+    private void imageValidationThrowOrWarning(ImageValidationException e)
+            throws ImageValidationException {
+        if (mIsDeviceBootloaderUnlocked || !mIsNetworkUrl) {
+            // If device is OEM unlocked or DSU is being installed from a local file URI,
+            // then be permissive.
             Log.w(TAG, e.toString());
+        } else {
+            throw e;
         }
     }
 
@@ -294,7 +336,8 @@
         }
     }
 
-    private void installImages() throws IOException, InterruptedException {
+    private void installImages()
+            throws IOException, InterruptedException, ImageValidationException {
         if (mStream != null) {
             if (mIsZip) {
                 installStreamingZipUpdate();
@@ -306,12 +349,14 @@
         }
     }
 
-    private void installStreamingGzUpdate() throws IOException, InterruptedException {
+    private void installStreamingGzUpdate()
+            throws IOException, InterruptedException, ImageValidationException {
         Log.d(TAG, "To install a streaming GZ update");
         installImage("system", mSystemSize, new GZIPInputStream(mStream), 1);
     }
 
-    private void installStreamingZipUpdate() throws IOException, InterruptedException {
+    private void installStreamingZipUpdate()
+            throws IOException, InterruptedException, ImageValidationException {
         Log.d(TAG, "To install a streaming ZIP update");
 
         ZipInputStream zis = new ZipInputStream(mStream);
@@ -330,7 +375,8 @@
         }
     }
 
-    private void installLocalZipUpdate() throws IOException, InterruptedException {
+    private void installLocalZipUpdate()
+            throws IOException, InterruptedException, ImageValidationException {
         Log.d(TAG, "To install a local ZIP update");
 
         Enumeration<? extends ZipEntry> entries = mZipFile.entries();
@@ -349,8 +395,9 @@
         }
     }
 
-    private boolean installImageFromAnEntry(ZipEntry entry, InputStream is,
-            int numInstalledPartitions) throws IOException, InterruptedException {
+    private boolean installImageFromAnEntry(
+            ZipEntry entry, InputStream is, int numInstalledPartitions)
+            throws IOException, InterruptedException, ImageValidationException {
         String name = entry.getName();
 
         Log.d(TAG, "ZipEntry: " + name);
@@ -373,8 +420,9 @@
         return true;
     }
 
-    private void installImage(String partitionName, long uncompressedSize, InputStream is,
-            int numInstalledPartitions) throws IOException, InterruptedException {
+    private void installImage(
+            String partitionName, long uncompressedSize, InputStream is, int numInstalledPartitions)
+            throws IOException, InterruptedException, ImageValidationException {
 
         SparseInputStream sis = new SparseInputStream(new BufferedInputStream(is));
 
@@ -445,6 +493,24 @@
                 publishProgress(progress);
             }
         }
+
+        AvbPublicKey avbPublicKey = new AvbPublicKey();
+        if (!mInstallationSession.getAvbPublicKey(avbPublicKey)) {
+            imageValidationThrowOrWarning(new PublicKeyException("getAvbPublicKey() failed"));
+        } else {
+            String publicKey = toHexString(avbPublicKey.sha1);
+            if (mKeyRevocationList.isRevoked(publicKey)) {
+                imageValidationThrowOrWarning(new KeyRevokedException(publicKey));
+            }
+        }
+    }
+
+    private static String toHexString(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b));
+        }
+        return sb.toString();
     }
 
     private void close() {
diff --git a/packages/OsuLogin/AndroidManifest.xml b/packages/OsuLogin/AndroidManifest.xml
index 123559a..a428cb3 100644
--- a/packages/OsuLogin/AndroidManifest.xml
+++ b/packages/OsuLogin/AndroidManifest.xml
@@ -17,7 +17,7 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-          package="com.android.hotspot2">
+          package="com.android.hotspot2.osulogin">
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
     <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/>
     <uses-permission android:name="android.permission.INTERNET"/>
@@ -28,7 +28,7 @@
         android:label="@string/app_name"
         android:configChanges="keyboardHidden|orientation|screenSize"
         android:supportsRtl="true">
-        <activity android:name="com.android.hotspot2.osu.OsuLoginActivity"
+        <activity android:name="com.android.hotspot2.osulogin.OsuLoginActivity"
                   android:label="@string/action_bar_label"
                   android:theme="@style/AppTheme"
                   android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/packages/OsuLogin/res/layout/osu_web_view.xml b/packages/OsuLogin/res/layout/osu_web_view.xml
index fb3c065..4436aab 100644
--- a/packages/OsuLogin/res/layout/osu_web_view.xml
+++ b/packages/OsuLogin/res/layout/osu_web_view.xml
@@ -3,7 +3,7 @@
              android:id="@+id/container"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
-             tools:context="com.android.hotspot2.osu.OsuLoginActivity">
+             tools:context="com.android.hotspot2.osulogin.OsuLoginActivity">
     <LinearLayout
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java b/packages/OsuLogin/src/com/android/hotspot2/osulogin/OsuLoginActivity.java
similarity index 98%
rename from packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
rename to packages/OsuLogin/src/com/android/hotspot2/osulogin/OsuLoginActivity.java
index 3a994d7..d554745 100644
--- a/packages/OsuLogin/src/com/android/hotspot2/osu/OsuLoginActivity.java
+++ b/packages/OsuLogin/src/com/android/hotspot2/osulogin/OsuLoginActivity.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.hotspot2.osu;
+package com.android.hotspot2.osulogin;
 
 import static android.net.NetworkCapabilities.NET_CAPABILITY_TRUSTED;
 
@@ -42,8 +42,6 @@
 
 import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
 
-import com.android.hotspot2.R;
-
 import java.net.MalformedURLException;
 import java.net.URL;
 
@@ -194,7 +192,7 @@
         // Check if the key event was the Back button.
         if ((keyCode == KeyEvent.KEYCODE_BACK)) {
             // If there is a history to move back
-            if (mWebView.canGoBack()){
+            if (mWebView.canGoBack()) {
                 mWebView.goBack();
                 return true;
             }
@@ -278,6 +276,6 @@
                 mPageError = true;
                 Log.e(TAG, "onReceived Error for MainFrame: " + error.getErrorCode());
             }
-         }
+        }
     }
 }
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index 1a015a6..762053e 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-ontfouting"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"In ontfoutmodus wanneer USB gekoppel is"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Herroep USB-onfoutingmagtigings"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Draadlose ontfouting"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Ontfoutingmodus wanneer Wi-Fi gekoppel is"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Fout"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Draadlose ontfouting"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Skakel draadlose ontfouting aan om beskikbare toestelle te sien en te gebruik"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Gebruik QR-kode om toestel saam te bind"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Gebruik QR-kodeskandeerder om nuwe toestelle saam te bind"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Gebruik saambindkode om toestel saam te bind"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Gebruik \'n sessyferkode om nuwe toestelle saam te bind"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Saamgebinde toestelle"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Tans gekoppel"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Toestelbesonderhede"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Vergeet"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Toestelvingerafdruk: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Kon nie koppel nie"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Maak seker dat <xliff:g id="DEVICE_NAME">%1$s</xliff:g> aan die regte netwerk gekoppel is"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Bind met toestel saam"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi-saambindkode"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Kon nie saambind nie"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Maak seker dat die toestel aan dieselfde netwerk gekoppel is."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Bind toestel oor Wi-Fi saam deur \'n QR-kode te skandeer"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Bind tans toestel saam …"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Kon nie die toestel saambind nie. Óf die QR-kode is verkeerd, óf die toestel is nie aan dieselfde netwerk gekoppel nie."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adres en -poort"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skandeer QR-kode"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Bind toestel oor Wi-Fi saam deur \'n QR-kode te skandeer"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Kortpad na foutverslag"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Wys \'n knoppie in die kragkieslys om \'n foutverslag te doen"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Bly wakker"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Gebruik hardewareversnelling vir verbinding indien beskikbaar"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Laat USB-ontfouting toe?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-ontfouting is net vir ontwikkelingsdoeleindes bedoel. Gebruik dit om data te kopieer tussen jou rekenaar en jou toestel, programme op jou toestel te installeer sonder kennisgewing en om loglêerdata te lees."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Laat draadlose ontfouting toe?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Draadlose ontfouting is net vir ontwikkelingsdoeleindes bedoel. Gebruik dit om data te kopieer tussen jou rekenaar en jou toestel, programme op jou toestel te installeer sonder kennisgewing, en loglêerdata te lees."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Herroep toegang tot USB-ontfouting vanaf alle rekenaars wat jy voorheen gemagtig het?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Laat ontwikkeling-instellings toe?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Hierdie instellings is bedoel net vir ontwikkelinggebruik. Dit kan jou toestel en die programme daarop breek of vreemde dinge laat doen."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rooi-groen)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blou-geel)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurregstelling"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Kleurregstelling help mense met kleurblindheid om akkurater kleure te sien"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Geneutraliseer deur <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Minder as <xliff:g id="THRESHOLD">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Meer as <xliff:g id="TIME_REMAINING">%1$s</xliff:g> oor"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Foon kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Toestel kan binnekort afgaan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Foon kan binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet kan binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Toestel kan binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Foon sal dalk binnekort afgaan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet sal dalk binnekort afgaan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Toestel sal dalk binnekort afgaan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Foon sal dalk binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet sal dalk binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Toestel sal dalk binnekort afgaan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> oor tot battery gelaai is"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> tot battery gelaai is"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laai"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laai tans vinnig"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laai tans stadig"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Laai nie"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Ingeprop; kan nie op die oomblik laai nie"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Vol"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 05f0e1b..3e6886c 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"የUSB አራሚ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB ሲያያዝ የአርም ሁኔታ"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"የዩ ኤስ ቢ ስህተት ማረም ፈቀዳዎችን ይሻሩ"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ገመድ-አልባ ማረም"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi ሲገናኝ የማረም ሁነታ"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ስህተት"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ገመድ-አልባ ማረም"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"የሚገኙ መሣሪያዎችን ለመመልከትና ለመጠቀም ገመድ-አልባ ማረምን ያብሩ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"የQR ኮድን በመጠቀም መሣሪያን ያጣምሩ"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"የQR ኮድ መቃኛን በመጠቀም አዲስ መሣሪያዎችን ያጣምሩ"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"የማጣመሪያ ኮድን በመጠቀም መሣሪያን ያጣምሩ"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"የስድስት አኃዝ ኮድ በመጠቀም አዲስ መሣሪያዎችን ያጣምሩ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"የተጣመሩ መሣሪያዎች"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"አሁን ላይ ተገናኝቷል"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"የመሣሪያ ዝርዝሮች"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"እርሳ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"የመሣሪያ አሻራ፦ <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ግንኙነት አልተሳካም"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ከትክክለኛው አውታረ መረብ ጋር መገናኘቱን ያረጋግጡ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"በመሣሪያ ያጣምሩ"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"የWi-Fi ማጣመሪያ ኮድ"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ማጣመር ተሳክቷል"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"መሣሪያው ከተመሳሳዩ አውታረ መረብ ጋር መገናኘቱን ያረጋግጡ።"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"የQR ኮድ በመጠቀም መሣሪያን በመቃኘት በWi-Fi ላይ ያጣምሩ"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"መሣሪያን በማጣመር ላይ…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"መሣሪያውን ማጣመር አልተሳካም። ወይም QR ኮዱ ትክክል አልነበረም፣ ወይም መሣሪያው ከተመሳሳዩ አውታረ መረብ ጋር አልተገናኘም።"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"የአይፒ አድራሻ እና ወደብ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ኮድን ይቃኙ"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"የQR ኮድ በመጠቀም መሣሪያን በመቃኘት በWi-Fi ላይ ያጣምሩ"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb፣ ማረም፣ ግንባታ"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"የሳንካ ሪፖርት አቋራጭ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"የሳንካ ሪፖርት ለመውሰድ በሃይል ምናሌ ውስጥ አዝራር አሳይ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ነቅተህ ቆይ"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"የሃርድዌር ማቀላጠፊያን ማስተሳሰርን የሚገኝ ከሆነ ይጠቀሙ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"የUSB ማረሚያ ይፈቀድ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"የUSB አድስ ለግንባታ አላማ ብቻ የታሰበ ነው። ከኮምፒዩተርህ ወደ መሳሪያህ ውሂብ ለመገልበጥ፣ መሣሪያህ ላይ ያለ ማሳወቂያ መተግበሪያዎችን መጫን፣ እና ማስታወሻ ውሂብ ማንበብ ለመጠቀም ይቻላል።"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ገመድ-አልባ ማረም ይፈቀድ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ገመድ-አልባ ማረም ለግንባታ አላማዎች ብቻ የታሰበ ነው። ውሂብን ከኮምፒዩተርዎ ወደ መሳሪያዎ ለመቅዳት፣ መሣሪያዎ ላይ ያለማሳወቂያ መተግበሪያዎችን ለመጫን እና የምዝግብ ማስታወሻ ውሂብን ለማንበብ ይጠቀሙበት።"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"የዩ ኤስ ቢ ማረም መዳረሻ ከዚህ ቀደም ፍቃድ ከሰጧቸው ኮምፒውተሮች ላይ ይሻሩ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"የግንባታ ቅንብሮችን ፍቀድ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"እነዚህ ቅንብሮች  የታሰቡት ለግንባታ አጠቃቀም ብቻ ናቸው። መሳሪያህን እና በሱ ላይ ያሉትን መተግበሪያዎች እንዲበለሹ ወይም በትክክል እንዳይሰሩ ሊያደርጉ ይችላሉ።"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ፕሮታኖማሊ (ቀይ-አረንጓዴ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ትራይታኖማሊ (ሰማያዊ-ቢጫ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"የቀለም ማስተካከያ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ቀለም ማስተካከያ ቀለም ማየት የማይችሉ ሰዎች ተጨማሪ ትክክለኛ ቀለማትን እንዲመለከቱ ያስችላቸዋል"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"በ<xliff:g id="TITLE">%1$s</xliff:g> ተሽሯል"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ገደማ ቀርቷል"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"ከ<xliff:g id="THRESHOLD">%1$s</xliff:g> ያነሰ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"ከ<xliff:g id="TIME_REMAINING">%1$s</xliff:g> በላይ ይቀራል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ስልኩ በቅርቡ ሊዘጋ ይችላል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ጡባዊው በቅርቡ ሊዘጋ ይችላል"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"መሣሪያው በቅርቡ ሊዘጋ ይችላል"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ስልኩ በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ጡባዊው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"መሣሪያው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ስልኩ በቅርቡ ሊዘጋ ይችላል"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ጡባዊው በቅርቡ ሊዘጋ ይችላል"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"መሣሪያው በቅርቡ ሊዘጋ ይችላል"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ስልኩ በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ጡባዊው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"መሣሪያው በቅርቡ ሊዘጋ ይችላል (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ኃይል እስከሚሞላ ድረስ ይቀራል"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ኃይል እስከሚሞላ ድረስ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ያልታወቀ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ኃይል በመሙላት ላይ"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ኃይል በፍጥነት በመሙላት ላይ"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ኃይል በዝግታ በመሙላት ላይ"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ባትሪ እየሞላ አይደለም"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ተሰክቷል፣ አሁን ኃይል መሙላት አይቻልም"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ሙሉነው"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index 07befeb..7fa6b7f 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -206,6 +206,60 @@
     <string name="enable_adb" msgid="8072776357237289039">"‏تصحيح أخطاء USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"‏وضع تصحيح الأخطاء عند توصيل USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"‏إلغاء عمليات تفويض تصحيح أخطاء USB"</string>
+    <!-- no translation found for enable_adb_wireless (6973226350963971018) -->
+    <skip />
+    <!-- no translation found for enable_adb_wireless_summary (7344391423657093011) -->
+    <skip />
+    <!-- no translation found for adb_wireless_error (721958772149779856) -->
+    <skip />
+    <!-- no translation found for adb_wireless_settings (2295017847215680229) -->
+    <skip />
+    <!-- no translation found for adb_wireless_list_empty_off (1713707973837255490) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_title (6982904096137468634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_summary (3729901496856458634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_title (1122590300445142904) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_summary (6370414511333685185) -->
+    <skip />
+    <!-- no translation found for adb_paired_devices_title (5268997341526217362) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_connected_summary (3039660790249148713) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_details_title (7129369670526565786) -->
+    <skip />
+    <!-- no translation found for adb_device_forget (193072400783068417) -->
+    <skip />
+    <!-- no translation found for adb_device_fingerprint_title_format (291504822917843701) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_title (664211177427438438) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_message (9213896700171602073) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_title (7141739231018530210) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_pairing_code_label (3639239786669722731) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_title (3426758947882091735) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_msg (6611097519661997148) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_summary (8051414549011801917) -->
+    <skip />
+    <!-- no translation found for adb_wireless_verifying_qrcode_text (6123192424916029207) -->
+    <skip />
+    <!-- no translation found for adb_qrcode_pairing_device_failed_msg (6936292092592914132) -->
+    <skip />
+    <!-- no translation found for adb_wireless_ip_addr_preference_title (8335132107715311730) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_title (1906409667944674707) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_description (8578868049289910131) -->
+    <skip />
+    <!-- no translation found for keywords_adb_wireless (6507505581882171240) -->
+    <skip />
     <string name="bugreport_in_power" msgid="8664089072534638709">"اختصار تقرير الأخطاء"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"عرض زر في قائمة خيارات التشغيل لإعداد تقرير بالأخطاء"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"البقاء في الوضع النشط"</string>
@@ -271,6 +325,10 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"استخدام إعداد تسريع الأجهزة للتوصيل إن كان متاحًا"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‏هل تريد السماح بتصحيح أخطاء USB؟"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‏تم تصميم تصحيح أخطاء USB لأغراض التطوير فقط. يمكن استخدامه لنسخ البيانات بين الكمبيوتر والجهاز، وتثبيت التطبيقات على جهازك بدون تنبيه، وقراءة بيانات السجل."</string>
+    <!-- no translation found for adbwifi_warning_title (727104571653031865) -->
+    <skip />
+    <!-- no translation found for adbwifi_warning_message (8005936574322702388) -->
+    <skip />
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‏هل تريد إلغاء إمكانية الدخول إلى تصحيح أخطاء USB من جميع أجهزة الكمبيوتر التي تم التصريح لها سابقًا؟"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"هل تريد السماح لإعدادات التطوير؟"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"هذه الإعدادات مخصصة لاستخدام التطوير فقط. قد يتسبب هذا في حدوث أعطال أو خلل في أداء الجهاز والتطبيقات المثبتة عليه."</string>
@@ -403,12 +461,18 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"يتبقى أقل من <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"يتبقى أكثر من <xliff:g id="TIME_REMAINING">%1$s</xliff:g>."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"قد يتم إغلاق الهاتف بعد قليل."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"قد يتم إغلاق الجهاز اللوحي بعد قليل."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"قد يتم إغلاق الجهاز بعد قليل."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"قد يتم إغلاق الهاتف بعد قليل (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"قد يتم إغلاق الجهاز اللوحي بعد قليل (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"قد يتم إغلاق الجهاز بعد قليل (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (137330009791560774) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (145489081521468132) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1070562682853942350) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4429259621177089719) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7703677921000858479) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4374784375644214578) -->
+    <skip />
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> إلى أن يتم شحن الجهاز بالكامل"</string>
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index 4d0d8cc..dc22f29 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"ইউএছবি ডিবাগিং"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"ইউএছবি সংযোগ হৈ থকাৰ অৱস্থাত ডিবাগ ম\'ড"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"ইউএছবি ডিবাগিং অনুমতিসমূহ প্ৰত্যাহাৰ কৰক"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ৱায়াৰলেছ ডিবাগিং"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ৱাই-ফাই সংযোজিত হৈ থকা সময়ত ডিবাগ ম’ড"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"আসোঁৱাহ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ৱায়াৰলেছ ডিবাগিং"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"উপলব্ধ ডিভাইচসমূহ চাবলৈ আৰু ব্যৱহাৰ কৰিবলৈ, ৱায়াৰলেছ ডিবাগিং অন কৰক"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"কিউআৰ ক’ডৰ জৰিয়তে ডিভাইচ পেয়াৰ কৰক"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"কিউআৰ ক’ড স্কেনাৰ ব্যৱহাৰ কৰি নতুন ডিভাইচসমূহ পেয়াৰ কৰক"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"পেয়াৰ কৰা ক’ডৰ জৰিয়তে ডিভাইচ পেয়াৰ কৰক"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ছটা অংকৰ ক’ড ব্যৱহাৰ কৰি নতুন ডিভাইচসমূহ পেয়াৰ কৰক"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"পেয়াৰ কৰি থোৱা ডিভাইচসমূহ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"সম্প্ৰতি সংযোজিত হৈ আছে"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ডিভাইচটোৰ সবিশেষ"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"পাহৰক"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ডিভাইচৰ ফিংগাৰপ্ৰিণ্ট: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"সংযোগ কৰিব পৰা নগ’ল"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>টো শুদ্ধ নেটৱৰ্কৰ সৈতে সংযোগ কৰাটো নিশ্চিত কৰক"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ডিভাইচৰ সৈতে পেয়াৰ কৰক"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ৱাই-ফাইৰ পেয়াৰ কৰা ক’ড"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"পেয়াৰ কৰিব পৰা নগ’ল"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ডিভাইচটো একেটা নেটৱৰ্কৰ সৈতে সংযোগ কৰাটো নিশ্চিত কৰক।"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"এটা কিউআৰ ক’ড স্কেন কৰি ৱাই-ফাইৰে ডিভাইচ পেয়াৰ কৰক"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ডিভাইচ পেয়াৰ কৰি থকা হৈছে…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ডিভাইচটো পেয়াৰ কৰিব পৰা নগ’ল। কিউআৰ ক’ডটো ভুল অথবা ডিভাইচটো একেটা নেটৱৰ্কৰ সৈতে সংযোগ কৰা হোৱা নাই।"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"আইপি ঠিকনা &amp; প’ৰ্ট"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"কিউআৰ ক’ড স্কেন কৰক"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"এটা কিউআৰ ক’ড স্কেন কৰি ৱাই-ফাইৰে ডিভাইচ পেয়াৰ কৰক"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ডিবাগ, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"বাগ ৰিপৰ্টৰ শ্ৱৰ্টকাট"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"পাৱাৰ মেনুত বাগ প্ৰতিবেদন গ্ৰহণ কৰিবলৈ এটা বুটাম দেখুৱাওক"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"জাগ্ৰত কৰি ৰাখক"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"যদিহে উপলব্ধ হয় তেন্তে টেডাৰিং হাৰ্ডৱেৰ ত্বৰণ ব্যৱহাৰ কৰক"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"ইউএছবি ডিবাগিঙৰ অনুমতি দিয়েনে?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"ইউএছবি ডিবাগ কৰা কাৰ্য কেৱল বিকাশৰ উদ্দেশ্যৰেহে কৰা হৈছে৷ আপোনাৰ কম্পিউটাৰ আৰু আপোনাৰ ডিভাইচৰ মাজত ডেটা প্ৰতিলিপি কৰিবলৈ এইটো ব্যৱহাৰ কৰক, কোনো জাননী নিদিয়াকৈয়ে আপোনাৰ ডিভাইচত এপ্‌সমূহ ইনষ্টল কৰক আৰু লগ ডেটা পঢ়ক৷"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ৱায়াৰলেছ ডিবাগিঙৰ অনুমতি দিবনে?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ৱায়াৰলেছ ডিবাগিং কেৱল বিকাশৰ উদ্দেশ্যেৰে কৰা হয়। আপোনাৰ কম্পিউটাৰ আৰু আপোনাৰ ডিভাইচৰ মাজত ডেটা প্ৰতিলিপি কৰিবলৈ, কোনো জাননী নিদিয়াকৈয়ে আপোনাৰ ডিভাইচত এপ্‌সমূহ ইনষ্টল কৰিবলৈ আৰু লগ ডেটা পঢ়িবলৈ এইটো ব্যৱহাৰ কৰক।"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"আপুনি আগতে ইউএছবি ডিবাগিঙৰ বাবে প্ৰৱেশৰ অনুমতি দিয়া সকলো কম্পিউটাৰৰ পৰা সেই অনুমতি প্ৰত্যাহাৰ কৰেনে?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"বিকাশৰ কামৰ বাবে থকা ছেটিংবিলাকক অনুমতি দিবনে?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"এই ছেটিংসমূহ বিকাশৰ কামত ব্যৱহাৰ কৰিবলৈ তৈয়াৰ কৰা হৈছে। সেইবিলাকে আপোনাৰ ডিভাইচ আৰু তাত থকা এপ্লিকেশ্বনসমূহক অকামিলা কৰি পেলাব পাৰে আৰু সেইবিলাকৰ কাৰণে এপ্লিকেশ্বনসমূহে অদ্ভুত আচৰণ কৰিব পাৰে।"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্ৰ’টানোমালি (ৰঙা-সেউজীয়া)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্ৰাইটান\'মেলী (নীলা-হালধীয়া)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ৰং শুধৰণী"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ৰং শুধৰণি কৰা কার্যই বর্ণান্ধ লোকসকলক ৰংবোৰ অধিক সঠিককৈ দেখাত সহায় কৰে"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>ৰ দ্বাৰা অগ্ৰাহ্য কৰা হৈছে"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"প্রায় <xliff:g id="TIME_REMAINING">%1$s</xliff:g> বাকী আছে"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>তকৈও কম সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>তকৈও বেছি সময় বাকী আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>তকৈও বেছি সময় বাকী আছে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ফ\'নটো সোনকালেই বন্ধ হ\'ব পাৰে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"টেবলেটটো সোনকালেই বন্ধ হ\'ব পাৰে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ডিভাইচটো সোনকালেই বন্ধ হ\'ব পাৰে"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ফ\'নটো সোনকালেই বন্ধ হ\'ব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"টেবলেটটো সোনকালেই বন্ধ হ\'ব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ডিভাইচটো সোনকালেই বন্ধ হ\'ব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ফ’নটো সোনকালে বন্ধ হৈ যাব পাৰে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"টেবলেটটো সোনকালে বন্ধ হৈ যাব পাৰে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ডিভাইচটো সোনকালে বন্ধ হৈ যাব পাৰে"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ফ’নটো সোনকালে বন্ধ হৈ যাব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"টেবলেটটো সোনকালে বন্ধ হৈ যাব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ডিভাইচটো সোনকালে বন্ধ হৈ যাব পাৰে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"চাৰ্জ হ’বলৈ <xliff:g id="TIME">%1$s</xliff:g> বাকী আছে"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> চাৰ্জ হ\'বলৈ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজ্ঞাত"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চাৰ্জ কৰি থকা হৈছে"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্ৰুততাৰে চাৰ্জ হৈছে"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"লাহে লাহে চাৰ্জ হৈছে"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"চ্চাৰ্জ কৰা নাই"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"প্লাগ কৰি থোৱা হৈছে, এই মুহূৰ্তত চ্চাৰ্জ কৰিব নোৱাৰি"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"পূৰ্ণ"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 73eb48a..9b082b6 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB debaq prosesi"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB qoşulu olan zaman debaq rejimi"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB debaq avtorizasiyasını ləğv edin"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Simsiz sazlama"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi qoşulduqda sazlama rejimi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Xəta"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Simsiz sazlama"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Əlçatan cihazları görmək və onlardan istifadə etmək üçün simsiz sazlamanı yandırın"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR kodu ilə cihazı cütləşdirin"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR kod Skanerindən istifadə etməklə yeni cihazları cütləşdirin"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Cütləşdirmə kodu ilə cihazı cütləşdirin"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Altı rəqəmli koddan istifadə etməklə yeni cihazları cütləşdirin"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Cütləşdirilmiş cihazlar"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Hazırda qoşulub"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Cihaz detalları"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Unudun"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Cihaz barmaq izi: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Bağlantı uğursuz oldu"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının düzgün şəbəkəyə qoşulduğundan əmin olun"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Cihaz ilə cütləşdirin"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi cütləşdirmə kodu"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Cütləşdirmə uğursuz oldu"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Cihazın eyni şəbəkəyə qoşulduğundan əmin olun."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR kodu skanlamaqla cihazı Wi‑Fi vasitəsilə cütləşdirin"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Cihaz cütləşdirilir…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Cihazı cütləşdirmək alınmadı. Ya QR kodu yanlış idi, ya da cihaz eyni şəbəkəyə qoşulmayıb."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ünvanı və Port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodu skanlayın"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR Kodu skanlamaqla cihazı Wi‑Fi vasitəsilə cütləşdirin"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Baq raportu qısa yolu"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Baq raportunu götürmək üçün qidalanma menyusunda düyməni göstərin"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Oyaq qal"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Əlçatan oldarsa, birləşmə üçün avadanlıq akselerasiyasından istifadə edin"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB debaq funksiyasına icazə verilsin?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB sazlanması yalnız inkişaf məqsədlidir. Kompüteriniz və cihazınız arasında datanı kopyalamaq üçün ondan istifadə edin, bildiriş olmadan tətbiqləri cihazınıza quraşdırın və qeydiyyat datasını oxuyun."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Simsiz sazlamaya icazə verilsin?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Simsiz sazlama yalnız inkişaf məqsədlidir. Ondan kompüteriniz və cihazınız arasında datanı kopyalamaq, cihazınızda bildiriş olmadan tətbiqləri quraşdırmaq və qeydiyyat datasını oxumaq üçün istifadə edin."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Əvvəl icazə verdiyiniz kompüterlərdən USB debaq əməliyyatına giriş ləğv olunsun?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"İnkişaf ayarlarına icazə verilsin mi?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Bu parametrlər yalnız inkişafetdirici istifadə üçün nəzərdə tutulub. Onlar cihaz və tətbiqlərinizin sınması və ya pis işləməsinə səbəb ola bilər."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qırmızı-yaşıl)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (göy-sarı)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rəng düzəlişi"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Rəng korreksiyası rəng korluğu olan insanlara rəngləri daha dəqiq görməkdə kömək edir"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tərəfindən qəbul edilmir"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Təxminən <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qalıb"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Qalan vaxt <xliff:g id="THRESHOLD">%1$s</xliff:g> və daha azdır (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Qalan vaxt <xliff:g id="TIME_REMAINING">%1$s</xliff:g> və daha çoxdur"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Planşet tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Cihaz tezliklə sönə bilər"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon tezliklə sönə bilər(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Planşet tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Cihaz tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Planşet tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Cihaz tezliklə sönə bilər"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Planşet tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Cihaz tezliklə sönə bilər (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Enerjinin dolmasına <xliff:g id="TIME">%1$s</xliff:g> qalıb"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - Enerjinin dolmasına <xliff:g id="TIME">%2$s</xliff:g> qalıb"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Naməlum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Enerji doldurma"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Sürətlə doldurulur"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Asta doldurulur"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Doldurulmur"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Cihaz hazırda batareya yığa bilmir"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Tam"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index dff657e..cc63740 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Otklanjanje USB grešaka"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Režim otklanjanja grešaka kada je USB povezan"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Opozivanje odobrenja za uklanjanje USB grešaka"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bežično otklanjanje grešaka"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Režim za otklanjanje grešaka kada je Wi‑Fi povezan"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Greška"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bežično otklanjanje grešaka"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Da biste videli i koristili dostupne uređaje, uključite bežično otklanjanje grešaka"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Uparite uređaj pomoću QR koda"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Uparite nove uređaje pomoću čitača QR koda"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Uparite uređaj pomoću koda za uparivanje"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Uparite nove uređaje pomoću šestocifrenog koda"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Upareni uređaji"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Trenutno je povezano"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalji o uređaju"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Zaboravi"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Otisak prsta na uređaju: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Povezivanje nije uspelo"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Uverite se da je <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povezan sa odgovarajućom mrežom"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Uparite sa uređajem"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kôd za uparivanje preko Wi‑Fi-ja"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Uparivanje nije uspelo"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Uverite se da je uređaj povezan na istu mrežu."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Uparite uređaj pomoću Wi‑Fi mreže ili tako što ćete skenirati QR kôd"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Uparuje se uređaj…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Uparivanje uređaja nije uspelo. QR kôd je pogrešan ili uređaj nije povezan sa istom mrežom."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skeniraj QR kôd"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparite uređaj pomoću Wi‑Fi mreže ili tako što ćete skenirati QR kôd"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izveštaj o greškama"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaži dugme u meniju napajanja za pravljenje izveštaja o greškama"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ne zaključavaj"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Koristi hardversko ubrzanje privezivanja ako je dostupno"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Dozvoli otklanjanje USB grešaka?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Otklanjanje USB grešaka namenjeno je samo za svrhe programiranja. Koristite ga za kopiranje podataka sa računara na uređaj i obrnuto, instaliranje aplikacija na uređaju bez obaveštenja i čitanje podataka iz evidencije."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Želite da dozvolite bežično otklanjanje grešaka?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bežično otklanjanje grešaka namenjeno je samo programiranju. Koristite ga za kopiranje podataka sa računara na uređaj i obrnuto, instaliranje aplikacija na uređaju bez obaveštenja i čitanje podataka iz evidencije."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Želite li da opozovete pristup otklanjanju USB grešaka sa svih računara koje ste prethodno odobrili?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Želite li da omogućite programerska podešavanja?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ova podešavanja su namenjena samo za programiranje. Mogu da izazovu prestanak funkcionisanja ili neočekivano ponašanje uređaja i aplikacija na njemu."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boja"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korekcija boja pomaže ljudima koji su daltonisti da preciznije vide boje"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamenjuje ga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Uređaj će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Uređaj će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napuniće se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napuniće se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Puni se"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo se puni"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo se puni"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Priključeno je, ali punjenje trenutno nije moguće"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index 12c21a6..f08726e 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Адладка USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Рэжым адладкі, калі USB падключаны"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Адклікаць дазвол USB-адладкі"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Бесправадная адладка"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Рэжым адладкі з падключанай сеткай Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Памылка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Бесправадная адладка"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Каб праглядаць і выкарыстоўваць даступныя прылады, уключыце бесправадную адладку"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Спалучыць прыладу з дапамогай QR-кода"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Спалучаць новыя прылады з дапамогай сканера QR-кода"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Спалучыць прыладу з дапамогай кода спалучэння"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Спалучаць новыя прылады з дапамогай шасцізначнага кода"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Спалучаныя прылады"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Цяпер падключана"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Падрабязныя звесткі пра прыладу"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Ігнараваць"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Лічбавы адбітак прылады: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Не ўдалося падключыцца"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Пераканайцеся, што прылада \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" падключана да правільнай сеткі"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Спалучыць з прыладай"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код спалучэння Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Не ўдалося спалучыць"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Пераканайцеся, што прылада падключана да той самай сеткі."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Спалучыць прыладу праз Wi‑Fi шляхам сканіравання QR-кода"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Прылада спалучаецца…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Не ўдалося спалучыць прыладу. QR-код няправільны, ці прылада падключана не да той самай сеткі."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адрас і порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканіраваць QR-код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Спалучыць прыладу праз Wi‑Fi шляхам сканіравання QR-кода"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, адладка, распрацоўшчык"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ярлык для справаздачы пра памылкі"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Паказаць кнопку для прыняцця справаздачы пра памылку ў меню сілкавання"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Прадухіляць ад пераходу ў рэжым сну"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Выкарыстоўваць апаратнае паскарэнне ў рэжыме мадэма пры наяўнасці"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Дазволіць адладку USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Адладка USB прызначана толькі для мэтаў распрацоўкі. Яна можа выкарыстоўвацца, каб капіяваць дадзеныя паміж кампутарам і прыладай, усталёўваць прыкладанні на прыладзе без папярэдняга апавяшчэння і чытаць дадзеныя дзённiка."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Дазволіць бесправадную адладку?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Бесправадная адладка прызначана толькі для мэт распрацоўкі. Яна можа выкарыстоўвацца, каб капіраваць даныя паміж камп\'ютарам і прыладай, усталёўваць праграмы на прыладзе без апавяшчэння і чытаць даныя журнала."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Адклікаць доступ да адладкі USB з усіх камп\'ютараў, на якiх вы уваходзiлi ў сiстэму?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Дазволiць налады распрацоўшчыка?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Гэтыя налады прызначаны толькi для распрацоўшыкаў. Яны могуць выклікаць збоi прылад i ўсталяваных на iх прыкладанняў, а таксама перашкаджаць iх працы."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Пратанамалія (чырвоны-зялёны)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Трытанамалія (сіні-жоўты)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Карэкцыя колеру"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Карэкцыя колеру дазваляе людзям з парушэннямі колеравага зроку лепш распазнаваць выявы на экране"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Перавызначаны <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Зараду хопіць прыблізна на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць менш чым на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Узровень зараду батарэі: <xliff:g id="LEVEL">%2$s</xliff:g> (хопіць больш чым на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Хопіць больш чым на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Тэлефон у хуткім часе спыніць працу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Планшэт у хуткім часе спыніць працу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Прылада ў хуткім часе спыніць працу"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Узровень зараду батарэі: <xliff:g id="LEVEL">%1$s</xliff:g>. Тэлефон хутка спыніць працу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Узровень зараду батарэі: <xliff:g id="LEVEL">%1$s</xliff:g>. Планшэт хутка спыніць працу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Узровень зараду батарэі: <xliff:g id="LEVEL">%1$s</xliff:g>. Прылада хутка спыніць працу."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Тэлефон у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Планшэт у хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Прылада ў хуткім часе выключыцца"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Тэлефон у хуткім часе выключыцца (узровень зараду: <xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшэт у хуткім часе выключыцца (узровень зараду: <xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Прылада ў хуткім часе выключыцца (узровень зараду: <xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Засталося <xliff:g id="TIME">%1$s</xliff:g> да поўнай зарадкі"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> да поўнай зарадкі"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невядома"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарадка"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хуткая зарадка"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Павольная зарадка"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не зараджаецца"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Падключана да сеткі сілкавання, зарадзіць зараз немагчыма"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Акумулятар зараджаны"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 6fda5b3..78ab01a 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"През USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Режим за отстраняване на грешки, когато е свързано USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Отмяна на упълномощ. за отстр. на грешки през USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Безжично отстраняване на грешки"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим за отстраняване на грешки при връзка с Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Безжично отстраняване на грешки"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"За да виждате и използвате наличните устройства, включете функцията за отстраняване на грешки през безжична мрежа"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Сдвояване на устройството чрез QR код"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Сдвояване на новите устройства чрез скенер за QR кодове"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Сдвояване на устройството чрез код за сдвояване"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Сдвояване на новите устройства чрез шестцифрен код"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Сдвоени устройства"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Понастоящем свързано"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Подробности за устройството"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Забравяне"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Сензор за отпечатъци на устройството: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Връзката не е успешна"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Проверете дали устройството „<xliff:g id="DEVICE_NAME">%1$s</xliff:g>“ е свързано с правилната мрежа"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Сдвояване с устройство"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код за сдвояване през Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Сдвояването не е успешно"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Уверете се, че устройството е свързано със същата мрежа."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Сдвояване на устройството през Wi‑Fi чрез сканиране на QR код"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Устройството се сдвоява…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Сдвояването на устройството не бе успешно. QR кодът е неправилен или устройството не е свързано със същата мрежа."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP адрес и порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканиране на QR код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Сдвояване на устройството през Wi‑Fi чрез сканиране на QR код"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отстраняване на грешки, програмиране"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Пряк път за сигнал за програмна грешка"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"В менюто за захранване да се показва бутон за подаване на сигнал за програмна грешка"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Да остане активен"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Да се използва хардуерно ускорение на тетъринга, ако е налице"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Разрешаване на отстраняването на грешки през USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Отстраняването на грешки през USB е предназначено само за програмни цели. Използвайте го за копиране на данни между компютъра и устройството си, за инсталиране на приложения на устройството си без известяване и за четене на регистрационни данни."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Да се разреши ли отстраняването на грешки през безжична мрежа?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Отстраняването на грешки през безжична мрежа е предназначено само за програмни цели. Използвайте го за копиране на данни между компютъра и устройството си, за инсталиране на приложения на устройството си без известяване и за четене на регистрационни данни."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Да се отмени ли достъпът до отстраняването на грешки през USB от всички по-рано упълномощени от вас компютри?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Да се разрешат ли настройките за програмиране?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Тези настройки са предназначени само за програмиране. Те могат да доведат до прекъсване на работата или неправилно функциониране на устройството ви и приложенията в него."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (червено – зелено)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синьо – жълто)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекция на цветове"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Коригирането на цветовете помага на хората с цветна слепота да виждат по-точни цветове"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Заменено от „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Още около <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Остава/т по-малко от <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Остава/т повече от <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Възможно е телефонът да се изключи скоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Възможно е таблетът да се изключи скоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Възможно е устройството да се изключи скоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Възможно е телефонът да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Възможно е таблетът да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Възможно е устройството да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Възможно е телефонът да се изключи скоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Възможно е таблетът да се изключи скоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Възможно е устройството да се изключи скоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Възможно е телефонът да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Възможно е таблетът да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Възможно е устройството да се изключи скоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Оставащо време до пълно зареждане: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до пълно зареждане"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарежда се"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Зарежда се бързо"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Зарежда се бавно"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се зарежда"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Включена в захранването, в момента не се зарежда"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Пълна"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index be2d1e0..15ebfb8 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ডিবাগিং"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB কানেক্ট থাকাকালীন ডিবাগ মোড"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ডিবাগিং অনুমতিগুলি প্রত্যাহার করুন"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ওয়্যারলেস ডিবাগিং"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ওয়াই-ফাই কানেক্ট থাকাকালীন ডিবাগ মোড"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"সমস্যা"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ওয়্যারলেস ডিবাগিং"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"কোন কোন ডিভাইস উপলভ্য আছে তা দেখে নিয়ে ব্যবহার করার জন্য, ওয়্যারলেস ডিবাগিং চালু করুন"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR কোড ব্যবহার করে ডিভাইস যোগ করুন"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR কোড স্ক্যানার ব্যবহার করে নতুন ডিভাইস যোগ করুন"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"যোগ করার কোড ব্যবহার করে ডিভাইস যোগ করুন"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ছয় সংখ্যার কোড ব্যবহার করে নতুন ডিভাইস যোগ করুন"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"যোগ করা ডিভাইস"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"এখন কানেক্ট রয়েছে"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ডিভাইসের বিবরণ"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ভুলে যান"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ডিভাইসে আঙ্গুলের ছাপ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"কানেক্ট করা যায়নি"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>টি সঠিক নেটওয়ার্কে কানেক্ট আছে কিনা দেখে নিন"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ডিভাইসের সাথে যোগ করুন"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ওয়াই-ফাই যোগ করার কোড"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"যোগ করা যায়নি"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ডিভাইসটি একই নেটওয়ার্কে কানেক্ট আছে কিনা দেখে নিন।"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR কোড স্ক্যান করে ওয়াই-ফাই ব্যবহার করে ডিভাইস যোগ করুন"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ডিভাইস যোগ করা হচ্ছে…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ডিভাইস যোগ করা যায়নি। এটি দুটি কারণে হয়ে থাকে - QR কোডটি সঠিক নয় বা ডিভাইসটি একই নেটওয়ার্কে কানেক্ট করা নেই।"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP অ্যাড্রেস ও পোর্ট"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR কোড স্ক্যান করুন"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR কোড স্ক্যান করে ওয়াই-ফাই ব্যবহার করে ডিভাইস যোগ করুন"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ত্রুটি প্রতিবেদনের শর্টকাট"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"সমস্যার তথ্য ক্যাপচার করতে পাওয়ার মেনুতে একটি বোতাম দেখান"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"জাগিয়ে রাখুন"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন উপলভ্য থাকলে ব্যবহার করুন"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ডিবাগিং মঞ্জুর করবেন?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ডিবাগিং কেবলমাত্র বিকাশ করার উদ্দেশ্যে। আপনার কম্পিউটার এবং আপনার ডিভাইসের মধ্যে ডেটা অনুলিপি করতে এটি ব্যবহার করুন, বিজ্ঞপ্তি ছাড়া আপনার ডিভাইসে অ্যাপ্লিকেশানগুলি ইনস্টল করুন এবং ডেটা লগ পড়ুন।"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ওয়্যারলেস ডিবাগিং-এর অনুমতি দেবেন?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ওয়্যারলেস ডিবাগিং কেবলমাত্র বিকাশ করার উদ্দেশ্যে। আপনার কম্পিউটার এবং আপনার ডিভাইসের মধ্যে ডেটা কপি করতে এটি ব্যবহার করুন, বিজ্ঞপ্তি ছাড়া আপনার ডিভাইসে অ্যাপ ইনস্টল করুন এবং ডেটা লগ পড়ুন।"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"আপনি আগে যে সব কম্পিউটার USB ডিবাগিং এর অ্যাক্সেসের অনুমতি দিয়েছিলেন তা প্রত্যাহার করবেন?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"উন্নতি সেটিংসের অনুমতি দেবেন?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"এইসব সেটিংস কেবলমাত্র উন্নত করার উদ্দেশ্য। সেগুলি কারণে আপনার ডিভাইস ভেঙ্গে এবং অ্যাপ্লিকেশানগুলি ভালো ভাবে কাজ করা নাও কারতে পারে।"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"প্রোটানোম্যালি (লাল-সবুজ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ট্রিট্যানোম্যালি (নীল-হলুদ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"রঙ সংশোধন"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"রঙ অ্যাডজাস্ট করার সেটিংস, বর্ণান্ধতা আছে এমন ব্যক্তিদের আরও সঠিকভাবে রঙ দেখতে সাহায্য করে"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> এর দ্বারা ওভাররাইড করা হয়েছে"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"আর আনুমানিক <xliff:g id="TIME_REMAINING">%1$s</xliff:g> চলবে"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"আর <xliff:g id="THRESHOLD">%1$s</xliff:g>-এর কম চার্জ বাকি আছে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"আরও <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-এর বেশি চলবে (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"আরও <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-এর বেশি চলবে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ফোনটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ট্যাবলেটটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ফোনটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ট্যাবলেটটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ফোন শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ট্যাবলেটটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ফোনটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ট্যাবলেটটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ডিভাইসটি শীঘ্রই বন্ধ হয়ে যেতে পারে (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"সম্পূর্ণ চার্জ হতে <xliff:g id="TIME">%1$s</xliff:g> বাকি আছে"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>-এ সম্পূর্ণ চার্জ হয়ে যাবে"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"অজানা"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"চার্জ হচ্ছে"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"দ্রুত চার্জ হচ্ছে"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ধীরে চার্জ হচ্ছে"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"চার্জ হচ্ছে না"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"প্লাগ-ইন করা হয়েছে কিন্তু এখনই চার্জ করা যাবে না"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"পূর্ণ"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index c32df18..cb55c5d 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Otklanjanje grešaka putem uređaja spojenog na USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Način rada za uklanjanje grešaka kada je povezan USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Ukini odobrenja otklanjanja grešaka putem uređaja spojenog na USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bežično otklanjanje grešaka"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Način rada otklanjanja grešaka kada je WiFi mreža povezana"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Greška"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bežično otklanjanje grešaka"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Da vidite i koristite dostupne uređaje, uključite otklanjanje grešaka putem bežične veze"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Uparite uređaj pomoću QR koda"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Uparite nove uređaje pomoću skenera QR koda"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Uparite uređaj pomoću koda za uparivanje"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Uparite nove uređaje pomoću šestocifrenog koda"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Upareni uređaji"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Trenutno povezano"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalji o uređaju"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Zaboravi"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Otisak prsta uređaja: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Povezivanje nije uspjelo"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Provjerite je li uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povezan na odgovarajuću mrežu"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Uparite s uređajem"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kôd za uparivanje putem WiFi-ja"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Uparivanje nije uspjelo"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Provjerite je li uređaj povezan na istu mrežu."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Uparite uređaj putem WiFi-ja skeniranjem QR koda"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Uparivanje uređaja…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Uparivanje uređaja nije uspjelo. QR kȏd nije tačan ili uređaj nije povezan na istu mrežu."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i priključak"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skenirajte QR kôd"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparite uređaj putem WiFi-ja skeniranjem QR koda"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje grešaka, programer"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Prečica za izvještaj o greškama"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaz dugmeta za prijavu grešaka u meniju napajanja"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ne zaključavaj ekran"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Korištenje hardverskog ubrzavanja za povezivanje putem mobitela ako je dostupno"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Omogućiti otklanjanje grešaka putem uređaja spojenog na USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Otklanjanje grešaka putem uređaja spojenog na USB je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz zapisnika."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Omogućiti bežično otklanjanje grešaka?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bežično otklanjanje grešaka je namijenjeno samo u svrhe razvoja aplikacija. Koristite ga za kopiranje podataka između računara i uređaja, instaliranje aplikacija na uređaj bez obavještenja te čitanje podataka iz zapisnika."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Opozvati pristup otklanjanju grešaka putem uređaja spojenog na USB za sve računare koje ste prethodno ovlastili?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Dopustiti postavke za razvoj?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ove postavke su namijenjene samo za svrhe razvoja. Mogu izazvati pogrešno ponašanje uređaja i aplikacija na njemu."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno-zeleno)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo-žuto)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ispravka boje"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Ispravka boje pomaže daltonistima da preciznije vide boje"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Zamjenjuje <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Preostalo je još oko <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Preostalo je više od: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Uređaj će se uskoro isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Uređaj će se uskoro isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Uređaj će se uskoro isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo punjenje"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Priključen, trenutno se ne može puniti"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 813fff4..7ac03aa 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuració per USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mode de depuració quan l\'USB està connectat"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoca autoritzacions de depuració per USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuració sense fil"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode de depuració quan la Wi‑Fi està connectada"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuració sense fil"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Per veure i utilitzar els dispositius disponibles, activa la depuració sense fil"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincula el dispositiu amb un codi QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Vincula dispositius nous utilitzant l\'escàner de codis QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincula el dispositiu amb un codi de vinculació"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincula dispositius nous utilitzant un codi de sis dígits"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositius vinculats"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Connectat actualment"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Dades del dispositiu"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Oblida"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Empremta digital del dispositiu: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"No s\'ha pogut connectar"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Assegura\'t que <xliff:g id="DEVICE_NAME">%1$s</xliff:g> estigui connectat a la xarxa correcta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincular amb el dispositiu"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Codi de vinculació Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"No s\'ha pogut vincular"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Assegura\'t que el dispositiu estigui connectat a la mateixa xarxa."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Vincula el dispositiu per Wi‑Fi escanejant un codi QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"S\'està vinculant el dispositiu…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"No s\'ha pogut vincular el dispositiu. O bé el codi QR és incorrecte, o bé el dispositiu no està connectat a la mateixa xarxa."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adreça IP i port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escaneja un codi QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula el dispositiu per Wi‑Fi escanejant un codi QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depurar, desenvolupador"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Drecera per a informe d\'errors"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un botó al menú d\'engegada per crear un informe d\'errors"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Pantalla activa"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Fes servir l\'acceleració per maquinari per a compartició de xarxa, si està disponible"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Voleu permetre la depuració per USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"La depuració per USB només està indicada per a activitats de desenvolupament. Fes-la servir intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vols permetre la depuració sense fil?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"La depuració sense fil només està indicada per a activitats de desenvolupament. Fes-la servir per intercanviar dades entre l\'ordinador i el dispositiu, per instal·lar aplicacions al dispositiu sense rebre notificacions i per llegir dades de registre."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Vols revocar l\'accés a la depuració per USB dels ordinadors que has autoritzat anteriorment?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Vols permetre la conf. de desenvolupament?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Aquesta configuració només està prevista per a usos de desenvolupament. Pot fer que el dispositiu i que les aplicacions s\'interrompin o tinguin un comportament inadequat."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermell-verd)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (blau-groc)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correcció del color"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La correcció del color ajuda les persones daltòniques a veure colors més precisos"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"S\'ha substituït per <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant aproximat: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Temps restant inferior a <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Temps restant superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Temps restant superior a <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"És possible que el telèfon s\'apagui aviat"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"És possible que la tauleta s\'apagui aviat"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"És possible que el dispositiu s\'apagui aviat"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"És possible que el telèfon s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"És possible que la tauleta s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"És possible que el dispositiu s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"És possible que el telèfon s\'apagui aviat"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"És possible que la tauleta s\'apagui aviat"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"És possible que el dispositiu s\'apagui aviat"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"És possible que el telèfon s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"És possible que la tauleta s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"És possible que el dispositiu s\'apagui aviat (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> per completar la càrrega"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> per completar la càrrega"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconegut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"S\'està carregant"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregant ràpidament"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregant lentament"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"No s\'està carregant"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"El dispositiu està endollat però en aquests moments no es pot carregar"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index f116733..932051d 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Ladění přes USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Povolit režim ladění s připojeným zařízením USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Zrušit autorizace k ladění přes USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bezdrátové ladění"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Režim ladění při připojení k Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Chyba"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bezdrátové ladění"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Chcete-li zobrazit a použít dostupná zařízení, zapněte bezdrátové ladění"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Párovat zařízení pomocí QR kódu"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Párovat nová zařízení pomocí skenování QR kódu"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Párovat zařízení pomocí párovacího kódu"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Párovat nová zařízení pomocí šestimístného kódu"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Spárovaná zařízení"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Momentálně připojeno"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Podrobnosti o zařízení"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Zapomenout"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Otisk zařízení: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Připojení se nezdařilo"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Zkontrolujte, zda je zařízení <xliff:g id="DEVICE_NAME">%1$s</xliff:g> připojeno ke správné síti"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Spárování se zařízením"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Párovací kód Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Spárování se nezdařilo"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Zkontrolujte, zda je zařízení připojeno ke stejné síti."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Párovat zařízení přes Wi-Fi naskenováním QR kódu"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Párování zařízení…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Spárování zařízení se nezdařilo. Buď byl QR kód chybný, nebo zařízení není připojeno ke stejné síti."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa a port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Naskenování QR kódu"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Párovat zařízení přes Wi-Fi naskenováním QR kódu"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ladění, vývoj"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Zástupce hlášení chyb"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Zobrazit v hlavní nabídce tlačítko k vygenerování chybového hlášení"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Nevypínat obrazovku"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Pokud je k dispozici hardwarová akceleraci tetheringu, použít ji"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Povolit ladění přes USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ladění prostřednictvím rozhraní USB je určeno pouze pro účely vývoje. Použijte je ke kopírování dat mezi počítačem a zařízením, instalaci aplikací do zařízení bez upozornění a čtení dat protokolů."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Povolit bezdrátové ladění?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bezdrátové ladění je určeno pouze pro účely vývoje. Použijte jej ke kopírování dat mezi počítačem a zařízením, instalaci aplikací do zařízení bez upozornění a čtení dat protokolů."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Zrušit přístup k ladění přes USB ze všech počítačů, které jste v minulosti autorizovali?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Povolit nastavení pro vývojáře?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Tato nastavení jsou určena pouze pro vývojáře. Mohou způsobit rozbití nebo nesprávné fungování zařízení a nainstalovaných aplikací."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomálie (červená a zelená)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomálie (modrá a žlutá)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekce barev"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korekce barev pomáhá barvoslepým lidem vidět přesnější barvy"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Přepsáno nastavením <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zbývá asi <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zbývá méně než <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Zbývá více než <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon se brzy vypne"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet se brzy vypne"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Zařízení se brzy vypne"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Zařízení se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon se brzy vypne"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet se brzy vypne"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Zařízení se brzy vypne"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Zařízení se brzy vypne (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do nabití zbývá: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do nabití"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznámé"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíjí se"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rychlé nabíjení"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Pomalé nabíjení"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíjí se"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Zapojeno, ale nelze nabíjet"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index e3b96a4..20fbf94 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-fejlretning"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Fejlretningstilstand, når USB er tilsluttet"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Tilbagekald tilladelser for USB-fejlretning"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Trådløs fejlfinding"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Fejlfindingstilstand, når der er Wi-Fi-forbindelse"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Fejl"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Trådløs fejlfinding"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Du kan se og bruge tilgængelige enheder ved at aktivere trådløs fejlretning"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Dan par med en enhed ved hjælp af en QR-kode"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Dan par med nye enheder ved hjælp af QR-kodescanneren"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Dan par med en enhed ved hjælp af en parringskode"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Dan par med nye enheder ved hjælp af den sekscifrede kode"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Parrede enheder"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Forbundet lige nu"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Enhedsoplysninger"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Glem"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Fingeraftryk for enhed: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Forbindelsen mislykkedes"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Sørg for, at <xliff:g id="DEVICE_NAME">%1$s</xliff:g> har forbindelse til det rigtige netværk."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Dan par med enhed"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Parringskode til Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Parringen mislykkedes"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Sørg for, at enheden er forbundet til det samme netværk."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Dan par med en enhed via Wi-Fi ved at scanne en QR-kode"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Parrer enhed…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Enheden blev ikke parret. Det skyldes enten, at QR-koden var forkert, eller at enheden ikke er forbundet til det samme netværk."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adresse og port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR-kode"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Dan par med en enhed via Wi-Fi ved at scanne en QR-kode"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, fejlfinding, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Genvej til fejlrapportering"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Vis en knap til oprettelse af fejlrapporter i afbrydermenuen"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Lås ikke"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Brug hardwareacceleration ved netdeling, hvis det er muligt"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Vil du tillade USB-fejlretning?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-fejlretning er kun beregnet til udvikling og kan bruges til at kopiere data mellem din computer og enheden, installere apps på enheden uden notifikation og læse logdata."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vil du tillade trådløs fejlfinding?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Trådløs fejlretning er kun beregnet til udvikling og kan bruges til at kopiere data mellem din computer og enheden, installere apps på enheden uden notifikation og læse logdata."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Vil du ophæve adgangen til USB-fejlretning for alle computere, du tidligere har godkendt?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Vil du tillade udviklingsindstillinger?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Disse indstillinger er kun beregnet til brug i forbindelse med udvikling. De kan forårsage, at din enhed og dens apps går ned eller ikke fungerer korrekt."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopi (rød-grøn)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopi (blå-gul)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korriger farver"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Farvekorrigering gør det nemmere for farveblinde at se farver mere nøjagtigt"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tilsidesat af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ca. <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Der er mindre end <xliff:g id="THRESHOLD">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Der er mere end <xliff:g id="TIME_REMAINING">%1$s</xliff:g> tilbage"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefonen lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Denne tablet lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Enheden lukker muligvis snart ned"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefonen lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Denne tablet lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Enheden lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefonen lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Denne tablet lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Enheden lukker muligvis snart ned"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefonen lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tabletten lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Enheden lukker muligvis snart ned (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Opladet om <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – opladet om <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukendt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Oplader"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Oplader hurtigt"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Oplader langsomt"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Oplader ikke"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Enheden er tilsluttet en strømkilde. Det er ikke muligt at oplade på nuværende tidspunkt."</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Fuldt"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 1ddabcab..3d46649 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-Debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debugmodus bei Anschluss über USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB-Debugging-Autorisierungen aufheben"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Kabelloses Debugging"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debugging-Modus, wenn eine WLAN-Verbindung besteht"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Fehler"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Kabelloses Debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Aktiviere das kabellose Debugging, um verfügbare Geräte zu sehen und zu verwenden"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Gerät über einen QR-Code koppeln"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Neue Geräte über QR-Codescanner koppeln"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Gerät über einen Kopplungscode koppeln"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Neue Geräte mit sechsstelligem Code koppeln"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Gekoppelte Geräte"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Derzeit verbunden"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Gerätedetails"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Entfernen"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Fingerabdruck des Geräts: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Verbindung fehlgeschlagen"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Prüfe, ob <xliff:g id="DEVICE_NAME">%1$s</xliff:g> mit dem richtigen Netzwerk verbunden ist"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Mit einem Gerät koppeln"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"WLAN-Kopplungscode"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Kopplung fehlgeschlagen"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Prüfe, ob das Gerät mit demselben Netzwerk verbunden ist."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Scanne einen QR-Code, um ein Gerät über WLAN zu koppeln"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Gerät wird gekoppelt…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Das Gerät konnte nicht gekoppelt werden. Der QR-Code war nicht korrekt oder das Gerät ist nicht mit demselben Netzwerk verbunden."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-Adresse &amp; Port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-Code scannen"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Scanne einen QR-Code, um ein Gerät über WLAN zu koppeln"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, Debug, Dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Verknüpfung zu Fehlerbericht"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Im Menü \"Ein/Aus\" wird eine Option zum Erstellen eines Fehlerberichts angezeigt"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Aktiv lassen"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Falls verfügbar, Hardwarebeschleunigung für Tethering verwenden"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB-Debugging zulassen?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-Debugging ist nur für Entwicklungszwecke vorgesehen. Damit kannst du Daten zwischen deinem Computer und deinem Gerät kopieren, Apps auf deinem Gerät ohne Benachrichtigung installieren und Protokolldaten lesen."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Kabelloses Debugging zulassen?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Das kabellose Debugging ist nur für Entwicklungszwecke vorgesehen. Damit kannst du Daten zwischen deinem Computer und deinem Gerät kopieren, Apps auf deinem Gerät ohne Benachrichtigung installieren und Protokolldaten lesen."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Zugriff auf USB-Debugging für alle zuvor autorisierten Computer aufheben?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Entwicklungseinstellungen zulassen?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Diese Einstellungen sind ausschließlich für Entwicklungszwecke gedacht. Sie können dein Gerät und die darauf installierten Apps beschädigen oder zu unerwünschtem Verhalten führen."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (Rot-Grün-Sehschwäche)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (Blau-Gelb-Sehschwäche)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Farbkorrektur"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Die Farbkorrektur hilft farbenblinden Menschen, Farben besser zu erkennen"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Außer Kraft gesetzt von \"<xliff:g id="TITLE">%1$s</xliff:g>\""</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noch etwa <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Weniger als <xliff:g id="THRESHOLD">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mehr als <xliff:g id="TIME_REMAINING">%1$s</xliff:g> verbleibend"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Smartphone wird eventuell bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet wird eventuell bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Gerät wird eventuell bald ausgeschaltet"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Smartphone wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Gerät wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Smartphone wird eventuell bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet wird eventuell bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Gerät wird eventuell bald ausgeschaltet"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Smartphone wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Gerät wird eventuell bald ausgeschaltet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Noch <xliff:g id="TIME">%1$s</xliff:g> bis zur Aufladung"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> bis zur Aufladung"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unbekannt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Wird aufgeladen"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Schnelles Aufladen"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Langsames Aufladen"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Wird nicht geladen"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Angeschlossen, kann derzeit nicht geladen werden"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Voll"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index 3a97d5a..6bd8736 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Εντοπισμός σφαλμάτων USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Λειτουργία εντοπισμού σφαλμάτων όταν το USB είναι συνδεδεμένο"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Ανάκληση εξ/σεων εντ/σμού σφ/των USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Εντοπισμός σφαλμ. ασύρ. σύνδεσης"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Λειτουργία εντοπισμού σφαλμάτων όταν το Wi‑Fi είναι συνδεδεμένο"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Σφάλμα"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Εντοπισμός σφαλμ. ασύρ. σύνδεσης"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Για να δείτε και να χρησιμοποιήσετε τις διαθέσιμες συσκευές, ενεργοποιήστε τον εντοπισμό σφαλμάτων ασύρματης σύνδεσης"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Σύζευξη συσκευής με κωδικό QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Σύζευξη νέων συσκευών με τη χρήση σαρωτή κωδικών QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Σύζευξη συσκευής με κωδικό σύζευξης"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Σύζευξη νέων συσκευών με τη χρήση εξαψήφιου κωδικού"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Συσκευές σε σύζευξη"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Συνδεδεμένες αυτήν τη στιγμή"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Λεπτομέρειες συσκευής"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Διαγραφή"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Μοναδικό χαρακτηριστικό συσκευής: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Η σύνδεση δεν ήταν επιτυχής"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Βεβαιωθείτε ότι η συσκευή <xliff:g id="DEVICE_NAME">%1$s</xliff:g> είναι συνδεδεμένη στο σωστό δίκτυο"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Σύζευξη με συσκευή"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Κωδικός σύζευξης Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Η σύζευξη δεν ήταν επιτυχής"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Βεβαιωθείτε ότι η συσκευή είναι συνδεδεμένη στο ίδιο δίκτυο."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Σύζευξη συσκευής μέσω Wi‑Fi με τη σάρωση ενός κωδικού QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Σύζευξη συσκευής…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Η σύζευξη της συσκευής απέτυχε. Ο κωδικός QR ήταν λανθασμένος ή η συσκευή δεν είναι συνδεδεμένη στο ίδιο δίκτυο."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Διεύθυνση IP και θύρα"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Σάρωση κωδικού QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Σύζευξη συσκευής μέσω Wi‑Fi με τη σάρωση ενός κωδικού QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, εντοπισμός σφαλμάτων, προγραμματιστής"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Συντόμευση αναφοράς σφαλμάτων"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Εμφάνιση κουμπιού στο μενού ενεργοποίησης για τη λήψη αναφοράς σφαλμάτων"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Παραμονή σε λειτουργία"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Χρήση της σύνδεσης επιτάχυνσης υλικού εάν υπάρχει"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Να επιτρέπεται ο εντοπισμός σφαλμάτων USB;"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ο εντοπισμός σφαλμάτων USB προορίζεται μόνο για σκοπούς προγραμματισμού. Χρησιμοποιήστε τον για αντιγραφή δεδομένων μεταξύ του υπολογιστή και της συσκευής σας, για την εγκατάσταση εφαρμογών στη συσκευή σας χωρίς προειδοποίηση και για την ανάγνωση δεδομένων καταγραφής."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Να επιτρέπεται ο εντοπισμός σφαλμάτων ασύρματης σύνδεσης;"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Ο εντοπισμός σφαλμάτων ασύρματης σύνδεσης προορίζεται μόνο για σκοπούς προγραμματισμού. Χρησιμοποιήστε τον για αντιγραφή δεδομένων μεταξύ του υπολογιστή και της συσκευής σας, για την εγκατάσταση εφαρμογών στη συσκευή σας χωρίς ειδοποίηση και για την ανάγνωση δεδομένων καταγραφής."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Ανάκληση πρόσβασης στον εντοπισμό σφαλμάτων USB από όλους τους υπολογιστές για τους οποίους είχατε εξουσιοδότηση στο παρελθόν;"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Να επιτρέπεται η χρήση των ρυθμίσεων ανάπτυξης;"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Αυτές οι ρυθμίσεις προορίζονται για χρήση κατά την ανάπτυξη. Μπορούν να προκαλέσουν προβλήματα στη λειτουργία της συσκευής και των εφαρμογών σας."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Πρωτανοπία (κόκκινο-πράσινο)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Τριτανοπία (μπλε-κίτρινο)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Διόρθωση χρωμάτων"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Η διόρθωση χρωμάτων βοηθάει τα άτομα με αχρωματοψία να βλέπουν τα χρώματα με μεγαλύτερη ακρίβεια"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Αντικαταστάθηκε από <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Απομένει/ουν περίπου <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Απομένει/ουν λιγότερo/α από <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Απομένουν περισσότερα/ες από <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Το tablet μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Η συσκευή μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Το tablet μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Η συσκευή μπορεί να απενεργοποιηθεί σύντομα"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Το τηλέφωνο μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Το tablet μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Η συσκευή μπορεί να απενεργοποιηθεί σύντομα (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Απομένουν <xliff:g id="TIME">%1$s</xliff:g> για ολοκλήρωση της φόρτισης"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> για την ολοκλήρωση της φόρτισης"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Άγνωστο"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Φόρτιση"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ταχεία φόρτιση"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Αργή φόρτιση"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Δεν φορτίζει"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Συνδέθηκε, δεν είναι δυνατή η φόρτιση αυτήν τη στιγμή"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Πλήρης"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index ec0a129..810f81e 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode when USB is connected"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorisations"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless debugging"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode when Wi‑Fi is connected"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Wireless debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"To see and use available devices, turn on wireless debugging"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Pair device with QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Pair new devices using QR code scanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pair device with pairing code"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six-digit code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Paired devices"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Currently connected"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Device details"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Forget"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Device fingerprint: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connection unsuccessful"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure that <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Pair with device"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi pairing code"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pairing unsuccessful"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure that the device is connected to the same network."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Stay awake"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Use tethering hardware acceleration if available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Allow USB debugging?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Allow wireless debugging?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Allow development settings?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Colour correction helps people with colour blindness see more accurate colours"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Device may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Phone may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Phone may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Device may shut down soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Phone may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Device may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Plugged in, can\'t charge at the moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index ec0a129..810f81e 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode when USB is connected"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorisations"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless debugging"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode when Wi‑Fi is connected"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Wireless debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"To see and use available devices, turn on wireless debugging"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Pair device with QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Pair new devices using QR code scanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pair device with pairing code"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six-digit code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Paired devices"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Currently connected"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Device details"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Forget"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Device fingerprint: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connection unsuccessful"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure that <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Pair with device"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi pairing code"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pairing unsuccessful"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure that the device is connected to the same network."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Stay awake"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Use tethering hardware acceleration if available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Allow USB debugging?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Allow wireless debugging?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Allow development settings?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Colour correction helps people with colour blindness see more accurate colours"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Device may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Phone may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Phone may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Device may shut down soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Phone may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Device may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Plugged in, can\'t charge at the moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index ec0a129..810f81e 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode when USB is connected"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorisations"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless debugging"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode when Wi‑Fi is connected"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Wireless debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"To see and use available devices, turn on wireless debugging"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Pair device with QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Pair new devices using QR code scanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pair device with pairing code"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six-digit code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Paired devices"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Currently connected"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Device details"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Forget"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Device fingerprint: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connection unsuccessful"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure that <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Pair with device"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi pairing code"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pairing unsuccessful"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure that the device is connected to the same network."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Stay awake"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Use tethering hardware acceleration if available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Allow USB debugging?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Allow wireless debugging?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Allow development settings?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Colour correction helps people with colour blindness see more accurate colours"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Device may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Phone may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Phone may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Device may shut down soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Phone may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Device may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Plugged in, can\'t charge at the moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index ec0a129..810f81e 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB debugging"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode when USB is connected"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoke USB debugging authorisations"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless debugging"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode when Wi‑Fi is connected"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Wireless debugging"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"To see and use available devices, turn on wireless debugging"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Pair device with QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Pair new devices using QR code scanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pair device with pairing code"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Pair new devices using six-digit code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Paired devices"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Currently connected"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Device details"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Forget"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Device fingerprint: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connection unsuccessful"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Make sure that <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is connected to the correct network"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Pair with device"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi pairing code"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pairing unsuccessful"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Make sure that the device is connected to the same network."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pairing device…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address &amp; port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scan QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Pair device over Wi‑Fi by scanning a QR code"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Bug report shortcut"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Show a button in the power menu for taking a bug report"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Stay awake"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Use tethering hardware acceleration if available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Allow USB debugging?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification and read log data."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Allow wireless debugging?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revoke access to USB debugging from all computers you\'ve previously authorised?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Allow development settings?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (red-green)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (blue-yellow)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Colour correction"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Colour correction helps people with colour blindness see more accurate colours"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overridden by <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"About <xliff:g id="TIME_REMAINING">%1$s</xliff:g> left"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Less than <xliff:g id="THRESHOLD">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"More than <xliff:g id="TIME_REMAINING">%1$s</xliff:g> remaining"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Phone may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet may shutdown soon"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Device may shutdown soon"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Phone may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Device may shutdown soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Phone may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet may shut down soon"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Device may shut down soon"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Phone may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Device may shut down soon (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> left until charged"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> until charged"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Unknown"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charging"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charging rapidly"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charging slowly"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Not charging"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Plugged in, can\'t charge at the moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Full"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 3b286f7..d142c0a 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‏‎‎‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‎‎‎‏‎‎‏‏‎‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎USB debugging‎‏‎‎‏‎"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‎‎‏‏‏‎‏‏‎‏‏‎‎‎Debug mode when USB is connected‎‏‎‎‏‎"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‏‏‎‎‎‏‏‎‎‎‏‏‎‎‏‎‎‏‎‏‎‎‏‏‎‎‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‏‏‏‏‏‎‏‎Revoke USB debugging authorizations‎‏‎‎‏‎"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‎‎‏‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‏‏‏‏‎‎‏‎‏‎‎Wireless debugging‎‏‎‎‏‎"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‏‏‎‎‏‏‎‏‎‏‎‏‎‎‎‎‎‎‏‏‎‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎Debug mode when Wi‑Fi is connected‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎Error‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‎‏‎‎‎‎‎‏‏‏‏‎‎‎‏‏‏‎‏‎‏‎‏‏‏‎‎‏‎‏‎Wireless debugging‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‎‏‏‏‏‎‎‏‏‎‏‎‎‎‎‏‎‎To see and use available devices, turn on wireless debugging‎‏‎‎‏‎"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‏‎‎‎‏‏‏‎‏‎‎‎‏‏‎‏‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‏‎‏‏‎‏‎‎Pair device with QR code‎‏‎‎‏‎"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‏‎‎‏‏‎‎‏‎‎‎‏‏‏‎‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‎‎Pair new devices using QR code Scanner‎‏‎‎‏‎"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‎‏‎‏‎‎‏‏‏‎‏‏‏‏‎‏‏‏‏‎‎‎‎Pair device with pairing code‎‏‎‎‏‎"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‏‏‎‏‎‎‎‎‏‎‎‎‎‏‎‎‎‏‏‏‏‏‏‎‎‎‎‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‎‏‏‏‏‏‎‎‎‎‎‏‎Pair new devices using six digit code‎‏‎‎‏‎"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‎‎‎‏‏‏‏‏‎‎‏‏‏‏‎‏‎‎‏‎‏‎‏‎‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‏‏‏‎‏‎‎‏‎‏‎‎‏‎‎‏‎‎Paired devices‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‎‎‏‎‎‎‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‎‎‏‎Currently connected‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‎‏‏‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‏‏‎‎‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎Device details‎‏‎‎‏‎"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‏‎‎‏‎‏‎‎‏‏‎‏‎‏‏‎‎‎‏‎‎‏‏‎‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎Forget‎‏‎‎‏‎"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‏‏‎‎‎‎‎‎‏‎‏‏‏‎‏‎‎‎‏‎‎‎‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‏‎‏‎‏‎‎‏‏‎‎‏‎‏‎‏‏‏‏‎‏‎‏‎Device fingerprint: ‎‏‎‎‏‏‎<xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‏‎‏‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‎‎‏‎‏‏‎‏‏‎‎‏‏‎‎Connection unsuccessful‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‏‏‏‎‏‎‎‏‎‎‎‏‎‎‏‏‎‎‏‎Make sure ‎‏‎‎‏‏‎<xliff:g id="DEVICE_NAME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ is connected to the correct network‎‏‎‎‏‎"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‏‏‏‎‎‏‎‎‎‏‏‎‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‎‎‏‎‏‏‎‏‎‏‏‎‏‎‎‎‏‎‎Pair with device‎‏‎‎‏‎"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‏‎‎‏‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‎‏‏‎‏‎‏‏‎Wi‑Fi pairing code‎‏‎‎‏‎"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎‏‏‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‎‏‏‎‏‎‏‏‏‎Pairing unsuccessful‎‏‎‎‏‎"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‏‏‎‎‎Make sure the device is connected to the same network.‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‏‎‏‏‏‏‎‎‎‏‎‏‏‏‏‎‏‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‏‎‎‏‏‏‏‎‏‎Pair device over Wi‑Fi by scanning a QR code‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‎‎‎‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‏‏‏‎‎‎‏‏‏‏‎‎‎‏‎‏‏‏‎Pairing device…‎‏‎‎‏‎"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‎‏‎‎‎‎‏‎‏‎‏‎‏‎‎‎‏‏‏‎‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‏‏‏‏‏‏‎‏‏‎‏‎‏‎‎‎Failed to pair the device. Either the QR code was incorrect, or the device is not connected to the same network.‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‎‏‏‎‎‎‏‎‏‎‏‏‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‎‎‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎IP address &amp; Port‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‎‏‏‏‎‏‎‏‏‎‎‏‎‎‏‏‎Scan QR code‎‏‎‎‏‎"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‎‎‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‎‎‏‎‏‏‏‎‏‏‏‎‎‏‏‎Pair device over Wi‑Fi by scanning a QR Code‎‏‎‎‏‎"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‎‎‏‏‎‏‏‏‎‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‏‏‏‏‏‎‏‏‎‏‎‎‎‎adb, debug, dev‎‏‎‎‏‎"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‏‏‎‏‎‎‎‎‎‏‏‏‎‎‎‏‏‎‏‏‎‏‏‎‏‏‏‎‏‏‎‎‎‏‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‏‎Bug report shortcut‎‏‎‎‏‎"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‏‎‏‎‏‎‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‏‏‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‏‏‏‏‏‎Show a button in the power menu for taking a bug report‎‏‎‎‏‎"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‏‏‏‏‎‎‏‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎‎‏‎‏‏‎‏‎‎‏‏‏‏‎‎‎‎‏‎‏‎‎‏‏‏‎‏‏‎‎Stay awake‎‏‎‎‏‎"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‎‎‎‏‏‏‏‏‏‎‎‏‎‎‎‏‏‏‏‏‏‏‎‏‏‏‏‏‏‎‏‎‏‎‏‏‎‎‏‏‎‎‏‏‎‎‏‎‏‎‏‎‏‎Use tethering hardware acceleration if available‎‏‎‎‏‎"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‏‏‎‏‎‏‎‏‎‎‎‏‏‎‏‏‏‏‎‎‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‎‏‏‏‏‎‎‎‎‎‎Allow USB debugging?‎‏‎‎‏‎"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‎‏‎‎‎‎‏‎‎‏‏‏‎‏‎‎‎‎‏‎‎‎‎‎‎‏‏‎‏‎‏‎‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‏‎‎‏‏‏‎‎‏‎‏‎USB debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data.‎‏‎‎‏‎"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‏‎‎‏‏‎‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‏‎‏‏‏‏‏‏‎‎‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‎‎‏‎Allow wireless debugging?‎‏‎‎‏‎"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‏‏‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‎‏‎‏‏‎‏‎‎‏‏‎‏‏‎‎‏‏‏‏‏‏‏‏‏‎‎‎‎‎‏‏‎‏‎‎‎Wireless debugging is intended for development purposes only. Use it to copy data between your computer and your device, install apps on your device without notification, and read log data.‎‏‎‎‏‎"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‎‎‏‎‎‏‏‎‎‏‎‎‏‏‎‏‏‎‏‎‏‎‎‏‎‏‏‎‏‎‎‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‏‏‎‎‏‎‎‎Revoke access to USB debugging from all computers you’ve previously authorized?‎‏‎‎‏‎"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‎‏‎‎‏‎‎‎‏‏‎‎‏‏‎‏‎‏‎‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‎‎‏‎Allow development settings?‎‏‎‎‏‎"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‏‎‏‎‎‎‏‎‎‎These settings are intended for development use only. They can cause your device and the applications on it to break or misbehave.‎‏‎‎‏‎"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‎‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‎‏‎‏‎‏‎‎‎‎‎‏‏‏‎‎‏‏‏‎‎‎‎Protanomaly (red-green)‎‏‎‎‏‎"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‏‏‎‎‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‏‏‎‎‏‎‏‎‏‎‎‎‏‎‏‎‏‏‎‏‎‏‎‏‏‎‏‎‏‏‎Tritanomaly (blue-yellow)‎‏‎‎‏‎"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‏‎‏‏‎‏‎‏‏‎‎‎‏‎‏‏‎‎‏‏‎‎‏‏‏‎‏‎‎‎‏‎‏‏‎‎Color correction‎‏‎‎‏‎"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‎‏‎‏‎‎‎Color correction helps people with colorblindness see more accurate colors‎‏‎‎‏‎"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‎‏‎‏‎‏‎‏‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‎‎‏‎‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎Overridden by ‎‏‎‎‏‏‎<xliff:g id="TITLE">%1$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‎‎‎‏‏‎‎‏‏‏‎‎‎‏‏‏‎‎‏‏‎‎‏‎‎‏‏‎‎‏‏‎‏‎‎‎‎‏‏‏‎‏‎‎‏‎‎‏‏‎<xliff:g id="PERCENTAGE">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME_STRING">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‎‏‎‏‏‎‎‎‎‎‏‎‏‎‏‎‏‎‏‎‏‏‎‎‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‏‎‏‏‎‏‎‎‏‏‏‎About ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left‎‏‎‎‏‎"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‏‎‎‏‎‎‏‎‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‏‎‎‎‏‎‏‎‎‎‎‎‏‎‏‎‎‏‎‎‏‏‏‎‏‎‎‎‏‏‎‎‏‎‏‎‎‎Less than ‎‏‎‎‏‏‎<xliff:g id="THRESHOLD">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‎‏‎‏‏‏‎‏‎‏‏‎‏‏‎‏‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎‏‎‎‎‏‏‏‎‏‎‎‎‎‎‎‎‎‎More than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%2$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‏‎‏‏‎‎‎‏‏‏‎‏‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‎‏‏‎‎‏‏‏‎‏‎‎‎‎‎More than ‎‏‎‎‏‏‎<xliff:g id="TIME_REMAINING">%1$s</xliff:g>‎‏‎‎‏‏‏‎ remaining‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‎‏‎‏‏‏‏‎‏‎‎‏‏‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‏‎‎‏‎‏‎‏‎Phone may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‏‏‏‏‎‏‎‎‏‏‎‏‎‎‎‎‎‎‏‎‎‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‎‎‎Tablet may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‏‎‎‏‏‎‏‏‏‏‏‏‏‎‏‎‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‎‏‎‎Device may shutdown soon‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‏‎‏‏‎‎‎‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‎‏‎‏‎‎‏‏‎‎‏‎‏‎‎‎‎‎‏‏‏‏‏‎‎‏‏‎‏‎Phone may shutdown soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‏‎‏‎‎‏‎‏‎‎‎‎‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎‎‏‏‏‏‏‎‏‎‏‏‎‏‏‎‎‏‏‏‏‏‎‎‎‏‎Tablet may shutdown soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‏‏‎‏‎‏‎‏‏‏‏‎‎‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‎‎‎‏‎‏‏‎‎‎‏‏‏‎‏‏‏‎‏‏‎‏‎‎Device may shutdown soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‏‎‎‏‎‎‏‏‏‎‏‎‏‎‏‎‎‏‎‎‏‎‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‎‎‏‎‎‎‏‏‎‎Phone may shut down soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‎‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‎‎‏‏‎‎‎‏‏‏‏‏‏‎‏‏‎‎‏‎‎‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‎‎‎Tablet may shut down soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‎‏‏‏‎‏‏‎‏‏‎‏‏‎‏‏‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‎‎‎‏‎‏‎‏‎‎‏‏‎‎‎‏‏‎‎‏‎‎‎‏‎‎‏‏‏‎‎Device may shut down soon‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‎‏‏‏‎‏‏‏‏‏‏‎‎‏‎‎‎‎‏‎‏‎‎‎‏‎‎‎‎‎‏‎‎‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‏‏‎‏‏‏‎Phone may shut down soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‏‏‎‏‎‎‎‏‏‏‏‎‏‏‎‎‏‎‎‎‎‎‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‎‏‎‏‎‎‎‏‏‎‏‏‎‏‏‏‏‎Tablet may shut down soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‎‏‎‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‏‎‎‎‎‎‎‏‏‏‎‎‏‏‎‎‏‏‏‏‎‏‎‏‎‏‎‎‏‏‎‎‏‎‎Device may shut down soon (‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎)‎‏‎‎‏‎"</string>
     <string name="power_charging" msgid="6727132649743436802">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‏‎‏‎‏‎‏‏‎‏‏‏‎‎‏‎‎‏‏‏‎‎‎‎‎‎‎‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‏‏‏‎‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="STATE">%2$s</xliff:g>‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‏‎‎‎‏‎‎‏‎‏‎‎‎‎‏‏‎‏‎‏‏‏‏‎‏‏‏‎‏‏‏‏‎‏‎‎‎‏‎‎‏‏‎<xliff:g id="TIME">%1$s</xliff:g>‎‏‎‎‏‏‏‎ left until charged‎‏‎‎‏‎"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‏‏‏‎‏‏‎‎‎‎‎‏‎‏‏‏‎‎‏‏‎‏‏‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‏‎‏‏‏‏‎‎‏‎‎‏‎‎‏‏‎<xliff:g id="LEVEL">%1$s</xliff:g>‎‏‎‎‏‏‏‎ - ‎‏‎‎‏‏‎<xliff:g id="TIME">%2$s</xliff:g>‎‏‎‎‏‏‏‎ until charged‎‏‎‎‏‎"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‎‏‎‏‏‏‎‏‏‏‎‏‎‎‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‎‏‎‎‎‎‏‎‏‎‏‏‏‎‏‏‏‏‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎Unknown‎‏‎‎‏‎"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‏‎‏‏‎‎‏‎‏‎‏‏‏‎‏‏‏‎‎‏‎‎‎‏‏‏‎‎‎‏‎‏‏‎‏‎‏‎‎‎‎‎‏‏‎‎‏‏‎‏‏‎‎‏‏‎‏‎Charging‎‏‎‎‏‎"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‏‏‏‎‏‏‎‎‏‏‏‏‎‎‏‏‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‏‏‏‏‏‏‎‏‎‎‎‏‎‎‏‎‏‏‎‏‏‎‎‎‎‏‎‏‎Charging rapidly‎‏‎‎‏‎"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‏‏‎‎‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‏‏‎‎‏‎‏‏‏‎‎‏‏‎‏‎‎‎‏‏‎‎‏‎‏‏‎‎‎‎‏‏‏‏‎Charging slowly‎‏‎‎‏‎"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‏‎‎‎‎‎‎‏‏‏‎‎‎‏‎‎‎‎‏‎‎‎‏‎‎‎‏‎‏‎‏‎‎‏‎‏‏‎‎‎‎‏‏‎‎‏‎‎‎‎‎‏‎‏‎Not charging‎‏‎‎‏‎"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‏‎‏‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‎‎‏‏‏‎‏‎‏‏‎‎‏‏‏‎‏‏‏‏‎‏‎‏‎‎‎‏‏‏‎‏‏‎Plugged in, can\'t charge right now‎‏‎‎‏‎"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‎‏‏‎‏‎‏‎‎‏‎‏‎‎‏‏‏‎‏‎‎‏‏‏‎‏‏‎‎‏‎‎‏‎‎‎‏‎‏‎‏‏‎‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎‎Full‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 966f2f2..8b99f72 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -66,7 +66,7 @@
     <string name="bluetooth_disconnected" msgid="7739366554710388701">"Desconectado"</string>
     <string name="bluetooth_disconnecting" msgid="7638892134401574338">"Desconectando…"</string>
     <string name="bluetooth_connecting" msgid="5871702668260192755">"Conectando…"</string>
-    <string name="bluetooth_connected" msgid="8065345572198502293">"Conectado a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_connected" msgid="8065345572198502293">"Conectado<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_pairing" msgid="4269046942588193600">"Vinculando..."</string>
     <string name="bluetooth_connected_no_headset" msgid="2224101138659967604">"Conectado (sin teléfono) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"Conectado (sin archivos multimedia) a <xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
@@ -172,7 +172,7 @@
     <string name="tts_engine_network_required" msgid="8722087649733906851">"Este idioma necesita una conexión de red en funcionamiento para la salida de texto a voz."</string>
     <string name="tts_default_sample_string" msgid="6388016028292967973">"Ejemplo de síntesis de voz"</string>
     <string name="tts_status_title" msgid="8190784181389278640">"Estado del idioma predeterminado"</string>
-    <string name="tts_status_ok" msgid="8583076006537547379">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> es totalmente compatible."</string>
+    <string name="tts_status_ok" msgid="8583076006537547379">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> es totalmente compatible"</string>
     <string name="tts_status_requires_network" msgid="8327617638884678896">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> requiere una conexión de red."</string>
     <string name="tts_status_not_supported" msgid="2702997696245523743">"El idioma <xliff:g id="LOCALE">%1$s</xliff:g> no es compatible."</string>
     <string name="tts_status_checking" msgid="8026559918948285013">"Comprobando…"</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuración por USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuración cuando se conecta el USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revocar autorizaciones de depur. USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuración inalámbrica"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuración cuando la conexión Wi‑Fi está activada"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuración inalámbrica"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver y usar los dispositivos disponibles, activa la depuración inalámbrica"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular dispositivo mediante código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Vincular dispositivos nuevos mediante escáner de código QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo mediante código de sincroniz."</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincular dispositivos nuevos mediante código de seis dígitos"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectado actualmente"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalles del dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Olvidar"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Huellas digitales del dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Error de conexión"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asegúrate de que <xliff:g id="DEVICE_NAME">%1$s</xliff:g> esté conectado a la red correcta."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincular con dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de sincroniz. de Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Error de sincronización"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Asegúrate de que el dispositivo esté conectado a la misma red."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Escanea un código QR para vincular el dispositivo mediante Wi‑Fi"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Vinculando dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Error al vincular el dispositivo. El código QR era incorrecto o el dispositivo no está conectado a la misma red."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Dirección IP y puerto"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Escanea un código QR para vincular el dispositivo mediante Wi‑Fi"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Acceso directo para informes de errores"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar un botón en el menú de encendido para realizar un informe de errores"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer activo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar la aceleración de hardware de conexión mediante dispositivo móvil si está disponible"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"¿Permitir depuración por USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"La depuración por USB solo está indicada para actividades de programación. Úsala para copiar datos entre tu computadora y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"¿Permitir la depuración inalámbrica?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"La depuración inalámbrica solo está indicada para actividades de desarrollo. Úsala para copiar datos entre la computadora y el dispositivo, instalar apps en el dispositivo sin recibir notificaciones y leer datos de registro."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"¿Quieres revocar el acceso a la depuración por USB desde todas la computadoras que autorizaste hasta ahora?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"¿Permitir configuración de desarrollo?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Estos parámetros de configuración están destinados únicamente a los programadores. Pueden hacer que el dispositivo o sus aplicaciones no funcionen correctamente."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La corrección de color ayuda a las personas daltónicas a ver mejor los colores"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Reemplazado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante: aproximadamente <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tiempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Es posible que pronto se apague el teléfono"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Es posible que pronto se apague la tablet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Es posible que pronto se apague el dispositivo"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Es posible que pronto se apague el teléfono (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Es posible que pronto se apague la tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Es posible que pronto se apague el dispositivo (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Es posible que pronto se apague el teléfono"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Es posible que pronto se apague la tablet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Es posible que pronto se apague el dispositivo"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Es posible que pronto se apague el teléfono (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Es posible que pronto se apague la tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Es posible que pronto se apague el dispositivo (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar la carga"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> para completar la carga"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carga rápida"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carga lenta"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando."</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Conectado. No se puede cargar en este momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Cargado"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 1198722..5c8efc5 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -190,7 +190,7 @@
     <item msgid="5664310435707146591">"Más rápida"</item>
     <item msgid="5491266922147715962">"Muy rápida"</item>
     <item msgid="7659240015901486196">"Superrápida"</item>
-    <item msgid="7147051179282410945">"Hiperrrápida"</item>
+    <item msgid="7147051179282410945">"Hiperrápida"</item>
     <item msgid="581904787661470707">"La más rápida"</item>
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"Seleccionar perfil"</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuración por USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Activar el modo de depuración cuando el dispositivo esté conectado por USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revocar autorizaciones de depuración USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuración inalámbrica"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Activar el modo Depuración cuando tenga conexión Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuración inalámbrica"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver y utilizar los dispositivos disponibles, activa la depuración inalámbrica"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular dispositivo con código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Vincula nuevos dispositivos con el escáner de códigos QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular dispositivo con código de sincronización"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincula nuevos dispositivos con un código de seis dígitos"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectados actualmente"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Datos del dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Olvidar"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Huella digital del dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"No se ha podido conectar"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Comprueba que has conectado <xliff:g id="DEVICE_NAME">%1$s</xliff:g> a la red correcta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Vincular con dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de sincronización de Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"No se ha podido vincular"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Comprueba que el dispositivo está conectado a la misma red."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Vincula un dispositivo a través de Wi‑Fi con un código QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Vinculando dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"No se ha podido vincular el dispositivo. El código QR no era correcto o el dispositivo no estaba conectado a la misma red."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Dirección IP y puerto"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula un dispositivo a través de Wi‑Fi con un código QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depuración, desarrollo"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atajo a informe de errores"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar un botón en el menú de encendido para crear un informe de errores"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Pantalla siempre encendida al cargar"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar la conexión compartida con aceleración por hardware si está disponible"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"¿Permitir depuración por USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"La depuración por USB solo está indicada para actividades de desarrollo. Puedes utilizarla para intercambiar datos entre el ordenador y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"¿Permitir la depuración inalámbrica?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"La depuración inalámbrica solo está pensada para llevar a cabo actividades de desarrollo. Puedes utilizarla para intercambiar datos entre el ordenador y el dispositivo, para instalar aplicaciones en el dispositivo sin recibir notificaciones y para leer datos de registro."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"¿Quieres revocar el acceso a la depuración por USB de todos los ordenadores que has autorizado?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"¿Permitir ajustes de desarrollo?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Estos ajustes están destinados únicamente a los desarrolladores. Pueden provocar que el dispositivo o las aplicaciones no funcionen correctamente."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (rojo-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarillo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección de color"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La corrección de color ayuda a que los usuarios con daltonismo vean colores similares a los que perciben otras personas"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>: <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tiempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Queda menos del <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Queda más del <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Tiempo restante: más de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Es posible que el teléfono se apague pronto"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Es posible que el tablet se apague pronto"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Es posible que el dispositivo se apague pronto"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Es posible que el teléfono se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Es posible que el tablet se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Es posible que el dispositivo se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Es posible que el teléfono se apague pronto"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Es posible que el tablet se apague pronto"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Es posible que el dispositivo se apague pronto"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Es posible que el teléfono se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Es posible que el tablet se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Es posible que el dispositivo se apague pronto (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> hasta que termine de cargarse"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> (<xliff:g id="TIME">%2$s</xliff:g> hasta que termine de cargarse)"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconocido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rápidamente"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Cargando lentamente"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"No se está cargando"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Se ha conectado, pero no se puede cargar en este momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index 9be72f9..7597476 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB silumine"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Silumisrežiim, kui USB on ühendatud"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Tühista USB silumisvolitused"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Juhtmevaba silumine"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Silumisrežiim, kui WiFi-ühendus on olemas"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Viga"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Juhtmevaba silumine"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Saadaolevate seadmete nägemiseks ja kasutamiseks lülitage sisse juhtmevaba silumine"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Seadme sidumine QR-koodiga"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Uute seadmete sidumine QR-koodi skanneriga"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Seadme sidumine sidumiskoodiga"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Uute seadmete sidumine kuuekohalise koodiga"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Seotud seadmed"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Praegu ühendatud"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Seadme üksikasjad"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Unusta"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Seadme sõrmejälg: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Ühendamine ebaõnnestus"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Veenduge, et seade <xliff:g id="DEVICE_NAME">%1$s</xliff:g> oleks ühendatud samasse võrku"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sidumine seadmega"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"WiFi sidumiskood"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Sidumine ei õnnestunud"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Veenduge, et seade oleks ühendatud samasse võrku."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Siduge seade WiFi kaudu, skannides QR-koodi"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Seadme sidumine …"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Seadme sidumine ebaõnnestus. QR-kood oli vale või seade ei ole ühendatud samasse võrku."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-aadress ja port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-koodi skannimine"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Siduge seade WiFi kaudu, skannides QR-koodi"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, silumine, arendus"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Veaaruande otsetee"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Kuva toitemenüüs veaaruande jäädvustamise nupp"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Jää sisselülitatuks"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Kasuta võimalusel jagamise riistvaralist kiirendust"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Luban USB silumise?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-silumine on mõeldud ainult arendamiseks. Kasutage seda andmete kopeerimiseks oma arvuti ja seadme vahel, seadmesse rakenduste installimiseks ilma teatisteta ning logiandmete lugemiseks."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Kas lubada juhtmevaba silumine?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Juhtmevaba silumine on mõeldud ainult arendamiseks. Kasutage seda andmete kopeerimiseks oma arvuti ja seadme vahel, seadmesse rakenduste installimiseks ilma märguandeta ning logiandmete lugemiseks."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Kas tühistada juurdepääs USB silumisele kõikides arvutites, mille olete varem volitanud?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Kas lubada arendajaseaded?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Need seaded on mõeldud ainult arendajatele. Need võivad põhjustada seadme ja seadmes olevate rakenduste rikkeid või valesti toimimist."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaalia (punane-roheline)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaalia (sinine-kollane)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värvide korrigeerimine"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Värviparanduse funktsioon aitab värvipimedatel värve täpsemini näha"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Alistas <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ligikaudu <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäänud"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Jäänud on alla <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Jäänud on üle <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tahvelarvuti võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Seade võib peagi välja lülituda"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tahvelarvuti võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Seade võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tahvelarvuti võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Seade võib peagi välja lülituda"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tahvelarvuti võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Seade võib peagi välja lülituda (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Täislaadimiseni on jäänud <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täislaadimiseni"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tundmatu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laadimine"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Kiiresti laadimine"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Aeglaselt laadimine"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei lae"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Vooluvõrgus, praegu ei saa laadida"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Täis"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index d0c6c52..fd2635a 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -124,7 +124,7 @@
     <string name="bluetooth_talkback_headset" msgid="3406852564400882682">"Mikrofonodun entzungailua"</string>
     <string name="bluetooth_talkback_phone" msgid="868393783858123880">"Telefonoa"</string>
     <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Irudietarako gailua"</string>
-    <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Aurikularra"</string>
+    <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Entzungailua"</string>
     <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Idazteko gailua"</string>
     <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth gailua"</string>
     <string name="bluetooth_hearingaid_left_pairing_message" msgid="8561855779703533591">"Ezkerreko audifonoa parekatzen…"</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB bidezko arazketa"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Gaitu arazketa modua USBa konektatzean"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Baliogabetu USB bidezko arazketarako baimenak"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Hari gabeko arazketa"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Arazketa modua wifi-konexioa aktibatuta dagoenean"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Errorea"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Hari gabeko arazketa"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Erabilgarri dauden gailuak ikusteko eta erabiltzeko, aktibatu hari gabeko arazketa"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parekatu gailua QR kodearekin"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Parekatu gailu berriak QR kodea eskaneatuta"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parekatu gailua parekatze-kodearekin"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parekatu gailu berriak sei digituko kodearekin"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Parekatutako gailuak"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Konektatuta daudenak"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Gailuaren xehetasunak"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Ahaztu"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Gailuaren erreferentzia-gako digitala: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Ezin izan da konektatu"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Ziurtatu <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sare berera konektatuta dagoela"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Parekatu gailuarekin"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wifi bidezko parekatze-kodea"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Ezin izan da parekatu gailua"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Ziurtatu gailua sare berera konektatuta dagoela."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parekatu gailua wifi sare baten bidez QR kode bat eskaneatuta"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Gailua parekatzen…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Ezin izan da parekatu gailua. QR kodea ez zen zuzena zen edo gailua ez dago sare berera konektatuta."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP helbidea eta ataka"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Eskaneatu QR kodea"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parekatu gailua wifi sare baten bidez QR kode bat eskaneatuta"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, araztu, gailua"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Akatsen txostenerako lasterbidea"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Bateriaren menuan, erakutsi akatsen txostena sortzeko botoia"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Mantendu aktibo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Erabilgarri badago, erabili konexioa partekatzeko hardwarearen azelerazioa"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB bidezko arazketa onartu?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB bidezko arazketa garapen-xedeetarako soilik dago diseinatuta. Erabil ezazu ordenagailuaren eta gailuaren artean datuak kopiatzeko, aplikazioak gailuan jakinarazi gabe instalatzeko eta erregistro-datuak irakurtzeko."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Hari gabeko arazketa baimendu nahi duzu?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Hari gabeko arazketa garapen-xedeetarako soilik dago diseinatuta. Erabil ezazu ordenagailuaren eta gailuaren artean datuak kopiatzeko, gailuan aplikazioak jakinarazi gabe instalatzeko eta erregistroko datuak irakurtzeko."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Aurretik baimendutako ordenagailu guztiei USB bidezko arazketarako sarbidea baliogabetu nahi diezu?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Baimendu garapenerako ezarpenak?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ezarpen hauek garapen-xedeetarako pentsatu dira soilik. Baliteke ezarpenen eraginez gailua matxuratzea edo funtzionamendu okerra izatea."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanopia (gorri-berdeak)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanopia (urdin-horia)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koloreen zuzenketa"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Kolore-zuzenketak kolore zehatzagoak ikusten laguntzen die kolore-itsutasuna duten pertsonei"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> hobespena gainjarri zaio"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> inguru gelditzen dira"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> baino gutxiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen da (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> baino gehiago gelditzen da"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Baliteke telefonoa laster itzaltzea"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Baliteke tableta laster itzaltzea"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Baliteke gailua laster itzaltzea"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Baliteke telefonoa laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Baliteke tableta laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Baliteke gailua laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Baliteke telefonoa laster itzaltzea"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Baliteke tableta laster itzaltzea"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Baliteke gailua laster itzaltzea"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Baliteke telefonoa laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Baliteke tableta laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Baliteke gailua laster itzaltzea (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> guztiz kargatu arte"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> guztiz kargatu arte"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ezezaguna"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kargatzen"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Bizkor kargatzen"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mantso kargatzen"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ez da kargatzen ari"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Konektatuta dago. Ezin da kargatu une honetan."</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Beteta"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index f15174a..9d92cfe 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"‏اشکال‌زدایی USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"‏با اتصال USB، حالت اشکال‌زدایی فعال شود"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"‏لغو مجوزهای اشکال‌زدایی USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"اشکال‌زدایی بی‌سیم"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"‏حالت اشکال‌زدایی کردن وقتی Wi‑Fi متصل است"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"خطا"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"اشکال‌زدایی بی‌سیم"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"برای مشاهده و استفاده از دستگاه‌های در دسترس، اشکال‌زدایی بی‌سیم را روشن کنید"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"‏مرتبط کردن دستگاه با کد QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"‏دستگاه‌های جدید را با استفاده از اسکنر کد QR مرتبط کنید"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"مرتبط کردن دستگاه با کد مرتبط‌سازی"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"دستگاه‌های جدید را با استفاده از کد شش رقمی مرتبط کنید"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"دستگاه‌های مرتبط‌شده"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"درحال‌حاضر متصل"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"جزئیات دستگاه"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"فراموش شود"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"اثرانگشت دستگاه: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"اتصال ناموفق"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"مطمئن شوید که <xliff:g id="DEVICE_NAME">%1$s</xliff:g> به شبکه درستی متصل شده باشد"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"مرتبط کردن با دستگاه"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‏کد مرتبط‌سازی Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"مرتبط‌سازی ناموفق"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"مطمئن شوید که دستگاه به همان شبکه متصل باشد."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن کد QR مرتبط کنید"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"مرتبط‌سازی دستگاه…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"‏مرتبط کردن دستگاه انجام نشد. یا کد QR اشتباه بوده است، یا دستگاه به همان شبکه متصل نیست."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏نشانی IP و درگاه"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"‏اسکن کد QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"‏دستگاه را ازطریق Wi‑Fi و با اسکن کردن کد QR مرتبط کنید"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"‏ADB (پل اشکال‌زدایی Android)، اشکال‌زدایی کردن، برنامه‌نویس"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"میان‌بر گزارش مشکل"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"نمایش دکمه‌ای در منوی روشن/خاموش برای گرفتن گزارش اشکال"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"بیدار ماندن"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"استفاده از شتاب سخت‌افزاری اشتراک‌گذاری اینترنت درصورت دردسترس بودن"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‏اشکال‌زدایی USB انجام شود؟"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‏اشکال‌زدایی USB فقط برای اهداف برنامه‌نویسی در نظر گرفته شده است. از آن برای رونوشت‌برداری داده بین رایانه و دستگاهتان، نصب برنامه‌ها در دستگاهتان بدون اعلان و خواندن داده‌های گزارش استفاده کنید."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"اشکال‌زدایی بی‌سیم انجام شود؟"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"اشکال‌زدایی بی‌سیم فقط برای اهداف برنامه‌نویسی در نظر گرفته شده است. از آن برای کپی کردن داده بین رایانه و دستگاهتان، نصب برنامه‌ها در دستگاهتان بدون اعلان، و خواندن داده‌های گزارش استفاده کنید."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‏دسترسی به اشکال‌زدایی USB از تمام رایانه‌هایی که قبلاً مجاز دانسته‌اید لغو شود؟"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"تنظیمات برنامه‌نویسی مجاز باشد؟"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"این تنظیمات فقط برای برنامه‌نویسی در نظر گرفته شده است. ممکن است استفاده از این تنظیمات موجب خرابی یا عملکرد نادرست دستگاه یا برنامه‌های شما شود."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"قرمزدشواربینی (قرمز-سبز)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"آبی‌دشواربینی (آبی-زرد)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"تصحیح رنگ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"تصحیح رنگ به افراد مبتلا به کوررنگی کمک می‌کند رنگ‌ها را دقیق‌تر ببینند"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"توسط <xliff:g id="TITLE">%1$s</xliff:g> لغو شد"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"کمتر از <xliff:g id="THRESHOLD">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"بیش از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> شارژ باقی مانده است (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"بیش از <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی مانده است"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ممکن است تلفن به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ممکن است دستگاه به‌زودی خاموش شود"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ممکن است تلفن به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ممکن است رایانه لوحی به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ممکن است دستگاه به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ممکن است تلفن به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ممکن است رایانه لوحی به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ممکن است دستگاه به‌زودی خاموش شود"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ممکن است تلفن به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ممکن است رایانه لوحی به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ممکن است دستگاه به‌زودی خاموش شود (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - ‏<xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> مانده تا شارژ کامل"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> تا شارژ کامل"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ناشناس"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"در حال شارژ شدن"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"درحال شارژ شدن سریع"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"درحال شارژ شدن آهسته"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"شارژ نمی‌شود"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"به برق وصل شده‌ است، درحال‌حاضر شارژ نمی‌شود"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"پر"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 1232db3..6bb6d5b 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-vianetsintä"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Vianetsintätila USB-liitännän ollessa käytössä"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Peruuta USB-vianetsinnän käyttöoikeudet"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Langaton virheenkorjaus"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Virheenkorjaustila Wi-Fin ollessa käytössä"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Virhe"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Langaton virheenkorjaus"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Laita langaton virheenkorjaus päälle, niin voit nähdä saatavilla olevat laitteet ja käyttää niitä"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Muodosta laitepari QR-koodilla"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Muodosta uusia laitepareja QR-koodiskannerilla"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Yhdistä laite laiteparikoodilla"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Muodosta uusia laitepareja kuusinumeroisella koodilla"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Laiteparit"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Yhdistetty tällä hetkellä"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Laitteen tiedot"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Unohda"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Laitteen sormenjälki: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Yhteys epäonnistui"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Varmista, että <xliff:g id="DEVICE_NAME">%1$s</xliff:g> on yhdistetty oikeaan verkkoon"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Muodosta laitepari"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi-laiteparikoodi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Laiteparin muodostus ei onnistunut"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Varmista, että laite on yhdistetty samaan verkkoon."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Muodosta laitepari Wi-Fi-yhteyden kautta skannaamalla QR-koodi"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Muodostetaan laiteparia…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Laiteparin muodostus ei onnistunut. QR-koodi oli virheellinen, tai laitetta ei ole yhdistetty samaan verkkoon."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-osoite &amp; portti"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skannaa QR-koodi"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Muodosta laitepari Wi-Fi-yhteyden kautta skannaamalla QR-koodi"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, virheenkorjaus, kehittäminen"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Virheraportin pikakuvake"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Näytä virheraporttipainike virtavalikossa."</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Pysy käynnissä"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Käytä laitteistokiihdytyksen yhteyden jakamista, jos se on käytettävissä."</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Sallitaanko USB-vianetsintä?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-vianetsintä on tarkoitettu vain kehittäjien käyttöön. Sen avulla voidaan kopioida tietoja tietokoneesi ja laitteesi välillä, asentaa laitteeseesi sovelluksia ilmoittamatta siitä sinulle ja lukea lokitietoja."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Sallitaanko langaton virheenkorjaus?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Langaton virheenkorjaus on tarkoitettu vain kehittäjien käyttöön. Sen avulla voidaan kopioida dataa tietokoneesi ja laitteesi välillä, asentaa laitteeseesi sovelluksia ilmoittamatta siitä sinulle ja lukea lokidataa."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Haluatko peruuttaa USB-vianetsinnän käyttöoikeuden kaikilta tietokoneilta, joille olet antanut luvan aiemmin?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Sallitaanko kehittäjäasetukset?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Nämä asetukset on tarkoitettu vain kehityskäyttöön, ja ne voivat aiheuttaa haittaa laitteellesi tai sen sovelluksille."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (puna-vihersokeus)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (sini-keltasokeus)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Värikorjaus"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Värinkorjaus auttaa värisokeita tulkitsemaan värejä"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Tämän ohittaa <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Noin <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Alle <xliff:g id="THRESHOLD">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Yli <xliff:g id="TIME_REMAINING">%1$s</xliff:g> jäljellä"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Puhelin voi pian sammua"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tabletti voi pian sammua"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Laite voi pian sammua"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Puhelin voi pian sammua (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tabletti voi pian sammua (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Laite voi pian sammua (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Puhelin voi sammua pian"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tabletti voi sammua pian"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Laite voi sammua pian"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Puhelin voi sammua pian (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tabletti voi sammua pian (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Laite voi sammua pian (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jäljellä täyteen lataukseen"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> täyteen lataukseen"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tuntematon"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ladataan"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Nopea lataus"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Hidas lataus"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ei laturissa"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Kytketty virtalähteeseen, lataaminen ei onnistu"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Täynnä"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 6404df4..b040be9 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Débogage USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mode débogage lorsqu\'un câble USB est connecté"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Annuler les autorisations relatives au débogage USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Débogage sans fil"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode débogage lorsque le Wi-Fi est connecté"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Erreur"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Débogage sans fil"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Pour afficher et utiliser les appareils à proximité, activez le débogage sans fil"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Associer l\'appareil à l\'aide d\'un code QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Associer les nouveaux appareils à l\'aide d\'un lecteur de code QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Associer l\'appareil avec un code d\'association"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Associer les nouveaux appareils à l\'aide d\'un code à six chiffres"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Appareils associés"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Actuellement connecté"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Renseignements sur l\'appareil"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Oublier"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Empreinte digitale d\'appareil : <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Échec de la connexion"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Vérifiez que <xliff:g id="DEVICE_NAME">%1$s</xliff:g> est connecté au bon réseau"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Associer avec l\'appareil"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Code d\'association Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Échec de l\'association"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Vérifier que l\'appareil est connecté au même réseau."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associer un appareil au Wi-Fi en numérisant un code QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Association de l\'appareil en cours…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association de l\'appareil Soit le code QR est incorrect, soit l\'appareil n\'est pas connecté au même réseau."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Numériser le code QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Associer un appareil au Wi-Fi en numérisant un code QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, appareil"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci de rapport de bogue"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton permettant d\'établir un rapport de bogue dans le menu de démarrage"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Rester activé"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Utiliser l\'accélération matérielle du partage de connexion si possible"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Autoriser le débogage USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Le débogage USB est conçu uniquement pour le développement. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données de journal."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Autoriser le débogage sans fil?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Le débogage sans fil est conçu uniquement aux fin de conception. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données de journal."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Voulez-vous vraiment désactiver l\'accès au débogage USB de tous les ordinateurs précédemment autorisés?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Activer les paramètres de développement?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ces paramètres sont en cours de développement. Ils peuvent endommager votre appareil et les applications qui s\'y trouvent, ou provoquer leur dysfonctionnement."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu/jaune)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction des couleurs"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La correction des couleurs aide les personnes atteintes de daltonisme à mieux percevoir les couleurs"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> : <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Il reste environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Il se peut que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Il se peut que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Il se peut que l\'appareil s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Il se peut que le téléphone s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Il se peut que la tablette s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Il se peut que l\'appareil s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Il se peut que le téléphone s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Il se peut que la tablette s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Il se peut que l\'appareil s\'éteigne bientôt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Il se peut que le téléphone s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Il se peut que la tablette s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Il se peut que l\'appareil s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> : <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Charge en cours…"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Recharge rapide"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charge lente"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"N\'est pas en charge"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"L\'appareil est branché, mais il ne peut pas être chargé pour le moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Pleine"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index e75063b..fb70c88 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Débogage USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mode débogage lorsqu\'un câble USB est connecté"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Annuler autorisations pour débog. USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Débogage via Wi-Fi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode de débogage en connexion Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Erreur"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Débogage via Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Pour afficher et utiliser les appareils disponibles, activez le débogage sans fil"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Associer l\'appareil avec un code QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Associer les nouveaux appareils à l\'aide d\'un lecteur de code QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Associer l\'appareil avec un code d\'association"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Associer les nouveaux appareils à l\'aide d\'un code à six chiffres"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Appareils associés"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Actuellement connecté"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Infos sur l\'appareil"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Retirer"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Empreinte de l\'appareil : <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Échec de la connexion"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Vérifiez que l\'appareil <xliff:g id="DEVICE_NAME">%1$s</xliff:g> est connecté au bon réseau"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Associer à l\'appareil"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Code d\'association via le Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Échec de l\'association"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Assurez-vous que l\'appareil est connecté au même réseau."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Association de l\'appareil…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Échec de l\'association à l\'appareil. Le code QR est incorrect, ou l\'appareil n\'est pas connecté au même réseau."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresse IP et port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanner un code QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Associer l\'appareil via le Wi‑Fi à l\'aide d\'un code QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, débogage, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Raccourci vers rapport de bug"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afficher un bouton dans le menu de démarrage permettant de créer un rapport de bug"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Écran toujours actif"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Utiliser l\'accélération matérielle pour le partage de connexion, si disponible"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Autoriser le débogage USB ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Le débogage USB est conçu uniquement pour le développement. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données de journal."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Autoriser le débogage via Wi-Fi ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Le débogage via Wi-Fi est conçu uniquement pour le développement. Utilisez-le pour copier des données entre votre ordinateur et votre appareil, installer des applications sur votre appareil sans notification et lire les données des journaux."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Voulez-vous vraiment désactiver l\'accès au débogage USB de tous les ordinateurs précédemment autorisés ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Activer les paramètres de développement ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ces paramètres sont en cours de développement. Ils peuvent endommager votre appareil et les applications qui s\'y trouvent, ou provoquer leur dysfonctionnement."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rouge/vert)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (bleu-jaune)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correction couleur"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La correction des couleurs aide les personnes atteintes de daltonisme à mieux percevoir les couleurs"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Remplacé par <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Temps restant : environ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Il reste moins de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Il reste plus de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Il est possible que le téléphone s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Il est possible que la tablette s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Il est possible que l\'appareil s\'éteigne bientôt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Il est possible que le téléphone s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Il est possible que la tablette s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Il est possible que l\'appareil s\'éteigne bientôt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Le téléphone va bientôt s\'éteindre"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"La tablette va bientôt s\'éteindre"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"L\'appareil va bientôt s\'éteindre"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Le téléphone va bientôt s\'éteindre (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"La tablette va bientôt s\'éteindre (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"L\'appareil va bientôt s\'éteindre (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> jusqu\'à ce que la batterie soit chargée"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> jusqu\'à la charge complète"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Inconnu"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Batterie en charge"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Charge rapide"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Charge lente"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Pas en charge"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Appareil branché, mais impossible de le charger pour le moment"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Pleine"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 7fd32f9..1407a50 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuración por USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuración de erros cando o USB está conectado"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revogar as autorizacións de depuración por USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuración de erros sen fíos"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuración de erros ao conectarse a wifi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Produciuse un erro"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuración de erros sen fíos"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar os dispositivos dispoñibles, activa a depuración de erros sen fíos"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Vincular o dispositivo cun código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Vincula dispositivos novos mediante un escáner de códigos QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Vincular o dispositivo co código de sincronización"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Vincula dispositivos novos mediante un código de seis díxitos"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos vinculados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Dispositivos conectados actualmente"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Datos do dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Esquecer"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Impresión dixital do dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Produciuse un erro na conexión"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asegúrate de que o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> estea conectado á rede correcta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sincronizar co dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de sincronización da wifi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Produciuse un fallo na sincronización"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Asegúrate de que o dispositivo estea conectado á mesma rede"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Vincula o dispositivo a través da wifi escaneando un código QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Sincronizando dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Produciuse un erro ao sincronizar o dispositivo. O código QR era incorrecto ou o dispositivo non está conectado á mesma rede."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Enderezo IP e porto"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Escanear o código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Vincula o dispositivo a través da wifi escaneando un código QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depuración, programador"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atallo do informe de erros"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un botón no menú de acendido para crear un informe de erros"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Pantalla activa"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Se está dispoñible, úsase a aceleración de hardware para conexión compartida"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Queres permitir a depuración por USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"A depuración de erros USB está deseñada unicamente para fins de programación. Utilízaa para copiar datos entre o ordenador e o dispositivo, instalar aplicacións no dispositivo sen enviar notificacións e ler os datos do rexistro."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Queres permitir a depuración de erros sen fíos?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"A depuración de erros sen fíos está deseñada unicamente para fins de programación. Utilízaa para copiar datos entre o ordenador e o dispositivo, instalar aplicacións no dispositivo sen recibir notificacións e ler os datos do rexistro."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Queres revogar o acceso á depuración por USB desde todos os ordenadores que autorizaches previamente?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permitir a configuración de programación?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Esta configuración só está destinada á programación. Esta pode provocar que o dispositivo e as aplicacións fallen ou se comporten incorrectamente."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalía (vermello-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalía (azul-amarelo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corrección da cor"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"A corrección da cor axuda ás persoas con daltonismo a ver as cores con maior precisión"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Anulado por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tempo restante: menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tempo restante: máis de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Tempo restante: máis de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"É posible que o teléfono se apague en breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"É posible que a tableta se apague en breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"É posible que o dispositivo se apague en breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"É posible que o teléfono se apague en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"É posible que a tableta se apague en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"É posible que o dispositivo se apague en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"O teléfono pode apagarse en breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"A tableta pode apagarse en breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"O dispositivo pode apagarse en breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"O teléfono pode apagarse en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"A tableta pode apagarse en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"O dispositivo pode apagarse en breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> para completar a carga"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> para completar a carga"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Descoñecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Cargando"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Cargando rapidamente"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Cargando lentamente"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Non se está cargando"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Conectouse, pero non se pode cargar neste momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Completa"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 1513c57..889857a 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ડીબગિંગ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"જ્યારે USB કનેક્ટ કરેલ હોય ત્યારે ડીબગ મોડ"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ડીબગિંગ પ્રમાણીકરણોને રદબાતલ કરો"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"વાયરલેસ ડિબગીંગ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"વાઇ-ફાઇ કનેક્ટ કરેલું હોય ત્યારે ડિબગ મોડ"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ભૂલ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"વાયરલેસ ડિબગીંગ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ઉપલબ્ધ ડિવાઇસને જોવા અને તેનો ઉપયોગ કરવા માટે, વાયરલેસ ડિબગીંગ ચાલુ કરો"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR કોડ વડે ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR કોડ સ્કૅનરનો ઉપયોગ કરીને નવા ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"જોડાણ કરવાના કોડ વડે ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"છ અંકના કોડનો ઉપયોગ કરીને નવા ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"જોડાણ કરેલા ડિવાઇસ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"હાલમાં કનેક્ટ કરેલા"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ડિવાઇસની વિગતો"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ભૂલી જાઓ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ડિવાઇસ ફિંગરપ્રિન્ટ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"કનેક્શન અસફળ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"ખાતરી કરો કે <xliff:g id="DEVICE_NAME">%1$s</xliff:g> યોગ્ય નેટવર્ક સાથે કનેક્ટ થયેલું છે"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ડિવાઇસ સાથે જોડાણ કરો"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"વાઇ-ફાઇ જોડાણ કરવાનો કોડ"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"જોડાણ બનાવવું અસફળ રહ્યું"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ખાતરી કરો કે ડિવાઇસ સમાન નેટવર્કથી કનેક્ટ કરેલું છે."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR કોડને સ્કૅન કરીને વાઇ-ફાઇ પર ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ડિવાઇસનું જોડાણ બનાવી રહ્યાં છીએ…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ડિવાઇસનું જોડાણ કરવામાં નિષ્ફળ રહ્યાં. કાં તો QR કોડ ખોટો હતો અથવા ડિવાઇસ સમાન નેટવર્ક સાથે કનેક્ટ કરેલું નથી."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ઍડ્રેસ &amp; પોર્ટ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR કોડ સ્કૅન કરો"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR કોડને સ્કૅન કરીને વાઇ-ફાઇ પર ડિવાઇસનું જોડાણ બનાવો"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ડિબગ, ડેવ"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"બગ રિપોર્ટ શોર્ટકટ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"બગ રિપોર્ટ લેવા માટે પાવર મેનૂમાં એક બટન બતાવો"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"સક્રિય રાખો"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"જો ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ ઉપલબ્ધ હોય તો તેનો ઉપયોગ કરો"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ડિબગિંગને મંજૂરી આપીએ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ડિબગીંગ ફક્ત વિકાસ હેતુઓ માટે જ બનાવાયેલ છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ઉપકરણ વચ્ચે ડેટાને કૉપિ કરવા, નોટિફિકેશન વગર તમારા ઉપકરણ પર ઍપ્લિકેશનો ઇન્સ્ટોલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"વાયરલેસ ડિબગીંગને મંજૂરી આપીએ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"વાયરલેસ ડિબગીંગ ફક્ત ડેવલપમેન્ટના હેતુઓ માટે જ બનાવાયું છે. તેનો ઉપયોગ તમારા કમ્પ્યુટર અને તમારા ડિવાઇસ વચ્ચે ડેટાને કૉપિ કરવા, નોટિફિકેશન વગર તમારા ડિવાઇસ પર ઍપને ઇન્સ્ટૉલ કરવા અને લૉગ ડેટા વાંચવા માટે કરો."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"તમે અગાઉ અધિકૃત કરેલા તમામ કમ્પ્યુટર્સમાંથી USB ડિબગિંગ પરની અ‍ૅક્સેસ રદબાતલ કરીએ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"વિકાસ સેટિંગ્સને મંજૂરી આપીએ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"આ સેટિંગ્સ ફક્ત વિકાસનાં ઉપયોગ માટે જ હેતુબદ્ધ છે. તે તમારા ઉપકરણ અને તેના પરની એપ્લિકેશન્સનાં ભંગ થવા અથવા ખરાબ વર્તનનું કારણ બની શકે છે."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"પ્રોટેનોમલી (લાલ-લીલો)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ટ્રાઇટેનોમલી(વાદળી-પીળો)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"રંગ સુધારણા"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"રંગ સુધારણા રંગ અંધત્વવાળા લોકોને વધુ સચોટ રંગો જોવામાં સહાય કરે છે"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> દ્વારા ઓવરરાઇડ થયું"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"લગભગ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> બાકી છે"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> કરતાં ઓછો સમય બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> કરતાં વધુ સમય બાકી છે (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> કરતાં વધુ સમય બાકી છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ફોન થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ટૅબ્લેટ થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ઉપકરણ થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ફોન થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ટૅબ્લેટ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ઉપકરણ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ફોન થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ટૅબ્લેટ થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ડિવાઇસ થોડીક જ વારમાં બંધ થઈ શકે છે"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ફોન થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ટૅબ્લેટ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ડિવાઇસ થોડીક જ વારમાં બંધ થઈ શકે છે (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ચાર્જ થવામાં <xliff:g id="TIME">%1$s</xliff:g> બાકી છે"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ચાર્જ થવા માટે <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"અજાણ્યું"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ચાર્જ થઈ રહ્યું છે"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ઝડપથી ચાર્જ થાય છે"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ધીમેથી ચાર્જ થાય છે"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ચાર્જ થઈ રહ્યું નથી"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"પ્લગ ઇન કરેલ, હમણાં ચાર્જ કરી શકતા નથી"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"પૂર્ણ"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index c79c4a4..24153b9 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -206,6 +206,60 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB डीबग करना"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"डीबग मोड जब USB कनेक्‍ट किया गया हो"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB डीबग करने की मंज़ूरी रद्द करें"</string>
+    <!-- no translation found for enable_adb_wireless (6973226350963971018) -->
+    <skip />
+    <!-- no translation found for enable_adb_wireless_summary (7344391423657093011) -->
+    <skip />
+    <!-- no translation found for adb_wireless_error (721958772149779856) -->
+    <skip />
+    <!-- no translation found for adb_wireless_settings (2295017847215680229) -->
+    <skip />
+    <!-- no translation found for adb_wireless_list_empty_off (1713707973837255490) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_title (6982904096137468634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_summary (3729901496856458634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_title (1122590300445142904) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_summary (6370414511333685185) -->
+    <skip />
+    <!-- no translation found for adb_paired_devices_title (5268997341526217362) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_connected_summary (3039660790249148713) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_details_title (7129369670526565786) -->
+    <skip />
+    <!-- no translation found for adb_device_forget (193072400783068417) -->
+    <skip />
+    <!-- no translation found for adb_device_fingerprint_title_format (291504822917843701) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_title (664211177427438438) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_message (9213896700171602073) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_title (7141739231018530210) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_pairing_code_label (3639239786669722731) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_title (3426758947882091735) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_msg (6611097519661997148) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_summary (8051414549011801917) -->
+    <skip />
+    <!-- no translation found for adb_wireless_verifying_qrcode_text (6123192424916029207) -->
+    <skip />
+    <!-- no translation found for adb_qrcode_pairing_device_failed_msg (6936292092592914132) -->
+    <skip />
+    <!-- no translation found for adb_wireless_ip_addr_preference_title (8335132107715311730) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_title (1906409667944674707) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_description (8578868049289910131) -->
+    <skip />
+    <!-- no translation found for keywords_adb_wireless (6507505581882171240) -->
+    <skip />
     <string name="bugreport_in_power" msgid="8664089072534638709">"गड़बड़ी की रिपोर्ट का शॉर्टकट"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"गड़बड़ी की रिपोर्ट लेने के लिए पावर मेन्यू में कोई बटन दिखाएं"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"स्क्रीन को चालू रखें"</string>
@@ -271,6 +325,10 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"हार्डवेयर से तेज़ी लाने के लिए टेदर करने की सुविधा मौजूद होने पर उसका इस्तेमाल करें"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB डीबग करने की अनुमति दें?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB डीबग करने का मकसद केवल डेवेलप करना है. इसका इस्तेमाल आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना सूचना के आपके डिवाइस पर ऐप इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
+    <!-- no translation found for adbwifi_warning_title (727104571653031865) -->
+    <skip />
+    <!-- no translation found for adbwifi_warning_message (8005936574322702388) -->
+    <skip />
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"उन सभी कंप्यूटरों से USB डीबग करने की पहुंचर रद्द करें, जिन्हें आपने पहले इसकी मंज़ूरी दी थी?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिंग की अनुमति दें?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्‍थित ऐप्लिकेशन  को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string>
@@ -403,12 +461,18 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> से कम बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा चलने लायक बैटरी बची है (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> से ज़्यादा चलने लायक बैटरी बची है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"फ़ोन जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"टैबलेट जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"डिवाइस जल्दी ही बंद हो सकता है"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"फ़ोन जल्दी ही बंद हो सकता है (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"टैबलेट जल्दी ही बंद हो सकता है (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"डिवाइस जल्दी ही बंद हो सकता है (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (137330009791560774) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (145489081521468132) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1070562682853942350) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4429259621177089719) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7703677921000858479) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4374784375644214578) -->
+    <skip />
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"चार्ज पूरा होने में <xliff:g id="TIME">%1$s</xliff:g> बचा है"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> में पूरा चार्ज हो जाएगा"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 3ab5678..28a8858 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Otklanjanje pogrešaka putem USB-a"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Otklanjanje pogrešaka putem USB-a"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Opoziv autorizacija za otklanjanje pogrešaka putem USB-a"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bežično otklanjanje pogrešaka"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Način otklanjanja pogrešaka kad je Wi-Fi povezan"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Pogreška"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bežično otklanjanje pogrešaka"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Da biste vidjeli dostupne uređaje i mogli se njima koristiti, uključite bežično otklanjanje pogrešaka"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Uparivanje uređaja pomoću QR koda"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Uparivanje novih uređaja pomoću čitača QR koda"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Uparivanje uređaja pomoću koda za uparivanje"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Uparivanje novih uređaja pomoću šesteroznamenkastog koda"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Upareni uređaji"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Trenutačno povezano"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Pojedinosti o uređaju"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Zaboravi"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Otisak prsta na uređaju: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Neuspješno povezivanje"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Provjerite je li uređaj <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povezan na ispravnu mrežu"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Uparivanje s uređajem"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kôd za uparivanje putem Wi-Fija"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Uparivanje nije uspjelo"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Provjerite je li uređaj povezan na istu mrežu."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Uparivanje uređaja putem Wi-Fija skeniranjem QR koda"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Uparivanje uređaja…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Uparivanje uređaja nije uspjelo. QR kôd je neispravan ili uređaj nije povezan na istu mrežu."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresa i priključak"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skeniraj QR kôd"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Uparivanje uređaja putem Wi-Fija skeniranjem QR koda"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, otklanjanje pogrešaka, razvoj"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Prečac izvješća o pogreškama"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaži gumb u izborniku napajanja za izradu izvješća o programskim pogreškama"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ne pokreći mirovanje"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Upotreba hardverskog ubrzanja za modemsko povezivanje ako je dostupno"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Omogućiti otklanjanje pogrešaka putem USB-a?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Otklanjanje pogrešaka putem USB-a namijenjeno je samo u razvojne svrhe. Može se upotrijebiti za kopiranje podataka s računala na uređaj i obrnuto, instalaciju aplikacija na uređaju bez obavijesti i za čitanje dnevničkih zapisa."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Želite li omogućiti bežično otklanjanje pogrešaka?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bežično otklanjanje pogrešaka namijenjeno je samo u razvojne svrhe. Može se upotrijebiti za kopiranje podataka s računala na uređaj i obrnuto, instalaciju aplikacija na uređaj bez obavijesti i za čitanje dnevničkih zapisa."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Želite li opozvati pristup uklanjanju pogrešaka putem USB-a sa svih računala koja ste prethodno autorizirali?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Dopustiti postavke razvojnih programera?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ove su postavke namijenjene samo razvojnim programerima. One mogu uzrokovati kvar ili neželjeno ponašanje vašeg uređaja i aplikacija na njemu."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (crveno – zeleno)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (plavo – žuto)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcija boje"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korekcija boje pomaže slijepima za boje da vide preciznije boje"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Premošćeno postavkom <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Još otprilike <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostalo je manje od <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Preostalo je više od <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Uređaj bi se uskoro mogao isključiti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Uređaj bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Uređaj bi se uskoro mogao isključiti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Uređaj bi se uskoro mogao isključiti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Napunit će se za <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – napunit će se za <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nepoznato"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Punjenje"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Brzo punjenje"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sporo punjenje"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ne puni se"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Uključen, trenutačno se ne može puniti"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Puna"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index 8d06f58..61433be 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB hibakeresés"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Hibakeresés mód USB csatlakoztatásakor"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB-s hibakeresésre vonatkozó engedélyek visszavonása"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Vezeték nélküli hibakeresés"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Hibakeresési mód, amikor van Wi-Fi-kapcsolat"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Hiba"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Vezeték nélküli hibakeresés"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"A rendelkezésre álló eszközök megtekintéséhez és használatához kapcsolja be a vezeték nélküli hibakeresést"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Eszköz párosítása QR-kóddal"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Párosítsa az új eszközöket QR-kód-szkennelő használatával"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Eszköz párosítása párosítókóddal"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Párosítsa az új eszközöket hatjegyű kód használatával"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Párosított eszközök"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Csatlakoztatva"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Eszközadatok"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Elfelejtés"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Ujjlenyomat az eszközön: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Sikertelen kapcsolódás"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Győződjön meg arról, hogy a(z) <xliff:g id="DEVICE_NAME">%1$s</xliff:g> a megfelelő hálózathoz csatlakozik"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Párosítás eszközzel"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi-párosítókód"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Sikertelen párosítás"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Győződjön meg arról, hogy az eszköz a megfelelő hálózathoz csatlakozik."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Párosítsa az eszközt Wi-Fi-n keresztül QR-kód beolvasásával"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Eszköz párosítása…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Nem sikerült az eszközzel való párosítás. Vagy helytelen volt a QR-kód, vagy az eszköz másik hálózathoz csatlakozott."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-cím és port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-kód beolvasása"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Párosítsa az eszközt Wi-Fi-n keresztül QR-kód beolvasásával"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Hibabejelentési gomb"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Gomb megjelenítése a bekapcsolási menüben hibajelentés készítéséhez"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Nem kapcsolódik ki"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Az internetmegosztás hardveres gyorsításának használata, amikor lehetséges"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Engedélyezi az USB hibakeresést?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Az USB hibakeresés fejlesztési célokat szolgál. Használhatja adatok másolására a számítógép és a készülék között, alkalmazások a készülékre való értesítés nélküli telepítésére és naplózási adatok olvasására."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Engedélyezi a vezeték nélküli hibakeresést?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"A vezeték nélküli hibakeresés kizárólag fejlesztési célokat szolgál. Használhatja adatok másolására a számítógép és az eszköz között, alkalmazásoknak az eszközre való telepítésére (értesítés nélkül) és naplózási adatok olvasására."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Visszavonja a hozzáférést az USB-s hibakereséshez az összes számítógépről, ahol korábban engedélyezte azt?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Engedélyezi a fejlesztői beállításokat?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ezek a beállítások csak fejlesztői használatra szolgálnak. Használatuk esetén eszköze vagy alkalmazásai meghibásodhatnak, illetve nem várt módon viselkedhetnek."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (piros– zöld)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (kék–sárga)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Színkorrekció"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"A színkorrekció segít a színtévesztőknek abban, hogy pontosabban lássák a színeket"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Felülírva erre: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Körülbelül <xliff:g id="TIME_REMAINING">%1$s</xliff:g> maradt hátra"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Kevesebb mint <xliff:g id="THRESHOLD">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Kevesebb mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Több mint <xliff:g id="TIME_REMAINING">%1$s</xliff:g> van hátra"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Előfordulhat, hogy a telefon hamarosan leáll"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Előfordulhat, hogy a táblagép hamarosan leáll"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Előfordulhat, hogy az eszköz hamarosan leáll"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Előfordulhat, hogy a telefon hamarosan leáll (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Előfordulhat, hogy a táblagép hamarosan leáll (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Előfordulhat, hogy az eszköz hamarosan leáll (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Előfordulhat, hogy a telefon hamarosan kikapcsol"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Előfordulhat, hogy a táblagép hamarosan kikapcsol"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Előfordulhat, hogy az eszköz hamarosan kikapcsol"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Előfordulhat, hogy a telefon hamarosan kikapcsol (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Előfordulhat, hogy a táblagép hamarosan kikapcsol (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Előfordulhat, hogy az eszköz hamarosan kikapcsol (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> van hátra a feltöltésig"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> a feltöltésig"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ismeretlen"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Töltés"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Gyorstöltés"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lassú töltés"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nem tölt"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Csatlakoztatva, jelenleg nem tölt"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Feltöltve"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 99cef28..2e39f2c 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-ով վրիպազերծում"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Միացնել վրիպազերծման ռեժիմը, երբ USB-ն միացված է"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Չեղարկել USB-ով վրիպազերծման թույլտվությունները"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Անլար վրիպազերծում"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Ակտիվացնել վրիպազերծման ռեժիմը, երբ Wi-Fi-ը միացված է"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Սխալ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Անլար վրիպազերծում"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Հասանելի սարքերը տեսնելու և օգտագործելու համար միացրեք անլար վրիպազերծումը"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Զուգակցեք սարքը՝ օգտագործելով QR կոդը"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Զուգակցեք նոր սարքեր՝ օգտագործելով QR կոդերի սկաները"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Զուգակցեք սարքը՝ օգտագործելով զուգակցման կոդը"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Զուգակցեք նոր սարքեր՝ օգտագործելով վեցանիշ կոդը"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Զուգակցված սարքեր"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Միացված է"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Սարքի տվյալները"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Հեռացնել"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Սարքի մատնահետք՝ <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Չհաջողվեց միացնել"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Համոզվեք, որ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> սարքը միացված է ճիշտ ցանցին"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Սարքի հետ զուգակցում"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi-ի զուգակցման կոդ"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Չհաջողվեց զուգակցել"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Համոզվեք, որ սարքը միացված է միևնույն ցանցին։"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Զուգակցեք սարքը՝ Wi‑Fi-ի օգնությամբ սկանավորելով QR կոդը"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Սարքը զուգակցվում է…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Չհաջողվեց զուգակցել սարքի հետ։ Հնարավոր է, որ QR կոդը սխալ է, կամ սարքը միացված չէ միևնույն ցանցին։"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP հասցե և միացք"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR կոդի սկանավորում"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Զուգակցեք սարքը՝ Wi‑Fi-ի օգնությամբ սկանավորելով QR կոդը"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, վրիպազերծում, ծրագրավորող"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Սխալի հաղորդման դյուրանցում"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Գործարկման ցանկում ցույց տալ կոճակը՝ վրիպակների հաղորդման համար"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Մնալ արթուն"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Օգտագործել սարքակազմի արագացման միացումը, եթե հասանելի է"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Թույլատրե՞լ USB-ով վրիպազերծումը:"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-ով վրիպազերծումը միայն ծրագրավորման նպատակների համար է: Օգտագործեք այն ձեր համակարգչից տվյալները ձեր սարք պատճենելու համար, առանց ծանուցման ձեր սարքի վրա ծրագրեր տեղադրելու և տվյալների մատյանը ընթերցելու համար:"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Թույլատրե՞լ անլար վրիպազերծումը"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Անլար վրիպազերծումը նախատեսված է միայն ծրագրավորման համար: Այն թույլ է տալիս համակարգչի և սարքի միջև տվյալներ պատճենել, առանց ծանուցման ձեր սարքի վրա հավելվածներ տեղադրել և մատյանի ֆայլերը ընթերցել։"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Չեղարկե՞լ USB-ով վրիպազերծման հասանելիությունը` անջատելով այն բոլոր համակարգիչներից, որտեղ նախկինում թույլատրել էիք:"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ընդունե՞լ ծրագրավորման կարգավորումներ:"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Այս կարգավորումները միայն ծրագրավորման նպատակների համար են նախատեսված: Դրանք կարող են խանգարել ձեր սարքի կամ ծրագրի աշխատանքին:"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Պրոտանոմալիա (կարմիր-կանաչ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Տրիտանոմալիա (կապույտ-դեղին)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Գունաշտկում"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Գունաշտկումն օգնում է դալթոնիզմ ունեցող մարդկանց ավելի ճշգրիտ տեսնել գույները"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Գերազանցված է <xliff:g id="TITLE">%1$s</xliff:g>-ից"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Լիցքը կբավարարի մոտ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Մնացել է <xliff:g id="THRESHOLD">%1$s</xliff:g>-ից պակաս (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Մնացել է ավելի քան <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Հեռախոսը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Պլանշետը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Սարքը շուտով կանջատվի"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Հեռախոսը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Պլանշետը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Սարքը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Հեռախոսը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Պլանշետը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Սարքը շուտով կանջատվի"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Հեռախոսը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Պլանշետը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Սարքը շուտով կանջատվի (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> մինչև լիցքավորումը"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> մինչև լիցքավորումը"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Անհայտ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Լիցքավորում"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Արագ լիցքավորում"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Դանդաղ լիցքավորում"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Չի լիցքավորվում"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Միացված է հոսանքի աղբյուրին, սակայն այս պահին չի կարող լիցքավորվել"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Լիցքավորված է"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 25de382..b75fa35 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Debugging USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mode debug ketika USB tersambung"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Cabut otorisasi debug USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Proses debug nirkabel"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mode debug saat Wi-Fi tersambung"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Proses debug nirkabel"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Untuk melihat dan menggunakan perangkat yang tersedia, aktifkan proses debug nirkabel"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Sambungkan perangkat dengan kode QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Sambungkan perangkat baru menggunakan Pemindai kode QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sambungkan perangkat dengan kode penghubung"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sambungkan perangkat baru menggunakan kode enam digit"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Perangkat disambungkan"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Saat ini tersambung"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detail perangkat"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Lupakan"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Sidik jari perangkat: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Sambungan gagal"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> tersambung ke jaringan yang tepat"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sambungkan dengan perangkat"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kode penyambungan Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Penyambungan perangkat gagal"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan perangkat tersambung ke jaringan yang sama."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Menyambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Menyambungkan perangkat…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menyambungkan perangkat. Kode QR salah, atau perangkat tidak tersambung ke jaringan yang sama."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP &amp; Port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Memindai kode QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Menyambungkan perangkat melalui Wi‑Fi dengan memindai Kode QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan bug"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Tampilkan tombol di menu daya untuk mengambil laporan bug"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Tetap terjaga"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Gunakan akselerasi hardware tethering jika tersedia"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Izinkan melakukan debug USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Debugging USB dimaksudkan untuk tujuan pengembangan saja. Gunakan untuk menyalin data antara komputer dan perangkat Anda, memasang apl pada perangkat tanpa notifikasi, dan membaca data log."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Izinkan proses debug nirkabel?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Proses debug nirkabel dimaksudkan untuk tujuan pengembangan saja. Gunakan untuk menyalin data antara komputer dan perangkat Anda, menginstal aplikasi pada perangkat tanpa notifikasi, dan membaca data log."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Cabut akses ke debug USB dari semua komputer yang telah Anda otorisasi sebelumnya?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Izinkan setelan pengembangan?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Setelan ini hanya dimaksudkan untuk penggunaan pengembangan. Setelan dapat menyebabkan perangkat dan aplikasi yang menerapkannya rusak atau tidak berfungsi semestinya."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Koreksi warna"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Koreksi warna membantu orang penderita buta warna melihat warna yang lebih akurat"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Digantikan oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Sekitar <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tersisa kurang dari <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Tersisa lebih dari <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Ponsel mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Perangkat mungkin segera dimatikan"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Ponsel mungkin segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet mungkin segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Perangkat mungkin segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Ponsel akan segera dimatikan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet akan segera dimatikan"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Perangkat akan segera dimatikan"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Ponsel akan segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet akan segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Perangkat akan segera dimatikan (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Sisa <xliff:g id="TIME">%1$s</xliff:g> hingga terisi penuh"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> lagi terisi penuh"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengisi daya"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengisi daya cepat"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mengisi daya lambat"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengisi daya"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Tercolok, tidak dapat mengisi baterai sekarang"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 8fe382a..c75c689 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-villuleit"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Villuleitarstilling þegar USB er tengt."</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Afturkalla USB-villuleitarheimildir"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Þráðlaus villuleit"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Villuleitarstilling þegar Wi-Fi er tengt"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Villa"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Þráðlaus villuleit"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Til að sjá og nota tiltæk tæki skal kveikja á þráðlausri villuleit"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Para tæki með QR-kóða"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Para ný tæki með QR-kóðaskanna"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Para tæki með pörunarkóða"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Para ný tæki með sex tölustafa kóða"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Pöruð tæki"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Tengt"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Upplýsingar um tæki"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Gleyma"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Fingrafar tækis: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Tenging mistókst"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Gakktu úr skugga um að <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sé tengt réttu neti"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Para við tæki"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi pörunarkóði"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Pörun mistókst"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Gakktu úr skugga um að tækið sé tengt sama neti."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Tengja tæki með Wi-Fi með því að skanna QR-kóða"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Parar tæki…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Ekki tókst að para við tækið. Annað hvort var QR-kóðinn rangur eða tækið ekki tengt sama neti."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-tala og gátt"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skanna QR-kóða"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Tengja tæki með Wi-Fi með því að skanna QR-kóða"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, villuleit, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Flýtileið í villutilkynningu"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Sýna hnapp til að skrá villutilkynningu í valmynd aflrofans"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Vaka"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Nota vélbúnaðarhröðun fyrir tjóðrun ef það býðst"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Leyfa USB-villuleit?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-villuleit er aðeins ætluð til nota í þróunarskyni. Hana má nota til að afrita gögn á milli tölvu og tækis, setja forrit upp í tækinu án tilkynninga og lesa annálagögn."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Leyfa þráðlausa villuleit?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Þráðlaus villuleit er aðeins ætluð til nota í þróunarskyni. Hana má nota til að afrita gögn á milli tölvu og tækis, setja forrit upp í tækinu án tilkynninga og lesa annálagögn."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Afturkalla aðgang að USB-villuleit í öllum tölvum sem þú hefur áður veitt heimild?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Leyfa þróunarstillingar?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Þessar stillingar eru einungis ætlaðar í þróunarskyni. Þær geta valdið því að tækið og forrit þess bili eða starfi á rangan hátt."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Litblinda (rauðgræn)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Litblinda (blágul)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Litaleiðrétting"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Litaleiðrétting hjálpar fólki með litblindu að sjá réttari liti"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Hnekkt af <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Um það bil <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Minna en <xliff:g id="THRESHOLD">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Meira en <xliff:g id="TIME_REMAINING">%1$s</xliff:g> eftir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Síminn gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Spjaldtölvan gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Tækið gæti slökkt á sér fljótlega"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Síminn gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Spjaldtölvan gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Tækið gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Síminn gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Spjaldtölvan gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Tækið gæti slökkt á sér fljótlega"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Síminn gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Spjaldtölvan gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Tækið gæti slökkt á sér fljótlega (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> að fullri hleðslu"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> að fullri hleðslu"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Óþekkt"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Í hleðslu"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hröð hleðsla"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Hæg hleðsla"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ekki í hleðslu"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Í sambandi, ekki hægt að hlaða eins og er"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Fullhlaðin"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index c9abc74..f0dba68 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Debug USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modalità debug quando è connesso tramite USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoca autorizzazioni debug USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Debug wireless"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modalità Debug quando il Wi-Fi è connesso"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Errore"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Debug wireless"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Per trovare e utilizzare i dispositivi disponibili, attiva il debug wireless"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Accoppia il dispositivo con il codice QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Accoppia i nuovi dispositivi utilizzando lo scanner di codici QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Accoppia dispositivo con codice di accoppiamento"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Accoppia i nuovi dispositivi utilizzando un codice di sei cifre"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivi accoppiati"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Attualmente connesso"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Dettagli dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Elimina"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Impronta dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Connessione non riuscita"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Assicurati che il dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> sia connesso alla rete corretta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Accoppia con dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Codice di accoppiamento Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Accoppiamento non riuscito"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Assicurati che il dispositivo sia connesso alla stessa rete."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Accoppia il dispositivo tramite Wi-Fi eseguendo la scansione di un codice QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Accoppiamento dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Impossibile accoppiare il dispositivo. Il codice QR non era corretto oppure il dispositivo non è connesso alla stessa rete."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Indirizzo IP e porta"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scansiona codice QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Accoppia il dispositivo tramite Wi-Fi eseguendo la scansione di un codice QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, debug, sviluppatori"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Scorciatoia segnalazione bug"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostra un pulsante per segnalare i bug nel menu di accensione"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Rimani attivo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Utilizza l\'accelerazione hardware per il tethering se disponibile"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Consentire debug USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Il debug USB è solo a scopo di sviluppo. Utilizzalo per copiare dati tra il computer e il dispositivo, per installare applicazioni sul tuo dispositivo senza notifica e per leggere i dati dei log."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Consentire debug wireless?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Il debug wireless è solo a scopo di sviluppo. Utilizzalo per copiare dati tra il computer e il dispositivo, per installare app sul tuo dispositivo senza notifica e per leggere i dati dei log."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revocare l\'accesso al debug USB da tutti i computer precedentemente autorizzati?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Consentire impostazioni di sviluppo?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Queste impostazioni sono utilizzabili solo a scopo di sviluppo. Possono causare l\'arresto o il comportamento anomalo del dispositivo e delle applicazioni su di esso."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalìa (rosso-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalìa (blu-giallo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correzione del colore"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"La correzione del colore consente alle persone daltoniche di vedere colori più accurati"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valore sostituito da <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo rimanente: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> circa"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Tempo rimanente: meno di <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Tempo rimanente: più di <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Il telefono potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Il tablet potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Il dispositivo potrebbe spegnersi a breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Il telefono potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Il tablet potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Il dispositivo potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Il telefono potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Il tablet potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Il dispositivo potrebbe spegnersi a breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Il telefono potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Il tablet potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Il dispositivo potrebbe spegnersi a breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo rimanente alla carica completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> alla carica completa"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Sconosciuta"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"In carica"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ricarica veloce"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Ricarica lenta"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Non in carica"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Collegato alla corrente. Impossibile caricare al momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Carica"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 1921d03..524a87d 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"‏ניפוי באגים ב-USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"‏מצב ניפוי באגים כאשר USB מחובר"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"‏ביטול הרשאות לניפוי ב-USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ניפוי באגים אלחוטי"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"‏מצב ניפוי באגים כשיש חיבור Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"שגיאה"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ניפוי באגים אלחוטי"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"כדי להציג את המכשירים הזמינים ולהשתמש בהם, יש להפעיל ניפוי באגים אלחוטי"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"‏התאמת מכשיר באמצעות קוד QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"‏התאמת מכשירים חדשים באמצעות סורק של קודי QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"התאמת מכשיר באמצעות קוד התאמה"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"התאמת מכשירים חדשים באמצעות קוד בן שש ספרות"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"מכשירים מותאמים"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"מחובר עכשיו"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"פרטי מכשיר"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"אפשר לשכוח"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"המזהה הייחודי של המכשיר: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"החיבור נכשל"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"עליך לוודא שהמכשיר <xliff:g id="DEVICE_NAME">%1$s</xliff:g> מחובר לרשת הנכונה"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"התאמה למכשיר"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‏קוד התאמה של Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ההתאמה נכשלה"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"יש לוודא שהמכשיר מחובר לאותה רשת."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏יש לסרוק קוד QR כדי להתאים מכשיר באמצעות Wi‑Fi"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"המכשיר בתהליך התאמה…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"‏התאמת המכשיר נכשלה. קוד ה-QR היה שגוי או שהמכשיר לא מחובר לאותה רשת."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏יציאה וכתובת IP"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"‏סריקת קוד QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"‏יש לסרוק קוד QR כדי להתאים מכשיר באמצעות Wi‑Fi"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"‏adb, ניפוי באגים, פיתוח"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"קיצור של דוח באגים"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"כדי ליצור דוח באגים, הצג לחצן בתפריט לניהול צריכת החשמל"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"שיישאר פועל"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"אם השירות זמין, יש להשתמש בשיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‏לאפשר ניפוי באגים של USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‏ניפוי באגים באמצעות USB מיועד למטרות פיתוח בלבד. השתמש בו להעתקת נתונים בין המחשב והמכשיר שלך, להתקנת אפליקציות במכשיר ללא התראה ולקריאת נתוני יומן."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"האם לאפשר ניפוי באגים אלחוטי?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ניפוי באגים אלחוטי מיועד למטרות פיתוח בלבד. יש להשתמש בו להעתקת נתונים בין המחשב והמכשיר שלך, להתקנת אפליקציות במכשיר ללא התראה ולקריאת נתוני יומן."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‏האם לבטל את הגישה לניפוי ב-USB מכל המחשבים שהענקת להם בעבר הרשאה?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"האם להתיר הגדרות פיתוח?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"הגדרות אלה מיועדות לשימוש בפיתוח בלבד. הן עלולות לגרום למכשיר או לאפליקציות המותקנות בו לקרוס או לפעול באופן לא תקין."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"פרוטנומליה (אדום-ירוק)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"טריטנומליה (כחול-צהוב)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"תיקון צבע"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"תיקון צבע עוזר לאנשים עם עיוורון צבעים לראות צבעים באופן מדויק יותר"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"נעקף על ידי <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"הזמן הנותר: בערך <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"נותרו פחות מ-<xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"נותרו יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"הזמן שנותר: יותר מ-<xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ייתכן שהטלפון ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ייתכן שהטאבלט ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ייתכן שהמכשיר ייכבה בקרוב"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ייתכן שהטלפון ייכבה בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ייתכן שהטאבלט ייכבה בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ייתכן שהמכשיר ייכבה בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"הטלפון עלול להיכבות בקרוב"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"הטאבלט עלול להיכבות בקרוב"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"המכשיר עלול להיכבות בקרוב"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"הטלפון עלול להיכבות בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"הטאבלט עלול להיכבות בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"המכשיר עלול להיכבות בקרוב (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g>‏ - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"נשארו <xliff:g id="TIME">%1$s</xliff:g> עד הטעינה"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> עד הטעינה"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"לא ידוע"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"בטעינה"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"הסוללה נטענת מהר"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"הסוללה נטענת לאט"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"לא בטעינה"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"המכשיר מחובר, אבל לא ניתן לטעון עכשיו"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"מלאה"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index e4e1ab9..acefe20 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB デバッグ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB接続時はデバッグモードにする"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USBデバッグの許可の取り消し"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ワイヤレス デバッグ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi 接続時にデバッグモード"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"エラー"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ワイヤレス デバッグ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"利用可能なデバイスを確認して使用するには、ワイヤレス デバッグをオンにしてください"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR コードによるデバイスのペア設定"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR コードスキャナを使って新しいデバイスをペア設定します"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ペア設定コードによるデバイスのペア設定"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"6 桁のコードを使って新しいデバイスをペア設定します"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ペア設定済みのデバイス"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"現在接続"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"デバイスの詳細"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"削除"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"デバイスのフィンガープリント: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"接続エラー"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> が正しいネットワークに接続されていることを確認してください"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"デバイスとのペア設定"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi ペア設定コード"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ペア設定エラー"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"デバイスが同じネットワークに接続されていることを確認してください。"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR コードをスキャンして Wi-Fi 経由でデバイスをペア設定します"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"デバイスをペア設定しています…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"デバイスをペア設定できませんでした。QR コードが間違っているか、デバイスが同じネットワークに接続されていません。"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP アドレスとポート"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR コードのスキャン"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR コードをスキャンして Wi-Fi 経由でデバイスをペア設定します"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, デバッグ, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"バグレポートのショートカット"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"電源メニューにバグレポートを取得するボタンを表示する"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"スリープモードにしない"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"テザリング時にハードウェア アクセラレーションを使用します(使用可能な場合)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USBデバッグを許可しますか?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USBデバッグは開発専用に設計されています。パソコンとデバイスの間でデータをコピーする場合や、アプリを通知なしでデバイスにインストールする場合、ログデータを読み取る場合に使用できます。"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ワイヤレス デバッグを許可しますか?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ワイヤレス デバッグは開発専用に設計されています。パソコンとデバイスの間でデータをコピーする場合や、アプリを通知なしでデバイスにインストールする場合、ログデータを読み取る場合に使用できます。"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"以前に許可したすべてのパソコンからのUSBデバッグへのアクセスを取り消しますか?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"開発用の設定を許可しますか?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"これらの設定は開発専用に設計されています。そのためデバイスやデバイス上のアプリが故障したり正常に動作しなくなったりするおそれがあります。"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"第一色弱(赤緑)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"第三色弱(青黄)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色補正"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"色補正機能を利用すると、色覚障がいのある方がより正確に色を判別できるようになります"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g>によって上書き済み"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"残り時間: 約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"残り時間: <xliff:g id="THRESHOLD">%1$s</xliff:g>未満(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"残り時間: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>以上"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"スマートフォンの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"タブレットの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"デバイスの電源がもうすぐ切れます"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"スマートフォンの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"タブレットの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"デバイスの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"スマートフォンの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"タブレットの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"デバイスの電源がもうすぐ切れます"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"スマートフォンの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"タブレットの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"デバイスの電源がもうすぐ切れます(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"充電完了まであと <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 充電完了まで <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"急速充電中"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"低速充電中"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"充電していません"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"接続されていますが、現在、充電できません"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"フル"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index b2cfb17..ddc46ad 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB გამართვა"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"გამართვის რეჟიმი, როდესაც USB შეერთებულია"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB საშუალებით გამართვის შესაძლებლობის გამორთვა"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"შეცდომების უსადენო გამართვა"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"შეცდომების გამართვის რეჟიმი დაკავშირებული Wi-Fi-ის დროს"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"შეცდომა"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"შეცდომების უსადენო გამართვა"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ხელმისაწვდომი მოწყობილობების სანახავად და გამოსაყენებლად ჩართეთ შეცდომების უსადენო გამართვა"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"ახალი მოწყობილობების დაწყვილება QR კოდით"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"ახალი მოწყობილობების დაწყვილება QR კოდის სკანერის გამოყენებით"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"მოწყობილობის დაწყვილება დაკავშირების კოდით"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ახალი მოწყობილობების დაწყვილება ექვსნიშნა კოდის გამოყენებით"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"დაწყვილებული მოწყობილობები"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ამჟამად დაკავშირებულია"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"მოწყობილობის დეტალები"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"დავიწყება"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"მოწყობილობის თითის ანაბეჭდი: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"დაკავშირება წარუმატებლად დასრულდა"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"გადაამოწმეთ, რომ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> დაკავშირებულია საჭირო ქსელთან"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"მოწყობილობასთან დაწყვილება"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi დაკავშირების კოდი"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"დაწყვილება წარუმატებლად დასრულდა"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"გადაამოწმეთ, რომ მოწყობილობა დაკავშირებულია იმავე ქსელთან."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"მოწყობილობის დაწყვილება Wi-Fi-ის მეშვეობით QR კოდის სკანირებით"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"მიმდინარეობს მოწყობილობის დაწყვილება…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"მოწყობილობის დაწყვილება ვერ მოხერხდა. QR კოდი არასწორი იყო ან მოწყობილობა იმავე ქსელთან არ არის დაკავშირებული."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP მისამართი და პორტი"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR კოდის სკანირება"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"მოწყობილობის დაწყვილება Wi-Fi-ის მეშვეობით QR კოდის სკანირებით"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, შეცდომების გამართვა, დეველოპერული"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ხარვეზის შეტყობინების მალსახმობი"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ელკვების პარამეტრებში ხარვეზის შეტყობინების ღილაკის ჩვენება"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"არ დაიძინო"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ტეტერინგის აპარატურული აჩქარების ხელმისაწვდომობის შემთხვევაში გამოყენება"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"ჩაირთოს USB გამართვა?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB გამართვა განკუთვნილია მხოლოდ დეველოპერული მიზნებისთვის. გამოიყენეთ კომპიუტერსა და თქვენ მოწყობილობას შორის მონაცემების გადასატანად, თქვენ მოწყობილობაზე აპების შეტყობინების გარეშე დასაყენებლად და ჟურნალის მონაცემების წასაკითხად."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"დაუშვებთ შეცდომების უსადენო გამართვა?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"შეცდომების უსადენო გამართვა განკუთვნილია მხოლოდ დეველოპერული მიზნებისთვის. გამოიყენეთ ის თქვენს კომპიუტერსა და თქვენს მოწყობილობას შორის მონაცემების დასაკოპირებლად, თქვენს მოწყობილობაზე აპების შეტყობინების გარეშე ინსტალაციისთვის და ჟურნალის მონაცემების წასაკითხად."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"გავაუქმოთ ყველა იმ კომპიუტერიდან USB გამართვაზე წვდომა, რომლებიდანაც აქამდე განახორციელეთ შესვლა?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"გსურთ, დეველოპმენტის პარამეტრების ნების დართვა?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ამ პარამეტრების გამოყენება დასაშვებია მხოლოდ დეველოპერული მიზნებით. მათმა გამოყენებამ შეიძლება გამოიწვიოს თქვენი მოწყობილობის და მისი აპლიკაციების დაზიანება ან გაუმართავი მუშაობა."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"პროტოანომალია (წითელი-მწვანე)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ტრიტანომალია (ლურჯი-ყვითელი)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ფერის კორექცია"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ფერის კორექცია ეხმარება ფერითი სიბრმავის მქონე ადამიანებს, უფრო ზუსტად გაარჩიონ ფერები"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"უკუგებულია <xliff:g id="TITLE">%1$s</xliff:g>-ის მიერ"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"დარჩა დაახლოებით <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"დარჩენილია <xliff:g id="THRESHOLD">%1$s</xliff:g>-ზე ნაკლები დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი დრო (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"დარჩენილია <xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ზე მეტი დრო"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ტელეფონი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ტაბლეტი შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"მოწყობილობა შეიძლება მალე გაითიშოს"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ტელეფონი შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ტაბლეტი შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"მოწყობილობა შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ტელეფონი შეიძლება მალე გათიშოს"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ტაბლეტი შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"მოწყობილობა შეიძლება მალე გაითიშოს"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ტელეფონი შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ტაბლეტი შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"მოწყობილობა შეიძლება მალე გაითიშოს (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"დატენვამდე დარჩა <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> დატენვამდე"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"უცნობი"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"იტენება"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"სწრაფად იტენება"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ნელა იტენება"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"არ იტენება"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"მიერთებულია, დატენვა ამჟამად ვერ ხერხდება"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ბატარეა დატენილია"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index 756bc06..47babb1 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB жөндеу"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB жалғанғандағы жөндеу режимі"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB жөндеу рұқсаттарынан бас тарту"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Сымсыз желі арқылы түзету"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi желісіне жалғанған кездегі түзету режимі"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Қате"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Сымсыз желі арқылы түзету"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Қолжетімді құрылғыларды көру және пайдалану үшін сымсыз желі арқылы түзетуді іске қосыңыз."</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Құрылғыны QR коды арқылы жұптау"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Жаңа құрылғыларды QR коды сканері арқылы жұптау"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Құрылғыны кодпен жұптау"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Жаңа құрылғыларды алты цифрлық код арқылы жұптау"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Жұпталған құрылғылар"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Қазір жалғанып тұрғандар"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Құрылғы мәліметтері"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Ұмыту"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Құрылғыдағы саусақ ізі: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Байланыс орнамады"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> құрылғысының дұрыс желіге жалғанғанын тексеріңіз."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Құрылғымен жұптау"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi жұптау коды"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Жұпталмады"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Құрылғының бір желіге жалғанғанын тексеріңіз."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодын сканерлеп, құрылғыны Wi‑Fi арқылы жұптау"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Құрылғы жұпталуда…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Құрылғы жұпталмады. QR коды дұрыс емес немесе құрылғы бір желіге жалғанбаған."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP мекенжайы және порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодын сканерлеу"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR кодын сканерлеп, құрылғыны Wi‑Fi арқылы жұптау"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, түзету, әзірлеуші"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Қате туралы хабарлау"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Қуат мәзірінде қате туралы хабарлауға арналған түймені көрсету"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ояу тұру"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Тетеринг режиміндегі аппараттық жеделдетуді пайдалану (қолжетімді болса)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB жөндеулеріне рұқсат берілсін бе?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB жөндеу дамыту мақсаттарына ғана арналған. Оны компьютер және құрылғы арасында дерек көшіру, құрылғыға ескертусіз қолданба орнату және тіркелім деректерін оқу үшін қолданыңыз."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Сымсыз желі арқылы түзетуге рұқсат берілсін бе?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Сымсыз желі арқылы түзету функциясы дамыту мақсаттарына ғана арналған. Оны компьютер және құрылғы арасында дерек көшіру, құрылғыға ескертусіз қолданба орнату және журнал деректерін оқу үшін қолданыңыз."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Бұған дейін рұқсат берілген барлық компьютерлерде USB жөндеу функциясына тыйым салынсын ба?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Жетілдіру параметрлеріне рұқсат берілсін бе?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Бұл параметрлер жетілдіру мақсатында ғана қолданылады. Олар құрылғыңыз бен қолданбаларыңыздың бұзылуына немесе әдеттен тыс әрекеттерге себеп болуы мүмкін."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (қызыл-жасыл)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсті түзету"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Түсті түзету функциясы түстерді ажырата алмайтын адамдарға оларды дәлірек көруге көмектеседі"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> үстінен басқан"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Шамамен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> қалды"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> шамасынан аз қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> шамасынан көп уақыт қалды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> шамасынан көп уақыт қалды"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Планшет көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Құрылғы көп ұзамай өшуі мүмкін"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Телефон көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Планшет көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Құрылғы көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Планшет көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Құрылғы көп ұзамай өшуі мүмкін"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшет көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Құрылғы көп ұзамай өшуі мүмкін (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Зарядталғанға дейін <xliff:g id="TIME">%1$s</xliff:g> қалды"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – зарядталғанға дейін <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгісіз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Зарядталуда"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Жылдам зарядталуда"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Баяу зарядталуда"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Зарядталу орындалып жатқан жоқ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Қосылған, зарядталмайды"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Толы"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index cdf92b3..f62408d 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"ការ​កែ​កំហុស​តាម USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"មុខងារកែ​កំហុសពេល​ភ្ជាប់​ USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"ដក​សិទ្ធិ​កែ​កំហុសតាម USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ការជួសជុល​ដោយឥតខ្សែ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"មុខងារ​ជួសជុល នៅពេល​ភ្ជាប់ Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"បញ្ហា"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ការជួសជុល​ដោយឥតខ្សែ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ដើម្បី​មើលឃើញ និងប្រើ​ឧបករណ៍​ដែលមាន សូមបើក​ការជួសជុល​ដោយឥតខ្សែ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"ផ្គូផ្គង​ឧបករណ៍​ដោយប្រើ​កូដ QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"ផ្គូផ្គង​ឧបករណ៍​ថ្មី​ដោយប្រើ​កម្មវិធីស្កេន​កូដ QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ផ្គូផ្គង​ឧបករណ៍​ដោយប្រើ​កូដផ្គូផ្គង"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ផ្គូផ្គង​ឧបករណ៍​ថ្មី​ដោយប្រើ​កូដ​ប្រាំមួយ​ខ្ទង់"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ឧបករណ៍​ដែល​បាន​ផ្គូផ្គង"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"កំពុងភ្ជាប់​បច្ចុប្បន្ននេះ"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ព័ត៌មានលម្អិត​អំពី​ឧបករណ៍"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"បំភ្លេច"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ស្នាមម្រាមដៃ​ឧបករណ៍៖ <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ការតភ្ជាប់​មិន​ជោគជ័យ​ទេ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"សូមប្រាកដថា​បានភ្ជាប់ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ទៅ​បណ្ដាញ​ដែលត្រឹមត្រូវ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ផ្គូផ្គង​ជាមួយ​ឧបករណ៍"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"កូដ​ផ្គូផ្គង Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ការផ្គូផ្គង​មិន​ជោគជ័យ​ទេ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"សូម​ប្រាកដថា​បានភ្ជាប់​ឧបករណ៍​ទៅ​បណ្ដាញ​ដូចគ្នា។"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"ផ្គូផ្គង​ឧបករណ៍​តាមរយៈ Wi‑Fi ដោយស្កេន​កូដ QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"កំពុងផ្គូផ្គង​ឧបករណ៍…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"មិនអាច​ផ្គូផ្គង​ឧបករណ៍​បានទេ។ កូដ QR មិនត្រឹមត្រូវ ឬមិនបានភ្ជាប់​ឧបករណ៍​ទៅ​បណ្ដាញ​ដូចគ្នា។"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"អាសយដ្ឋាន IP និងច្រក"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"ស្កេន​កូដ QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"ផ្គូផ្គង​ឧបករណ៍​តាមរយៈ Wi‑Fi ដោយស្កេន​កូដ QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ជួសជុល, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ផ្លូវកាត់រាយការណ៍​កំហុស"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"បង្ហាញ​​ប៊ូតុង​ក្នុង​ម៉ឺនុយ​ប៊ូតុង​ថាមពល​​​សម្រាប់​ការ​ទទួល​យក​របាយការណ៍​កំហុស"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ទុកឲ្យបើកចោល"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ប្រើការ​បង្កើនល្បឿន​ផ្នែករឹងសម្រាប់​ការភ្ជាប់​ ប្រសិន​បើអាច​ប្រើបាន"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"អនុញ្ញាត​ការ​កែ​កំហុស​តាម USB ឬ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"ការ​កែ​កំហុស​​យូអេសប៊ី​គឺ​សម្រាប់​តែ​ការ​អភិវឌ្ឍ​ប៉ុណ្ណោះ។ ប្រើ​វា​ដើម្បី​ចម្លង​ទិន្នន័យ​រវាង​កុំព្យូទ័រ និង​ឧបករណ៍​របស់​អ្នក ដំឡើង​កម្មវិធី​ក្នុង​ឧបករណ៍​របស់​អ្នក​ដោយ​មិន​ជូន​ដំណឹង និង​អាន​ទិន្នន័យ​កំណត់ហេតុ។"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"អនុញ្ញាត​ការជួសជុល​ដោយឥតខ្សែ​ឬ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ការជួសជុល​ដោយឥតខ្សែ​គឺសម្រាប់​តែ​ការ​អភិវឌ្ឍ​ប៉ុណ្ណោះ។ ប្រើ​ការជួសជុល​ដោយឥតខ្សែ ដើម្បី​ចម្លង​ទិន្នន័យ​រវាង​កុំព្យូទ័រ និង​ឧបករណ៍​របស់អ្នក ដំឡើង​កម្មវិធី​នៅលើ​ឧបករណ៍​របស់អ្នក​ដោយ​គ្មានការ​ជូន​ដំណឹង និង​អាន​ទិន្នន័យ​កំណត់ហេតុ។"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ដក​សិទ្ធិ​ចូល​ការ​កែ​កំហុស​តាម​យូអេសប៊ី​ពី​គ្រប់​កុំព្យូទ័រ​ដែល​អ្នក​បាន​ផ្ដល់​សិទ្ធិ​ពី​មុន?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"អនុញ្ញាត​កំណត់​ការ​អភិវឌ្ឍ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ការ​កំណត់​ទាំង​នេះ​សម្រាប់​តែ​ការ​ប្រើ​ក្នុង​ការ​អភិវឌ្ឍ​ប៉ុណ្ណោះ។ ពួក​វា​អាច​ធ្វើ​ឲ្យ​ឧបករណ៍ និង​កម្មវិធី​របស់​អ្នក​ខូច ឬ​ដំណើរ​មិន​ត្រឹមត្រូវ។"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ក្រហម​ពណ៌​បៃតង​)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ពណ៌​ខៀវ​-លឿង​)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ការ​កែ​ពណ៌"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ការកែតម្រូវ​ពណ៌​ជួយដល់​អ្នកដែល​មិនអាច​បែងចែក​ពណ៌​ឱ្យមើលឃើញ​ពណ៌ដែលត្រឹមត្រូវ​ជាងមុន"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"បដិសេធ​ដោយ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"នៅសល់​ប្រហែល <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ទៀត"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"នៅសល់​តិចជាង <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"នៅសល់​ច្រើនជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"នៅ​សល់​ច្រើន​ជាង <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ទូរសព្ទ​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ទូរសព្ទ​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ទូរសព្ទ​អាច​នឹង​បិទ​ក្នុង​ពេល​បន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ទូរសព្ទ​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ថេប្លេត​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ឧបករណ៍​អាចនឹង​បិទក្នុង​ពេលបន្តិច​ទៀត (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ទៀតទើប​ត្រូវសាក"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"មិន​ស្គាល់"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"កំពុងបញ្ចូល​ថ្ម"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"កំពុងសាកថ្មយ៉ាងឆាប់រហ័ស"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"កំពុង​សាកថ្មយឺត"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"មិនកំពុង​បញ្ចូល​ថ្ម"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ដោត​សាកថ្ម​រួចហើយ ប៉ុន្តែ​​សាកថ្ម​មិន​ចូលទេឥឡូវនេះ"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ពេញ"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index 4a24691..39d6069 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB ಸಂಪರ್ಕಗೊಂಡಾಗ ಡೀಬಗ್ ಮೋಡ್"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ಡೀಬಗ್‌ ಮಾಡುವಿಕೆಯ ಅಧಿಕೃತಗೊಳಿಸುವಿಕೆಗಳನ್ನು ಹಿಂತೆಗೆದುಕೊಳ್ಳಿ"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ವೈ-ಫೈ ಕನೆಕ್ಟ್ ಆದಾಗ ಡೀಬಗ್ ಮೋಡ್"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ದೋಷ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ಲಭ್ಯವಿರುವ ಸಾಧನಗಳನ್ನು ನೋಡಲು ಮತ್ತು ಬಳಸಲು, ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಆನ್ ಮಾಡಿ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR ಕೋಡ್ ಬಳಸಿ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನರ್ ಬಳಸಿ ಹೊಸ ಸಾಧನಗಳನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ಜೋಡಿಸುವ ಕೋಡ್ ಬಳಸಿ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ಆರು ಅಂಕಿಯ ಕೋಡ್ ಬಳಸಿ ಹೊಸ ಸಾಧನಗಳನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ಜೋಡಿಸಲಾದ ಸಾಧನಗಳು"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ಪ್ರಸ್ತುತ ಕನೆಕ್ಟ್ ಮಾಡಲಾಗಿದೆ"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ಸಾಧನದ ವಿವರಗಳು"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ಮರೆತುಬಿಡಿ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ಸಾಧನದ ಫಿಂಗರ್‌ ಪ್ರಿಂಟ್: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ಕನೆಕ್ಷನ್ ವಿಫಲವಾಗಿದೆ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ಸಾಧನವು ಸರಿಯಾದ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ಸಾಧನದ ಜೊತೆಗೆ ಜೋಡಿಸಿ"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ವೈ-ಫೈ ಜೋಡಿಸುವಿಕೆ ಕೋಡ್"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ಜೋಡಿಸುವಿಕೆ ವಿಫಲವಾಗಿದೆ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ಸಾಧನವು ಒಂದೇ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಆಗಿದೆಯೇ ಎಂದು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಿ."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡುವ ಮೂಲಕ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ಸಾಧನವನ್ನು ಜೋಡಿಸಲಾಗುತ್ತಿದೆ…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ಸಾಧನವನ್ನು ಜೋಡಿಸಲು ವಿಫಲವಾಗಿದೆ. QR ಕೋಡ್ ತಪ್ಪಾಗಿದೆ ಅಥವಾ ಸಾಧನವು ಒಂದೇ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಕನೆಕ್ಟ್ ಆಗಿಲ್ಲ."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ವಿಳಾಸ ಮತ್ತು ಪೋರ್ಟ್"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ಕೋಡ್ ಸ್ಕ್ಯಾನ್ ಮಾಡಿ"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR ಕೋಡ್ ಅನ್ನು ಸ್ಕ್ಯಾನ್ ಮಾಡುವ ಮೂಲಕ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ನಲ್ಲಿ ಸಾಧನವನ್ನು ಜೋಡಿಸಿ"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ಡೀಬಗ್, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ದೋಷ ವರದಿಯ ಶಾರ್ಟ್‌ಕಟ್‌‌"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ದೋಷ ವರದಿ ಮಾಡಲು ಪವರ್ ಮೆನುನಲ್ಲಿ ಬಟನ್ ತೋರಿಸು"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ಎಚ್ಚರವಾಗಿರು"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ಹಾರ್ಡ್‌ವೇರ್‌ನ ವೇಗವರ್ಧನೆ ಟೆಥರಿಂಗ್ ಲಭ್ಯವಿದ್ದರೆ ಅದನ್ನು ಬಳಸಿ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ಅಧಿಸೂಚನೆ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಸ್ಥಾಪಿಸಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯನ್ನು ಅನುಮತಿಸಬೇಕೆ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ವೈರ್‌ಲೆಸ್ ಡೀಬಗ್ ಮಾಡುವಿಕೆಯು ಅಭಿವೃದ್ಧಿ ಉದ್ದೇಶಗಳಿಗೆ ಮಾತ್ರ ಆಗಿದೆ. ನಿಮ್ಮ ಕಂಪ್ಯೂಟರ್ ಮತ್ತು ನಿಮ್ಮ ಸಾಧನದ ನಡುವೆ ಡೇಟಾವನ್ನು ನಕಲಿಸಲು, ಅಧಿಸೂಚನೆ ಇಲ್ಲದೆ ನಿಮ್ಮ ಸಾಧನದಲ್ಲಿ ಆ್ಯಪ್‌ಗಳನ್ನು ಇನ್‌ಸ್ಟಾಲ್ ಮಾಡಲು ಮತ್ತು ಲಾಗ್ ಡೇಟಾ ಓದಲು ಅದನ್ನು ಬಳಸಿ."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ನೀವು ಹಿಂದೆ ಅಧಿಕೃತಗೊಳಿಸಿದ ಎಲ್ಲ ಕಂಪ್ಯೂಟರ್‌ಗಳಿಂದ USB ಡೀಬಗ್‌ಗೆ ಪ್ರವೇಶವನ್ನು ರದ್ದುಗೊಳಿಸುವುದೇ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ಅಭಿವೃದ್ಧಿಯ ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ಅನುಮತಿಸುವುದೇ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ಈ ಸೆಟ್ಟಿಂಗ್‌ಗಳು ಅಭಿವೃದ್ಧಿಯ ಬಳಕೆಗೆ ಮಾತ್ರ. ಅವುಗಳು ನಿಮ್ಮ ಸಾಧನ ಮತ್ತು ಅಪ್ಲಿಕೇಶನ್‌‌ಗಳಿಗೆ ಧಕ್ಕೆ ಮಾಡಬಹುದು ಅಥವಾ ಅವು ಸರಿಯಾಗಿ ಕಾರ್ಯನಿರ್ವಹಿಸದಿರುವಂತೆ ಮಾಡಬಹುದು."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ಪ್ರೊಟನೋಮಲಿ (ಕೆಂಪು-ಹಸಿರು)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ಟ್ರಿಟನೋಮಲಿ (ನೀಲಿ-ಹಳದಿ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ಬಣ್ಣದ ತಿದ್ದುಪಡಿ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ವರ್ಣ ಅಂಧತ್ವ ಹೊಂದಿರುವ ಜನರಿಗೆ ಬಣ್ಣಗಳನ್ನು ಹೆಚ್ಚು ನಿಖರವಾಗಿ ವೀಕ್ಷಿಸಲು ಬಣ್ಣ ತಿದ್ದುಪಡಿ ಸಹಾಯ ಮಾಡುತ್ತದೆ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ಮೂಲಕ ಅತಿಕ್ರಮಿಸುತ್ತದೆ"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಉಳಿದಿದೆ"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ಕ್ಕಿಂತ ಕಡಿಮೆ (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು (<xliff:g id="LEVEL">%2$s</xliff:g>) ಬಾಕಿ"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ಕ್ಕಿಂತ ಹೆಚ್ಚು ಸಮಯ ಉಳಿದಿದೆ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ಫೋನ್ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ಟ್ಯಾಬ್ಲೆಟ್‌‌ ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ಸಾಧನವು ಶೀಘ್ರದಲ್ಲೇ ಶಟ್ ಡೌನ್ ಆಗಬಹುದು (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%1$s</xliff:g> ಸಮಯ ಬಾಕಿ ಇದೆ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ಚಾರ್ಜ್ ಆಗಲು <xliff:g id="TIME">%2$s</xliff:g> ಸಮಯ ಬೇಕು"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ಅಪರಿಚಿತ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ಚಾರ್ಜ್ ಆಗುತ್ತಿದೆ"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ವೇಗದ ಚಾರ್ಜಿಂಗ್"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ನಿಧಾನ ಗತಿಯ ಚಾರ್ಜಿಂಗ್"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ಚಾರ್ಜ್‌ ಆಗುತ್ತಿಲ್ಲ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ಪ್ಲಗ್ ಇನ್ ಮಾಡಲಾಗಿದೆ, ಇದೀಗ ಚಾರ್ಜ್ ಮಾಡಲು ಸಾಧ್ಯವಿಲ್ಲ"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ಭರ್ತಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 51896e9..1ac029c 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -190,7 +190,7 @@
     <item msgid="5664310435707146591">"더 빠르게"</item>
     <item msgid="5491266922147715962">"매우 빠르게"</item>
     <item msgid="7659240015901486196">"상당히 빠르게"</item>
-    <item msgid="7147051179282410945">"매우 빠르게"</item>
+    <item msgid="7147051179282410945">"굉장히 빠르게"</item>
     <item msgid="581904787661470707">"가장 빠르게"</item>
   </string-array>
     <string name="choose_profile" msgid="343803890897657450">"프로필 선택"</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB 디버깅"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB가 연결된 경우 디버그 모드 사용"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB 디버깅 권한 승인 취소"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"무선 디버깅"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi가 연결되었을 때 디버그 모드 사용"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"오류"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"무선 디버깅"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"사용 가능한 기기를 보고 사용하려면 무선 디버깅을 사용 설정하세요."</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR 코드로 기기 페어링"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR 코드 스캐너를 사용하여 새 기기 페어링"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"페어링 코드로 기기 페어링"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"6자리 코드를 사용하여 새 기기 페어링"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"페어링된 기기"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"현재 연결된 기기"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"기기 세부정보"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"저장 안함"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"기기 지문: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"연결할 수 없음"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>이(가) 올바른 네트워크에 연결되어 있는지 확인하세요."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"기기 페어링"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi 페어링 코드"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"페어링 실패"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"기기가 동일한 네트워크에 연결되어 있는지 확인하세요"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR 코드를 스캔하여 Wi‑Fi를 통해 기기 페어링"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"기기 페어링 중…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"기기를 페어링할 수 없습니다. QR 코드가 잘못되었거나 기기가 동일한 네트워크에 연결되어 있지 않습니다."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 주소 및 포트"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR 코드 스캔"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR 코드를 스캔하여 Wi‑Fi를 통해 기기 페어링"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, 디버그, 개발자"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"버그 신고 바로가기"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"전원 메뉴에 버그 신고 버튼 표시"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"화면 켜짐 상태 유지"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"가능한 경우 테더링 하드웨어 가속 사용"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB 디버깅을 허용하시겠습니까?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB 디버깅은 개발용으로만 설계되었습니다. 이 기능을 사용하면 컴퓨터와 기기 간에 데이터를 복사하고 알림 없이 기기에 앱을 설치하며 로그 데이터를 읽을 수 있습니다."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"무선 디버깅을 허용하시겠습니까?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"무선 디버깅은 개발용으로만 설계되었습니다. 이 기능을 사용하면 컴퓨터와 기기 간에 데이터를 복사하고 알림 없이 기기에 앱을 설치하며 로그 데이터를 읽을 수 있습니다."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"이전에 승인한 모든 컴퓨터에서 USB 디버깅에 대한 액세스 권한을 취소하시겠습니까?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"개발자 설정을 허용하시겠습니까?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"이 설정은 개발자용으로만 설계되었습니다. 이 설정을 사용하면 기기 및 애플리케이션에 예기치 않은 중단이나 오류가 발생할 수 있습니다."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"적색약(적녹)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"청색약(청황)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"색보정"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"색상 보정을 사용하면 색맹인 사용자가 색상을 정확하게 구분하는 데 도움이 됩니다."</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> 우선 적용됨"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>, <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"남은 시간 약 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> 미만 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> 이상 남음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"휴대전화가 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"태블릿이 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"기기가 곧 종료될 수 있음"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"휴대전화가 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"태블릿이 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"기기가 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"휴대전화가 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"태블릿이 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"기기가 곧 종료될 수 있음"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"휴대전화가 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"태블릿이 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"기기가 곧 종료될 수 있음(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"충전 완료까지 <xliff:g id="TIME">%1$s</xliff:g> 남음"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 충전 완료까지 <xliff:g id="TIME">%2$s</xliff:g> 남음"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"알 수 없음"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"충전 중"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"고속 충전 중"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"저속 충전 중"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"충전 안함"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"전원이 연결되었지만 현재 충전할 수 없음"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"충전 완료"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 061f6fd..2070056 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -31,7 +31,7 @@
     <string name="wifi_disabled_password_failure" msgid="6892387079613226738">"Аутентификация маселеси бар"</string>
     <string name="wifi_cant_connect" msgid="5718417542623056783">"Туташпай жатат"</string>
     <string name="wifi_cant_connect_to_ap" msgid="3099667989279700135">"\"<xliff:g id="AP_NAME">%1$s</xliff:g>\" тармагына туташпай койду"</string>
-    <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Сырсөздү текшерип, кайра аракет кылыңыз."</string>
+    <string name="wifi_check_password_try_again" msgid="8817789642851605628">"Сырсөздү текшерип, кайталап көрүңүз."</string>
     <string name="wifi_not_in_range" msgid="1541760821805777772">"Тейлөө аймагында эмес"</string>
     <string name="wifi_no_internet_no_reconnect" msgid="821591791066497347">"Автоматтык түрдө туташпайт"</string>
     <string name="wifi_no_internet" msgid="1774198889176926299">"Интернетке туташпай турат"</string>
@@ -125,7 +125,7 @@
     <string name="bluetooth_talkback_phone" msgid="868393783858123880">"Телефон"</string>
     <string name="bluetooth_talkback_imaging" msgid="8781682986822514331">"Сүрөт тартуучу түзмөк"</string>
     <string name="bluetooth_talkback_headphone" msgid="8613073829180337091">"Кулакчын"</string>
-    <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Дайындарды киргизүүчү сырткы түзмөк"</string>
+    <string name="bluetooth_talkback_input_peripheral" msgid="5133944817800149942">"Дайындарды киргизүүчү тышкы түзмөк"</string>
     <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"Bluetooth"</string>
     <string name="bluetooth_hearingaid_left_pairing_message" msgid="8561855779703533591">"Угуу аппаратынын сол кулагы жупташтырылууда…"</string>
     <string name="bluetooth_hearingaid_right_pairing_message" msgid="2655347721696331048">"Угуу аппаратынын оң кулагы жупташтырылууда…"</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB аркылуу мүчүлүштүктөрдү оңдоо"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB компьютерге сайылганда мүчүлүштүктөрдү оңдоо режими иштейт"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB аркылуу мүчүлүштүктөрдү оңдоо уруксатын артка кайтаруу"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Мүчүлүштүктөрдү зымсыз оңдоо"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi\'га туташтырылганда мүчүлүштүктөрдү оңдоо режими"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Ката"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Мүчүлүштүктөрдү зымсыз оңдоо"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Жеткиликтүү түзмөктөрдү көрүү үчүн мүчүлүштүктөрдү зымсыз оңдоону күйгүзүңүз"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR кодун колдонуп, түзмөктү жупташтырыңыз"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR кодунун сканерин колдонуп, жаңы түзмөктөрдү жупташтырыңыз"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Жупташтыруучу код менен түзмөктү жупташтырыңыз"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Алты сандан турган кодду колдонуп, жаңы түзмөктөрдү жупташтырыңыз"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Жупташтырылган түзмөктөр"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Учурда туташып турган түзмөктөр"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Түзмөктүн чоо-жайы"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Унутулсун"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Түзмөктөгү манжа изи: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Туташкан жок"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> туура тармакка туташып турганын текшериңиз"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Түзмөктү жупташтыруу"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi жупташтыруучу коду"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Жупташтырылган жок"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Түзмөк бир тармакка туташканын текшериңиз."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Түзмөк жупташтырылууда…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Түзмөк жупташтырылган жок. QR коду туура эмес же түзмөк бир тармакка туташпай турат."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP дареги жана Оюкча"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR кодун скандоо"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR кодун скандап, түзмөктү Wi‑Fi аркылуу жупташтырыңыз"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, мүчүлүштүктөрдү оңдоо, иштеп чыгуу"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ката жөнүндө кабарлоо"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Менюда ката жөнүндө кабарлоо баскычы көрүнүп турат"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ойгоо туруу"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Мүмкүнчүлүккө жараша, модем режиминде аппарат тезирээк иштей баштайт"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB аркылуу жөндөөгө уруксат бересизби?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-жөндөө - өндүрүү максатында гана  түзүлгөн. Аны компүтериңиз менен түзмөгүңүздүн ортосунда берилиштерди алмашуу, түзмөгүңүзгө колдонмолорду эскертүүсүз орнотуу жана лог берилиштерин окуу үчүн колдонсоңуз болот."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Мүчүлүштүктөрдү зымсыз оңдоого уруксат берилсинби?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Мүчүлүштүктөрдү зымсыз оңдоо – өндүрүү максатында гана түзүлгөн. Аны компьютериңиз менен түзмөгүңүздүн ортосунда маалыматты алмашуу, колдонмолорду түзмөгүңүзгө эскертүүсүз орнотуу жана маалыматтар таржымалын окуу үчүн колдонсоңуз болот."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Сиз мурун USB жөндөөлөрүнө уруксат берген бардык компүтерлердин жеткиси жокко чыгарылсынбы?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Жөндөөлөрдү өзгөртүү"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Бул орнотуулар өндүрүүчүлөр үчүн гана берилген. Булар түзмөгүңүздүн колдонмолорун бузулушуна же туура эмес иштешине алып келиши мүмкүн."</string>
@@ -368,7 +397,7 @@
     <string name="runningservices_settings_summary" msgid="1046080643262665743">"Учурда иштеп жаткан кызматтарды көрүп, көзөмөлдөп турасыз"</string>
     <string name="select_webview_provider_title" msgid="3917815648099445503">"WebView кызматы"</string>
     <string name="select_webview_provider_dialog_title" msgid="2444261109877277714">"WebView аткарылышын коюу"</string>
-    <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Тандалган нерсе жараксыз болуп калган. Кайра аракет кылыңыз."</string>
+    <string name="select_webview_provider_toast_text" msgid="8512254949169359848">"Тандалган нерсе жараксыз болуп калган. Кайталап көрүңүз."</string>
     <string name="convert_to_file_encryption" msgid="2828976934129751818">"Файлдарды шифрлөөгө өтүү"</string>
     <string name="convert_to_file_encryption_enabled" msgid="840757431284311754">"Айландыруу…"</string>
     <string name="convert_to_file_encryption_done" msgid="8965831011811180627">"Файл мурунтан эле шифрленген"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (кызыл-жашыл)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (көк-сары)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Түсүн тууралоо"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Түстү тууралоо жөндөөсү түстөрдү айырмалап көрбөгөн адамдарга түстөрдү тагыраак билүүгө жардам берет"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> менен алмаштырылган"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Болжол менен <xliff:g id="TIME_REMAINING">%1$s</xliff:g> калды"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> жетпеген убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ашыгыраак убакыт калды (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ашыгыраак убакыт калды"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Планшет бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Телефон бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Планшет бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Түзмөк бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Планшет бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Түзмөк бир аздан кийин өчүп калышы мүмкүн"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшет бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Түзмөк бир аздан кийин өчүп калышы мүмкүн (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> кийин кубатталат"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> кийин кубатталат"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Белгисиз"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Кубатталууда"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ыкчам кубатталууда"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Жай кубатталууда"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Кубат алган жок"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Сайылып турат, учурда кубаттоо мүмкүн эмес"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Толук"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index bfbd8a9..5d504d4 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"ການດີບັ໊ກຜ່ານ USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"ເປີດໃຊ້ໂໝດດີບັ໊ກເມື່ອເຊື່ອມຕໍ່ USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"ຖອດຖອນການອະນຸຍາດການດີບັ໊ກຜ່ານ USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ການດີບັກໄຮ້ສາຍ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ໂໝດດີບັກເມື່ອເຊື່ອມຕໍ່ Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ຜິດພາດ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ການດີບັກໄຮ້ສາຍ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ເພື່ອເບິ່ງ ແລະ ໃຊ້ອຸປະກອນທີ່ມີຢູ່, ກະລຸນາເປີດການດີບັກໄຮ້ສາຍ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"ຈັບຄູ່ອຸປະກອນດ້ວຍລະຫັດ QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"ຈັບຄູ່ອຸປະກອນໃໝ່ໂດຍໃຊ້ຕົວສະແກນລະຫັດ QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ຈັບຄູ່ອຸປະກອນໂດຍໃຊ້ລະຫັດການຈັບຄູ່"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ຈັບຄູ່ອຸປະກອນໃໝ່ໂດຍໃຊ້ລະຫັດຫົກຕົວເລກ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ອຸປະກອນທີ່ຈັບຄູ່ແລ້ວ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ຕອນນີ້ເຊື່ອມຕໍ່ແລ້ວ"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ລາຍລະອຽດອຸປະກອນ"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ລືມ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ລາຍນິ້ວມືອຸປະກອນ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ການເຊື່ອມຕໍ່ບໍ່ສຳເລັດ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"ກະລຸນາກວດສອບວ່າ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍດຽວກັນແລ້ວ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ຈັບຄູ່ອຸປະກອນໃໝ່"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ລະຫັດການຈັບຄູ່ Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ການຈັບຄູ່ບໍ່ສຳເລັດ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ກະລຸນາກວດສອບວ່າອຸປະກອນເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍດຽວກັນແລ້ວ."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"ຈັບຄູ່ອຸປະກອນຜ່ານ Wi‑Fi ໂດຍການສະແກນລະຫັດ QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ກຳລັງຈັບຄູ່ອຸປະກອນ…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ຈັບຄູ່ອຸປະກອນບໍ່ສຳເລັດ. ລະຫັດ QR ບໍ່ຖືກຕ້ອງ ຫຼື ອຸປະກອນບໍ່ໄດ້ເຊື່ອມຕໍ່ຫາເຄືອຂ່າຍດຽວກັນ."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"ທີ່ຢູ່ IP ແລະ ຜອດ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"ສະແກນລະຫັດ QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"ຈັບຄູ່ອຸປະກອນຜ່ານ Wi‑Fi ໂດຍການສະແກນລະຫັດ QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ທາງ​ລັດລ​າຍງານ​ຂໍ້​ຜິດພາດ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"​ສະ​ແດງ​ປຸ່ມ​ໃນ​ເມ​ນູ​ປິດ​ເປີດ​ເພື່ອ​ບັນ​ທຶກ​ການ​ລາຍ​ງານ​ຂໍ້​ຜິດ​ພາດ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ເປີດໜ້າຈໍຕະຫຼອດ"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວຫາກວ່າສາມາດໃຊ້ໄດ້"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"ອະນຸຍາດໃຫ້ດີບັ໊ກຜ່ານ USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"ການດີບັ໊ກຜ່ານ USB ແມ່ນມີຈຸດປະສົງເພື່ອການພັດທະນາເທົ່ານັ້ນ. ມັນສາມາດໃຊ້ເພື່ອສຳເນົາຂໍ້ມູນລະຫວ່າງຄອມພິວເຕີ ແລະອຸປະກອນຂອງທ່ານ, ຕິດຕັ້ງແອັບຯໂດຍບໍ່ຜ່ານການແຈ້ງເຕືອນ ແລະອ່ານຂໍ້ມູນການບັນທຶກ."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ອະນຸຍາດການດີບັກໄຮ້ສາຍບໍ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ການດີບັກໄຮ້ສາຍແມ່ນມີຈຸດປະສົງສຳລັບການພັດທະນາເທົ່ານັ້ນ. ມັນສາມາດໃຊ້ເພື່ອສຳເນົາຂໍ້ມູນລະຫວ່າງຄອມພິວເຕີ ແລະ ອຸປະກອນຂອງທ່ານ, ຕິດຕັ້ງແອັບໂດຍບໍ່ຜ່ານການແຈ້ງເຕືອນ ແລະ ອ່ານຂໍ້ມູນບັນທຶກ."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ຖອດຖອນການເຂົ້າເຖິງການດີບັ໊ກຜ່ານ USB ຈາກຄອມພິວເຕີທຸກເຄື່ອງ ທີ່ທ່ານເຄີຍອະນຸຍາດກ່ອນໜ້ານີ້?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ອະນຸຍາດການຕັ້ງຄ່າສຳລັບນັກພັດທະນາ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ການ​ຕັ້ງຄ່າ​ເຫຼົ່ານີ້​ແມ່ນ​ມີ​ຈຸດປະສົງ​ເພື່ອ​ການ​ພັດທະນາ​ເທົ່ານັ້ນ. ພວກ​ມັນ​ສາມາດ​ເຮັດ​ໃຫ້​ອຸປະກອນ ແລະ​ແອັບພລິເຄຊັນ​ຂອງ​ທ່ານ​ຢຸດ​ເຮັດ​ວຽກ ຫຼື​ເຮັດ​ວຽກ​ຜິດປົກກະຕິ​ໄດ້."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ສີ​ແດງ​-ສີ​ຂຽວ​)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ສີ​ຟ້າ​-ສີ​ເຫຼືອງ​)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ການ​ປັບ​ແຕ່ງ​ສີ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ການແກ້ໄຂສີຈະຊ່ວຍໃຫ້ຄົນທີ່ຕາບອດສີສາມາດເບິ່ງເຫັນສີໄດ້ຖືກຕ້ອງຍິ່ງຂຶ້ນ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"ຖືກແທນໂດຍ <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"ເຫຼືອອີກປະມານ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"ຍັງເຫຼືອໜ້ອຍກວ່າ <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"ຍັງເຫຼືອຫຼາຍກວ່າ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ແທັບເລັດອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ໂທລະສັບອາດຈະປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ແທັບເລັດອາດຈະປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ອຸປະກອນອາດຈະປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ໂທລະສັບອາດປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ແທັບເລັດອາດປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ອຸປະກອນອາດປິດໃນໄວໆນີ້"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ໂທລະສັບອາດປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ແທັບເລັດອາດປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ອຸປະກອນອາດປິດໃນໄວໆນີ້ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ຈົນກວ່າຈະສາກເຕັມ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ບໍ່ຮູ້ຈັກ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ກຳລັງສາກໄຟ"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ກຳລັງສາກໄຟດ່ວນ"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ກຳລັງສາກໄຟຊ້າໆ"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ບໍ່ໄດ້ສາກໄຟ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ສຽບສາຍແລ້ວ, ບໍ່ສາມາດສາກໄດ້ໃນຕອນນີ້"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ເຕັມ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 76d06fa..6cdb547 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB perkrova"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Derinimo režimas, kai prijungtas USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Panaikinti USB derinimo prieigos teises"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Belaidžio ryšio derinimas"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Derinimo režimas, kai prisijungta prie „Wi‑Fi“"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Klaida"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Belaidžio ryšio derinimas"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Jei norite peržiūrėti ir naudoti pasiekiamus įrenginius, įjunkite belaidžio ryšio derinimą"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Įrenginio susiejimas naudojant QR kodą"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Susiekite naujus įrenginius naudodami QR kodų skaitytuvą"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Įrenginio susiejimas naudojant susiejimo kodą"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Susiekite naujus įrenginius naudodami šešių skaitmenų kodą"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Susieti įrenginiai"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Šiuo metu prisijungta"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Išsami įrenginio informacija"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Pamiršti"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Įrenginio kontrolinis kodas: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Nepavyko užmegzti ryšio"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Įsitikinkite, kad <xliff:g id="DEVICE_NAME">%1$s</xliff:g> prijungtas prie tinkamo tinklo"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Susiejimas su įrenginiu"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"„Wi‑Fi“ susiejimo kodas"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Nepavyko susieti"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Įsitikinkite, kad įrenginys prijungtas prie to paties tinklo."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Susiekite įrenginį „Wi‑Fi“ ryšiu nuskaitydami QR kodą"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Susiejamas įrenginys…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Nepavyko susieti įrenginio. Netinkamas QR kodas arba įrenginys neprijungtas prie to paties tinklo."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresas ir prievadas"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodo nuskaitymas"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Susiekite įrenginį „Wi‑Fi“ ryšiu nuskaitydami QR kodą"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, derinti, kūrėjas"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Pranešimo apie riktą spartusis klavišas"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Rodyti pranešimo apie riktą mygtuką maitinimo meniu"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Veikti"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Naudoti įrenginio kaip modemo naudojimo aparatinės įrangos spartinimą, jei pasiekiama"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Leisti USB perkrovimą?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB derinimas skirtas naudoti tik kūrimo tikslais. Jis gali būti naudojamas norint kopijuoti duomenis iš kompiuterio į įrenginį ir atvirkščiai, įdiegti programas įrenginyje be pranešimo ir skaityti žurnalo duomenis."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Leisti belaidžio ryšio derinimą?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Belaidžio ryšio derinimas skirtas naudoti tik kūrimo tikslais. Jis gali būti naudojamas norint kopijuoti duomenis iš kompiuterio į įrenginį ir atvirkščiai, įdiegti programas įrenginyje be pranešimo ir skaityti žurnalo duomenis."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Panaikinti visų kompiuterių, kuriems anksčiau suteikėte prieigos teisę, prieigą prie USB derinimo?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Leisti kūrėjų nustatymus?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Šie nustatymai skirti tik kūrėjams. Nustačius juos įrenginys ir jame naudojamos programos gali nustoti veikti arba veikti netinkamai."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (raudona, žalia)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (mėlyna, geltona)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Spalvų taisymas"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Naudojant spalvų taisymo funkciją daltonikai gali geriau matyti spalvas"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nepaisyta naudojant nuostatą „<xliff:g id="TITLE">%1$s</xliff:g>“"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Liko maždaug <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Liko mažiau nei <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Liko daugiau nei <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefonas netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Planšetinis komp. netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Įrenginys netrukus gali būti išjungtas"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefonas netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Planšetinis kompiuteris netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Įrenginys netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefonas netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Planšetinis komp. netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Įrenginys netrukus gali būti išjungtas"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefonas netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Planšetinis komp. netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Įrenginys netrukus gali būti išjungtas (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Iki visiškos įkrovos liko <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – iki visiškos įkrovos liko <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nežinomas"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Kraunasi..."</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Greitai įkraunama"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lėtai įkraunama"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nekraunama"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Įjungta į maitinimo lizdą, bet šiuo metu įkrauti neįmanoma"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Visiškai įkrautas"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index e4652d1..8257d53 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB atkļūdošana"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Atkļūdošanas režīms, kad ir pievienota kopne USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Atsaukt piekļuvi USB atkļūdošanai"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bezvadu atkļūdošana"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Atkļūdošanas režīms, kad Wi-Fi savienojums ir izslēgts"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Kļūda"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bezvadu atkļūdošana"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Lai skatītu un izmantotu pieejamās ierīces, ieslēdziet bezvadu atkļūdošanu."</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Ierīču savienošana pārī, izmantojot QR kodu"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Savienot pārī jaunas ierīces, izmantojot QR koda skeneri"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Ierīču savienošana pārī, izmantojot kodu"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Savienojiet pārī jaunas ierīces, izmantojot sešu ciparu kodu"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Pārī savienotās ierīces"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Pašlaik pievienota"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Ierīces dati"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Neiegaumēt"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Ierīces ciparnospiedums: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Neizdevās izveidot savienojumu"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Ierīcei <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ir jābūt izveidotam savienojumam ar pareizo tīklu."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Savienošana pārī ar ierīci"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi kods savienošanai pārī"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Neizdevās izveidot savienojumu pārī"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Ierīcei ir jābūt izveidotam savienojumam ar to pašu tīklu."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Izveidojiet savienojumu pārī ar ierīci Wi‑Fi tīklā, skenējot QR kodu."</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Notiek savienošana pārī ar ierīci…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Neizdevās izveidot savienojumu pārī ar ierīci. QR kods nebija pareizs, vai ierīcei nebija izveidots savienojums ar to pašu tīklu."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adrese un ports"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR koda skenēšana"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Izveidojiet savienojumu pārī ar ierīci Wi‑Fi tīklā, skenējot QR kodu."</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, atkļūdošana, izstrādātājiem"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Kļūdu pārskata saīsne"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Izslēgšanas izvēlnē rādīt kļūdu pārskata veidošanas pogu"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Atstāt nomodā"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Izmantot paātrinātu aparatūras darbību piesaistei, ja tā ir pieejama"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Vai atļaut USB atkļūdošanu?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB atkļūdošana ir paredzēta tikai ar izstrādi saistītām darbībām. Izmantojiet to datu kopēšanai no datora uz ierīci un pretēji, lietotņu instalēšanai ierīcē bez paziņojumiem un žurnāla datu lasīšanai."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vai atļaut bezvadu atkļūdošanu?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bezvadu atkļūdošana ir paredzēta tikai ar izstrādi saistītām darbībām. Izmantojiet to datu kopēšanai no datora uz ierīci un pretēji, lietotņu instalēšanai ierīcē bez paziņojumiem un žurnāla datu lasīšanai."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Vai atcelt piekļuvi USB atkļūdošanai no visiem datoriem, kuriem iepriekš piešķīrāt piekļuvi?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Vai atļaut izstrādes iestatījumus?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Šie iestatījumi ir paredzēti tikai izstrādei. To dēļ var tikt pārtraukta vai traucēta ierīces un lietojumprogrammu darbība."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomālija (sarkans/zaļš)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomālija (zils/dzeltens)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Krāsu korekcija"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Krāsu korekcija palīdz lietotājiem ar krāsu aklumu redzēt precīzākas krāsas."</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Jaunā preference: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> — <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Aptuvenais atlikušais laiks: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Atlicis mazāk nekā <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Atlicis vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Atlicis vairāk nekā <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Iespējams, tālrunis drīz izslēgsies"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Iespējams, planšetdators drīz izslēgsies"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Iespējams, ierīce drīz izslēgsies"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Iespējams, tālrunis drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Iespējams, planšetdators drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Iespējams, ierīce drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Tālrunis, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Planšetdators, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Ierīce, iespējams, drīz izslēgsies."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Tālrunis, iespējams, drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Planšetdators, iespējams, drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Ierīce, iespējams, drīz izslēgsies (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Vēl <xliff:g id="TIME">%1$s</xliff:g> līdz pilnai uzlādei"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> — <xliff:g id="TIME">%2$s</xliff:g> līdz pilnai uzlādei"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nezināms"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Uzlāde"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Notiek ātrā uzlāde"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Notiek lēnā uzlāde"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenotiek uzlāde"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Pievienots, taču pašlaik nevar veikt uzlādi"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Pilns"</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 21b2f96..ae2df9a 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Отстранување грешки на USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Режим на отстранување грешки кога е поврзано USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Отповикај овластувања за отстранување грешки од USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Безжично отстранување грешки"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим на отстранување грешки кога е поврзано Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Безжично отстранување грешки"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"За да ги гледате и користите достапните уреди, вклучете го безжичното отстранување грешки"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Спарете уред преку QR-код"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Спарете нови уреди преку скенер за QR-код"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Спарете уред преку код за спарување"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Спарете нови уреди преку шестцифрен код"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Спарени уреди"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Моментално поврзан"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Детали за уредот"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Заборави"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Отпечаток на уредот: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Врската е неуспешна"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Уверете се дека <xliff:g id="DEVICE_NAME">%1$s</xliff:g> е поврзан на точната мрежа"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Спарете со уред"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код за спарување преку Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Спарувањето е неуспешно"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Уверете се дека уредот е поврзан на истата мрежа."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Спарете го уредот преку Wi‑Fi со скенирање QR-код"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Се спарува уред…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Уредот не успеа да се спари. Или QR-кодот беше погрешен или уредот не е поврзан на истата мрежа."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адреса и порта"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Скенирајте QR-код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Спарете го уредот преку Wi‑Fi со скенирање QR-код"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отстранува грешка, програмер"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Кратенка за извештај за грешка"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Прикажи копче во менито за вклучување за да се направи извештај за грешка"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Остани во активен режим"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Ако е достапно, користи хардверско забрзување за врзување"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Овозможи отстранување грешки на USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Отстранувањето грешки на USB е наменето само за целите на развој. Користете го за копирање податоци меѓу вашиот компјутер и вашиот уред, за инсталирање апликации на вашиот уред без известување и за читање евиденција на податоци."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Да се дозволи безжично отстранување грешки?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Безжичното отстранување грешки е наменето само за развојни цели. Користете го за копирање податоци помеѓу компјутерот и уредот, за инсталирање апликации на уредот без известување и за читање податоци од евиденцијата."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Отповикај пристап кон отстранување грешка од USB од сите претходно овластени компјутери?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Дозволи поставки за развој?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Овие поставки се наменети само за употреба за развој. Тие може да предизвикаат уредот и апликациите во него да се расипат или да се однесуваат необично."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (слепило за црвена и зелена)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (слепило за сина и жолта)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција на бои"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Корекцијата на бои им помага на луѓето што не ги разликуваат боите попрецизно да ги гледаат"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Прескокнато според <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Уште околу <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Уште помалку од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Уште повеќе од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Таблетот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Уредот може да се исклучи наскоро"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Телефон може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Таблетот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Уредот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Таблетот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Уредот може да се исклучи наскоро"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Таблетот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Уредот може да се исклучи наскоро (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Уште <xliff:g id="TIME">%1$s</xliff:g> до целосно полнење"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> до целосно полнење"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Се полни"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо полнење"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Бавно полнење"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не се полни"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Приклучен е, но батеријата не може да се полни во моментов"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Полна"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 85aa000..8727755 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -206,6 +206,60 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ഡീബഗ്ഗിംഗ്"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB കണ‌ക്റ്റുചെയ്‌തിരിക്കുമ്പോഴുള്ള ഡീബഗ് മോഡ്"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ഡീബഗ്ഗിംഗ് അംഗീകാരം പിൻവലിക്കുക"</string>
+    <!-- no translation found for enable_adb_wireless (6973226350963971018) -->
+    <skip />
+    <!-- no translation found for enable_adb_wireless_summary (7344391423657093011) -->
+    <skip />
+    <!-- no translation found for adb_wireless_error (721958772149779856) -->
+    <skip />
+    <!-- no translation found for adb_wireless_settings (2295017847215680229) -->
+    <skip />
+    <!-- no translation found for adb_wireless_list_empty_off (1713707973837255490) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_title (6982904096137468634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_summary (3729901496856458634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_title (1122590300445142904) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_summary (6370414511333685185) -->
+    <skip />
+    <!-- no translation found for adb_paired_devices_title (5268997341526217362) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_connected_summary (3039660790249148713) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_details_title (7129369670526565786) -->
+    <skip />
+    <!-- no translation found for adb_device_forget (193072400783068417) -->
+    <skip />
+    <!-- no translation found for adb_device_fingerprint_title_format (291504822917843701) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_title (664211177427438438) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_message (9213896700171602073) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_title (7141739231018530210) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_pairing_code_label (3639239786669722731) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_title (3426758947882091735) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_msg (6611097519661997148) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_summary (8051414549011801917) -->
+    <skip />
+    <!-- no translation found for adb_wireless_verifying_qrcode_text (6123192424916029207) -->
+    <skip />
+    <!-- no translation found for adb_qrcode_pairing_device_failed_msg (6936292092592914132) -->
+    <skip />
+    <!-- no translation found for adb_wireless_ip_addr_preference_title (8335132107715311730) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_title (1906409667944674707) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_description (8578868049289910131) -->
+    <skip />
+    <!-- no translation found for keywords_adb_wireless (6507505581882171240) -->
+    <skip />
     <string name="bugreport_in_power" msgid="8664089072534638709">"ബഗ് റിപ്പോർട്ട് കുറുക്കുവഴി"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ബഗ് റിപ്പോർട്ട് എടുക്കുന്നതിന് പവർ മെനുവിൽ ഒരു ബട്ടൺ കാണിക്കുക"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"സജീവമായി തുടരുക"</string>
@@ -271,6 +325,10 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ലഭ്യമാണെങ്കിൽ \'ടെതറിംഗ് ഹാർഡ്‌വെയർ ത്വരിതപ്പെടുത്തൽ\' ഉപയോഗിക്കുക"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ഡീബഗ്ഗുചെയ്യാൻ അനുവദിക്കണോ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ഡീബഗ്ഗിംഗ് വികസന ആവശ്യകതകൾക്ക് മാത്രമുള്ളതാണ്. നിങ്ങളുടെ കമ്പ്യൂട്ടറിനും ഉപകരണത്തിനുമിടയിൽ ഡാറ്റ പകർത്തുന്നതിനും അറിയിപ്പില്ലാതെ തന്നെ നിങ്ങളുടെ ഉപകരണത്തിൽ അപ്ലിക്കേഷനുകൾ ഇൻസ്‌റ്റാളുചെയ്യുന്നതിനും ലോഗ് ഡാറ്റ റീഡുചെയ്യുന്നതിനും ഇത് ഉപയോഗിക്കുക."</string>
+    <!-- no translation found for adbwifi_warning_title (727104571653031865) -->
+    <skip />
+    <!-- no translation found for adbwifi_warning_message (8005936574322702388) -->
+    <skip />
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"നിങ്ങൾ മുമ്പ് അംഗീകരിച്ച എല്ലാ കമ്പ്യൂട്ടറുകളിൽ നിന്നും USB ഡീബഗ്ഗുചെയ്യുന്നതിനുള്ള ആക്‌സസ്സ് പിൻവലിക്കണോ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"വികസന ക്രമീകരണങ്ങൾ അനുവദിക്കണോ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ഈ ക്രമീകരണങ്ങൾ വികസന ഉപയോഗത്തിന് മാത്രമായുള്ളതാണ്. അവ നിങ്ങളുടെ ഉപകരണവും അതിലെ അപ്ലിക്കേഷനുകളും തകരാറിലാക്കുന്നതിനോ തെറ്റായി പ്രവർത്തിക്കുന്നതിനോ ഇടയാക്കാം."</string>
@@ -403,12 +461,18 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-ൽ കുറവ് സമയം ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-ൽ കൂടുതൽ സമയം ശേഷിക്കുന്നു"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ഫോൺ ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ടാബ്‌ലെറ്റ് ഉടൻ ഷട്ട് ഡൗൺ ആയേക്കാം (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ഉപകരണം ഉടൻ ഷട്ട്ഡൗൺ ആയേക്കാം (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (137330009791560774) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (145489081521468132) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1070562682853942350) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4429259621177089719) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7703677921000858479) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4374784375644214578) -->
+    <skip />
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%1$s</xliff:g> ശേഷിക്കുന്നു"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - പൂർണ്ണമായി ചാർജാവാൻ <xliff:g id="TIME">%2$s</xliff:g>"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 232148a..dc57b3b 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB дебаг"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB холбодсон үеийн согог засах горим"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB дебагын зөвшөөрлийг хураах"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Утасгүй алдаа засах"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi холбогдсон үед дебаг хийх горим"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Алдаа"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Утасгүй алдаа засах"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Боломжтой төхөөрөмжүүдийг харах болох ашиглахын тулд утасгүй алдаа засахыг асаана уу"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Хурдан хариу үйлдлийн кодоор төхөөрөмжийг хослуул"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Хурдан хариу үйлдлийн кодын сканнерыг ашиглан шинэ төхөөрөмжүүдийг хослуулна уу"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Хослуулах кодоор төхөөрөмжийг хослуулна уу"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Зургаан оронтой кодыг ашиглан шинэ төхөөрөмжүүдийг хослуулна уу"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Хослуулсан төхөөрөмжүүд"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Одоогоор холбогдсон байна"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Төхөөрөмжийн дэлгэрэнгүй"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Мартах"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Төхөөрөмжийн хурууны хээ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Холболт амжилтгүй боллоо"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>-г зөв сүлжээнд холбосон эсэхийг шалгана уу"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Төхөөрөмжтэй хослуулах"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi хослуулах код"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Хослуулалт амжилтгүй боллоо"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Төхөөрөмжийг ижил сүлжээнд холбосон эсэхийг шалгана уу."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Хурдан хариу үйлдлийн кодыг скан хийж Wi-Fi-р төхөөрөмжийг хослуулна уу"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Төхөөрөмжийг хослуулж байна…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Төхөөрөмжийг хослуулж чадсангүй. Хурдан хариу үйлдлийн код буруу эсвэл төхөөрөмжийг ижил сүлжээнд холбоогүй байна."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP хаяг ба порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Хурдан хариу үйлдлийн кодыг скан хийх"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Хурдан хариу үйлдлийн кодыг скан хийж Wi-Fi-р төхөөрөмжийг хослуулна уу"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, дебаг хийх, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Алдаа мэдээлэх товчлол"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Цэсэнд алдааны мэдэгдэл авахад зориулсан товчийг харуулах"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Идэвхтэй байлгах"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Модем болгох техник хангамжийн хурдасгуурыг боломжтой тохиолдолд ашиглах"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB дебаг хийхийг зөвшөөрөх үү?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB дебаг нь зөвхөн хөгжүүлэлтийн зорилготой. Үүнийг өөрийн компьютер болон төхөөрөмжийн хооронд өгөгдөл хуулах, өөрийн төхөөрөмж дээр мэдэгдэлгүйгээр аппликейшн суулгах, лог датаг унших зэрэгт ашиглаж болно."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Утасгүй алдаа засахыг зөвшөөрөх үү?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Утасгүй алдаа засах нь зөвхөн хөгжүүлэлтийн зориулалттай. Үүнийг компьютер болон төхөөрөмж хооронд өгөгдөл хуулах, төхөөрөмждөө мэдэгдэлгүйгээр аппууд суулгах болон лог өгөгдлийг унших зэрэгт ашиглана уу."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Таны өмнө нь зөвшөөрөл өгсөн бүх компьютерээс USB дебаг хандалтыг нь хураах уу?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Хөгжлийн тохиргоог зөвшөөрөх үү?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Эдгээр тохиргоо нь зөвхөн хөгжүүлэлтэд ашиглах зорилготой. Эдгээр нь таны төхөөрөмж буюу түүн дээрх аппликейшнүүдийг эвдрэх, буруу ажиллах шалтгаан нь болж болно."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномаль (улаан-ногоон)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомаль (цэнхэр-шар)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Өнгө тохируулах"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Өнгөний залруулга нь өнгө ялгадаггүй хүмүүст өнгийг илүү оновчтой харахад тусалдаг"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Давхарласан <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Ойролцоогоор <xliff:g id="TIME_REMAINING">%1$s</xliff:g> үлдсэн"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>-с бага хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>-с их хугацаа үлдсэн"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Утас удахгүй унтарна"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Таблет удахгүй унтарна"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Төхөөрөмж удахгүй унтарна"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Утас удахгүй унтарна (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Таблет удахгүй унтарна (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Төхөөрөмж удахгүй унтарна (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Утас удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Таблет удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Төхөөрөмж удахгүй унтарч болзошгүй"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Утас удахгүй унтарч болзошгүй (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Таблет удахгүй унтарч болзошгүй (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Төхөөрөмж удахгүй унтарч болзошгүй (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Цэнэглэх хүртэл үлдсэн <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - цэнэглэх хүртэл <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Тодорхойгүй"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Цэнэглэж байна"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Хурдан цэнэглэж байна"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Удаан цэнэглэж байна"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Цэнэглэхгүй байна"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Залгаастай тул одоо цэнэглэх боломжгүй"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Дүүрэн"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 8767b4f..1240c5b 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB डीबग करणे"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB कनेक्ट केलेले असताना डीबग मोड"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB डीबग करणारी प्रमाणीकरणे रीव्होक करा"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"वायरलेस डीबगिंग"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"वाय-फाय कनेक्ट केलेले असताना डीबग मोड"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"एरर"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"वायरलेस डीबगिंग"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"उपलब्ध डिव्हाइस पाहण्यासाठी आणि वापरण्यासाठी वायरलेस डीबगिंग सुरू करा"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR कोडसह डिव्हाइस जोडा"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR कोड स्कॅनर वापरून नवीन डिव्हाइस जोडा"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"पेअरींग कोडसह डिव्हाइस जोडा"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"सहा अंकी कोड वापरून नवीन डिव्हाइस जोडा"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"पेअर केलेले डिव्हाइस"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"सध्या कनेक्ट केलेले आहे"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"डिव्हाइस तपशील"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"विसरा"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"डिव्हाइस फिंगरप्रिंट: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"कनेक्‍ट करता आले नाही"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> योग्य नेटवर्कशी कनेक्ट केले असल्याची खात्री करा"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"डिव्हाइससह पेअर करा"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"वाय-फाय पेअरींग कोड"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"पेअर करता आले नाही"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"डिव्हाइस समान नेटवर्कशी कनेक्ट केले असल्याची खात्री करा."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR कोड स्कॅन करून वाय-फाय वापरून डिव्हाइस पेअर करा"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"डिव्हाइस पेअर करत आहे…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"डिव्हाइस पेअर करता आले नाही. QR कोड चुकीचा होता किंवा डिव्हाइस समान नेटवर्कशी कनेक्ट केलेले नाही."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"आयपी अ‍ॅड्रेस आणि पोर्ट"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR कोड स्कॅन करा"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR कोड स्कॅन करून वाय-फाय वापरून डिव्हाइस पेअर करा"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, डीबग, डेव्हलपर"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"बग रिपोर्ट शॉर्टकट"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट घेण्यासाठी पॉवर मेनूमध्ये एक बटण दर्शवा"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"सक्रिय रहा"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध असल्यास टेदरिंग हार्डवेअर ॲक्सिलरेशन वापरा"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB डीबग करण्यास अनुमती द्यायची?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डिव्हाइस वर अ‍ॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"वायरलेस डीबगिंग करण्याची अनुमती द्यायची आहे का?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"वायरलेस डीबग करण्याचा हेतू फक्त विकास उद्देशांसाठी आहे. याचा वापर तुमचा कॉंप्युटर आणि तुमचे डिव्हाइस यांच्या दरम्यान डेटा कॉपी करण्यासाठी करा, सूचनेशिवाय तुमच्या डिव्हाइसवर अ‍ॅप्स इंस्टॉल करा आणि लॉग डेटा वाचा."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"तुम्ही पूर्वी ऑथोराइझ केलेल्या सर्व संगणकांवरुन USB डीबग करण्यासाठी अ‍ॅक्सेस रीव्होक करायचा?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिंग्जला अनुमती द्यायची?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"या सेटिंग्जचा हेतू फक्त विकास वापरासाठी आहे. त्यामुळे तुमचे डिव्हाइस आणि त्यावरील ॲप्लिकेशन ब्रेक होऊ शकतात किंवा नेहमीपेक्षा वेगळे वर्तन करू शकतात."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"क्षीण रक्तवर्णांधता (लाल-हिरवा)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"रंग दृष्टी कमतरता (निळा-पिवळा)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रंग सुधारणा"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"रंग सुधारणा ही रंगांधळेपणा असलेल्या लोकांना रंग अधिक अचूक दिसण्यात मदत करते"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारे अधिलिखित"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"अंदाजे <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाकी आहे"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> पेक्षा कमी वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> पेक्षा जास्त वेळ शिल्लक आहे (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> हून जास्त वेळ शिल्लक आहे"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"फोन लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"टॅबलेट लवकरच बंद होऊ शकतो"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"डिव्हाइस लवकरच बंद होऊ शकते"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"फोन लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"टॅबलेट लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"डिव्हाइस लवकरच बंद पडू शकते (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"फोन लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"टॅबलेट लवकरच बंद होऊ शकतो"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"डिव्हाइस लवकरच बंद होऊ शकते"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"फोन लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"टॅबलेट लवकरच बंद होऊ शकतो (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"डिव्हाइस लवकरच बंद होऊ शकते (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> पर्यंत पूर्ण चार्ज होईल"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज होत आहे"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"वेगाने चार्ज होत आहे"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"हळूहळू चार्ज होत आहे"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज होत नाही"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"प्लग इन केलेले आहे, आता चार्ज करू शकत नाही"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"पूर्ण"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index b79b801..b4c3f60 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Penyahpepijatan USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mod nyahpepijat apabila USB disambungkan"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Batalkan kebenaran penyahpepijatan USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Penyahpepijatan wayarles"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Mod penyahpepijatan apabila Wi-Fi disambungkan"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Ralat"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Penyahpepijatan wayarles"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Untuk melihat dan menggunakan peranti yang tersedia, hidupkan penyahpepijatan wayarles"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Gandingkan peranti dengan kod QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Gandingkan peranti baharu menggunakan Pengimbas kod QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Gandingkan peranti dengan kod gandingan"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Gandingkan peranti baharu menggunakan kod enam digit"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Peranti gandingan"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Tersambung pada masa ini"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Butiran peranti"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Lupakan"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Cap jari peranti: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Sambungan tidak berjaya"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Pastikan <xliff:g id="DEVICE_NAME">%1$s</xliff:g> disambungkan kepada rangkaian yang betul"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Gandingkan dengan peranti"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kod gandingan Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Gandingan tidak berjaya"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Pastikan peranti disambungkan kepada rangkaian yang sama."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Gandingkan peranti melalui Wi-Fi dengan mengimbas kod QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Menggandingkan peranti…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Gagal menggandingkan peranti. Kod QR salah atau peranti tidak disambungkan kepada rangkaian yang sama."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Alamat IP &amp; Port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Imbas kod QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Gandingkan peranti melalui Wi-Fi dengan mengimbas Kod QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Pintasan laporan pepijat"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Tunjukkan butang dalam menu kuasa untuk mengambil laporan pepijat"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Tetap berjaga"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Gunakan pecutan perkakasan penambatan jika tersedia"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Benarkan penyahpepijatan USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Penyahpepijatan USB adalah dimaksudkan untuk tujuan pembangunan sahaja. Gunakannya untuk menyalin data antara komputer dan peranti anda, memasang aplikasi pada peranti anda tanpa pemberitahuan, dan membaca data log."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Benarkan penyahpepijatan wayarles?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Penyahpepijatan wayarles adalah dimaksudkan untuk tujuan pembangunan sahaja. Gunakannya untuk menyalin data antara komputer dengan peranti anda, memasang apl pada peranti anda tanpa pemberitahuan dan membaca data log."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Batalkan akses ke penyahpepijatan USB dari semua komputer yang anda berikan kebenaran sebelum ini?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Benarkan tetapan pembangunan?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Tetapan ini adalah untuk penggunaan pembangunan sahaja. Peranti dan aplikasi yang terdapat padanya boleh rosak atau tidak berfungsi dengan betul."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (merah-hijau)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (biru-kuning)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pembetulan warna"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Pembetulan warna membantu orang yang mengalami kebutaan warna melihat warna yang lebih tepat"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Diatasi oleh <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Kira-kira <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Kurang daripada <xliff:g id="THRESHOLD">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Lebih daripada <xliff:g id="TIME_REMAINING">%1$s</xliff:g> lagi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Peranti mungkin ditutup tidak lama lagi"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Peranti mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Peranti mungkin ditutup tidak lama lagi"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Peranti mungkin ditutup tidak lama lagi (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> lagi sehingga dicas penuh"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> sehingga dicas"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Tidak diketahui"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Mengecas"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mengecas dgn cepat"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mengecas dgn prlahan"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Tidak mengecas"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Dipalamkan, tidak boleh mengecas sekarang"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Penuh"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index b2ad664..ae8c1b9 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB အမှားရှာခြင်း"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB နှင့်ချိတ်ထားလျှင် အမှားရှာဖွေဖယ်ရှားမှုစနစ် စတင်ရန်"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB အမှားရှာပြင်ဆင်ခွင့်များ ပြန်ရုပ်သိမ်းခြင်း"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ကြိုးမဲ့ အမှားရှာပြင်ခြင်း"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi ချိတ်ဆက်ထားစဉ် အမှားရှာပြင်ပုံစံ"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"အမှား"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ကြိုးမဲ့ အမှားရှာပြင်ခြင်း"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ရနိုင်သည့် စက်ပစ္စည်းများကို ကြည့်ပြီး အသုံးပြုနိုင်ရန် ကြိုးမဲ့ အမှားရှာပြင်ခြင်းကို ဖွင့်ပါ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR ကုဒ်ဖြင့် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR ကုဒ်ဖတ်စက် သုံး၍ စက်ပစ္စည်းသစ်များကို အတူတွဲပါ"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"တွဲချိတ်ကုဒ်ဖြင့် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ဂဏန်းခြောက်လုံးကုဒ်ဖြင့် စက်ပစ္စည်းသစ်များကို အတူတွဲပါ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"တွဲချိတ်ပြီး စက်ပစ္စည်းများ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"လက်ရှိ ချိတ်ဆက်ထားသည်"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"စက်ပစ္စည်း အသေးစိတ်"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"မေ့ပစ်ရန်"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"စက်ပစ္စည်း လက်ဗွေ- <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ချိတ်ဆက်ခြင်း မအောင်မြင်ပါ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> သည် မှန်ကန်သည့် ကွန်ရက်သို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"စက်ပစ္စည်းနှင့် အတူတွဲပါ"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi အတူတွဲချိတ်ရန် ကုဒ်"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"တွဲချိတ်ခြင်း မအောင်မြင်ပါ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"စက်ပစ္စည်းသည် ကွန်ရက်တစ်ခုတည်းသို့ ချိတ်ဆက်ထားခြင်းရှိမရှိ စစ်ဆေးပါ။"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR ကုဒ် စကင်ဖတ်ခြင်းဖြင့် Wi-Fi ပေါ်တွင် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"စက်ပစ္စည်းနှင့် တွဲချိတ်နေသည်…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"စက်ပစ္စည်းကို အတူတွဲ၍မရပါ။ QR ကုဒ်မမှန်ပါ သို့မဟုတ် စက်ပစ္စည်းသည် ကွန်ရက်တစ်ခုတည်းသို့ ချိတ်ဆက်မထားပါ။"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"အိုင်ပီ (IP) လိပ်စာနှင့် ပို့တ်"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ကုဒ်ကို စကင်ဖတ်ပါ"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR ကုဒ် စကင်ဖတ်ခြင်းဖြင့် Wi-Fi ပေါ်တွင် စက်ပစ္စည်းကို အတူတွဲပါ"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ချွတ်ယွင်းမှု အစီရင်ခံရန် ဖြတ်လမ်း"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ချွတ်ယွင်းမှု အစီရင်ခံစာကို တင်ရန် ပါဝါမီနူးမှ ခလုတ်ကို ပြပါ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ဖွင့်လျက်သား"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"အရှိန်မြှင့်တင်ရန် မိုဘိုင်းဖုန်းသုံး ချိတ်ဆက်မျှဝေခြင်း စက်ပစ္စည်းကို ရနိုင်လျှင် သုံးပါ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ပြသနာရှာခြင်း ခွင့်ပြုပါမလား?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USBအမှားရှားခြင်းမှာ ဆော့ဝဲလ်ရေးသားရန်အတွက်သာ ရည်ရွယ်ပါသည်။ သင့်ကွန်ပြုတာနှင့်သင့်စက်ကြားတွင် ဒေတာများကိုကူးယူရန်၊ အကြောင်းမကြားပဲနှင့် သင့်စက်အတွင်းသို့ အပလီကေးရှင်းများထည့်သွင်းခြင်းနှင့် ဒေတာမှတ်တမ်းများဖတ်ရန်အတွက် အသုံးပြုပါ"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ကြိုးမဲ့ အမှားရှာပြင်ခြင်းကို ခွင့်ပြုမလား။"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ကြိုးမဲ့ အမှားရှာပြင်ခြင်းကို ဆော့ဖ်ဝဲရေးရန်အတွက်သာ ရည်ရွယ်ပါသည်။ သင့်ကွန်ပျူတာနှင့် စက်ပစ္စည်းကြားတွင် ဒေတာများကို ကူးယူရန်၊ အကြောင်းမကြားဘဲ သင့်စက်ပစ္စည်းတွင် အက်ပ်ထည့်သွင်းရန်နှင့် ဒေတာမှတ်တမ်းဖတ်ရန်အတွက် ၎င်းကို အသုံးပြုပါ။"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"သင် ယခင်က ခွင့်ပြုခဲ့သော ကွန်ပျူတာအားလုံးမှ ယူအက်စ်ဘီ အမှားစစ်ခွင့်ကို ရုတ်သိမ်းမည်လား ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"တည်ဆောက်ပြုပြင်ရန်ဆက်တင်များကို အသုံးပြုခွင့်ပေးမည်လား?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ဤဆက်တင်းများကို တည်ဆောက်ပြုပြင်ရာတွင် သုံးရန်အတွက်သာ ရည်ရွယ်သည်။ ၎င်းတို့သည် သင်၏စက်နှင့် အပလီကေးရှင်းများကို ရပ်စေခြင်း သို့ လုပ်ဆောင်ချက်မမှန်ကန်ခြင်းများ ဖြစ်ပေါ်စေနိုင်သည်။"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (အနီ-အစိမ်း)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (အပြာ-အဝါ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"အရောင်ပြင်ဆင်မှု"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"အရောင်ပြင်ဆင်ခြင်းက အရောင်မကွဲသူများအတွက် ပိုမိုတိကျသော အရောင်များ ကြည့်နိုင်ရန် ကူညီပေးသည်"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> မှ ကျော်၍ လုပ်ထားသည်။"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ခန့် ကျန်သည်"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> အောက်သာ ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သည် (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ကျော် ကျန်သေးသည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"မကြာမီ တက်ဘလက်ပိတ်သွားနိုင်သည်"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"မကြာမီ စက်ပိတ်သွားနိုင်သည်"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"မကြာမီ တက်ဘလက် ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"မကြာမီ စက်ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည်"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"မကြာမီ တက်ဘလက် ပိတ်သွားနိုင်သည်"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"မကြာမီ စက်ပိတ်သွားနိုင်သည်"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"မကြာမီ ဖုန်းပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"မကြာမီ တက်ဘလက် ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"မကြာမီ စက်ပိတ်သွားနိုင်သည် (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"အားပြည့်ရန် <xliff:g id="TIME">%1$s</xliff:g> ကျန်သည်"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - အားပြည့်ရန် <xliff:g id="TIME">%2$s</xliff:g> ကျန်သည်"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"မသိ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"အားသွင်းနေပါသည်"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"အမြန် အားသွင်းနေသည်"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"နှေးကွေးစွာ အားသွင်း"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"အားသွင်းမနေပါ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ပလပ်ထိုးထားသောကြောင့် ယခုအားသွင်း၍ မရသေးပါ"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"အပြည့်"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 6a1f158..960398d 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-feilsøking"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Feilsøkingsmodus når USB kobles til"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB-feilsøking – opphev autorisasjon"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Trådløs feilsøking"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Feilsøkingsmodus når Wi-Fi er tilkoblet"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Feil"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Trådløs feilsøking"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"For å se og bruke tilgjengelige enheter, slå på trådløs feilsøking"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Koble til enheten med en QR-kode"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Koble til nye enheter med en QR-kodeskanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Koble til enheten med en tilkoblingskode"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Koble til nye enheter med en sekssifret kode"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Tilkoblede enheter"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Tilkoblet nå"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Enhetsdetaljer"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Glem"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Enhetens fingeravtrykk: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Tilkoblingen mislyktes"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Sørg for at <xliff:g id="DEVICE_NAME">%1$s</xliff:g> er koblet til riktig nettverk"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Koble til enheten"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi-tilkoblingskode"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Tilkoblingen mislyktes"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Sørg for at enheten er koblet til samme nettverk."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Koble til enheten via Wi-Fi ved å skanne en QR-kode"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Kobler til enheten …"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Kunne ikke koble til enheten. Enten var QR-koden feil, eller enheten er ikke koblet til samme nettverk."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adresse og port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skann QR-koden"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Koble til enheten via Wi-Fi ved å skanne en QR-kode"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, feilsøking, utvikler"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Snarvei til feilrapport"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Vis en knapp for generering av feilrapport i batterimenyen"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Forbli våken"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Bruk maskinvareakselerasjon for internettdeling hvis det er tilgjengelig"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Tillate USB-feilsøking?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-feilsøking er bare ment for utviklingsformål. Bruk det til å kopiere data mellom datamaskinen og enheten, installere apper på enheten uten varsel og lese loggdata."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vil du tillate trådløs feilsøking?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Trådløs feilsøking er bare ment for utviklingsformål. Bruk det til å kopiere data mellom datamaskinen og enheten, installere apper på enheten uten varsel og lese loggdata."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Vil du oppheve tilgangen til USB-feilsøking fra alle datamaskiner du tidligere har autorisert?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Vil du aktivere utviklingsinnstillingene?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Disse innstillingene er bare beregnet for bruk under programutvikling. De kan forårsake problemer med enheten din og tilhørende apper."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rød-grønn)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blå-gul)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Fargekorrigering"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Med fargekorrigering kan personer med fargeblindhet se mer nøyaktige farger"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overstyres av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Omtrent <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mindre enn <xliff:g id="THRESHOLD">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mer enn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> gjenstår"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefonen slås kanskje av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Nettbrettet slås kanskje av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Enheten slås kanskje av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefonen slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Nettbrettet slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Enheten slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefonen slås kanskje av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Nettbrettet slås kanskje av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Enheten slås kanskje av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefonen slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Nettbrettet slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Enheten slås kanskje av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> til batteriet er fulladet"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> til batteriet er fulladet"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Ukjent"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Lader"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Lader raskt"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Lader sakte"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Lader ikke"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Laderen er koblet til – kan ikke lade akkurat nå"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index 9cd5e20..e11f02d 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB डिबग गर्दै"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB जडित हुँदा डिबग मोड"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB डिबग गर्ने प्राधिकरणहरू उल्टाउनुहोस्"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"वायरलेस डिबग गर्ने प्रक्रिया"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi मा जोडिँदा डिबग मोड सक्षम पार्ने कि नपार्ने"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"त्रुटि"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"वायरलेस डिबग गर्ने प्रक्रिया"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"उपलब्ध यन्त्रहरू हेर्न र प्रयोग गर्न वायरलेस डिबग गर्ने प्रक्रिया सक्रिय गर्नुहोस्"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR कोडमार्फत यन्त्रको जोडा बनाउनुहोस्"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR कोड स्क्यानर प्रयोग गरी नयाँ यन्त्रहरूको जोडा बनाउनुहोस्"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"जोडा मिलाउने कोडमार्फत यन्त्रको जोडा बनाउनुहोस्"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"छ अङ्कको कोड प्रयोग गरी नयाँ यन्त्रहरूको जोडा बनाउनुहोस्"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"जोडा बनाइएका यन्त्रहरू"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"हाल जोडिएको छ"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"यन्त्रसम्बन्धी विवरणहरू"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"बिर्सनुहोस्"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"यन्त्रको फिंगरप्रिन्ट: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"वायरलेसमा जोड्न सकिएन"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> सही नेटवर्कमा जोडिएको कुरा सुनिश्चित गर्नुहोस्"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"यन्त्रसँग जोडा बनाउनुहोस्"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi सँग जोडा मिलाउने कोड"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"जोडा बनाउने प्रक्रिया सफल भएन"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"यन्त्र उही नेटवर्कमा जोडिएको कुरा सुनिश्चित गर्नुहोस्।"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR कोड स्क्यान गरेर Wi‑Fi प्रयोग गरी यन्त्रको जोडा बनाउनुहोस्"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"यन्त्रसँग जोडा मिलाउँदै…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"यन्त्रसँग जोडा बनाउन सकिएन। कि त QR कोड गलत छ कि यन्त्र उही नेटवर्कमा जोडिएको छैन।"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ठेगाना र पोर्ट"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR कोड स्क्यान गर्नुहोस्"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR कोड स्क्यान गरेर Wi‑Fi प्रयोग गरी यन्त्रको जोडा बनाउनुहोस्"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"बग प्रतिवेदन सर्टकट"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"बग रिपोर्ट लिनका लागि पावर मेनुमा बटन देखाउनुहोस्"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"जागा रहनुहोस्"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"उपलब्ध भएमा टेदरिङको लागि हार्डवेयरको प्रवेग प्रयोग गर्नुहोस्"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB डिबग गर्न लागि अनुमति दिने हो?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"युएसबी डिबगिङ विकास प्रयोजनका लागि मात्र निर्मित हुन्छ। यसलाई तपाईँको कम्प्युटर र तपाईँको उपकरणका बीच डेटा प्रतिलिपि गर्न, बिना सूचना तपाईँको उपकरणमा अनुप्रयोगहरू स्थापना गर्न र लग डेटा पढ्नका लागि प्रयोग गर्नुहोस्।"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"वायरलेस डिबग गर्ने प्रक्रिया सक्षम पार्ने हो?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"वायरलेस डिबग गर्ने प्रक्रिया विकास प्रयोजनका लागि मात्रै हो। यसलाई आफ्ना कम्प्युटर र उपकरणका बिच डेटा प्रतिलिपि गर्न, सूचना नदिई आफ्नो उपकरणमा अनुप्रयोगहरू स्थापना गर्न र लगसम्बन्धी डेटा रिड गर्नका लागि प्रयोग गर्नुहोस्।"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"तपाईं पहिले नै अधिकृत गर्नुभएका सबै कम्प्यूटरबाट USB डिबग गर्नको लागि पहुँच रद्द गर्ने हो?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"विकास सेटिङहरू अनुमति दिने हो?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"यी सेटिङहरू केवल विकास प्रयोगको लागि विचार गरिएको हो। तिनीहरूले तपाईंको उपकरण र अनुप्रयोगहरूलाई विच्छेदन गर्न वा दुर्व्यवहार गर्न सक्दछ।"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"प्रोटानेमली (रातो, हरियो)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ट्रिटानोमेली (निलो-पंहेलो)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"रङ्ग सुधार"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"रङ सुधार गर्नुले रङ छुट्याउन नसक्ने मान्छेलाई थप सटीक रूपमा रङहरू छुट्याउन मद्दत गर्दछ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> द्वारा अधिरोहित"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"लगभग <xliff:g id="TIME_REMAINING">%1$s</xliff:g> बाँकी छ"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> भन्दा कम समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> भन्दा बढी समय बाँकी"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"फोन चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"यन्त्र चाँडै बन्द हुन सक्छ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"फोन चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ट्याब्लेट चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"यन्त्र चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"फोन चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ट्याब्लेट चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"यन्त्र चाँडै बन्द हुन सक्छ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"फोन चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ट्याब्लेट चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"यन्त्र चाँडै बन्द हुन सक्छ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"पूर्ण चार्ज हुन <xliff:g id="TIME">%1$s</xliff:g> बाँकी"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"पूर्ण चार्ज हुन <xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> लाग्छ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"अज्ञात"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"चार्ज हुँदै"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"द्रुत गतिमा चार्ज गरिँदै"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"बिस्तारै चार्ज गरिँदै"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"चार्ज भइरहेको छैन"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"प्लगइन गरिएको छ, अहिले नै चार्ज गर्न सकिँदैन"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"पूर्ण चार्ज भएको स्थिति"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 8d5dea4..e79784c 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-foutopsporing"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Foutopsporingsmodus bij USB-verbinding"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Autorisatie USB-foutopsporing intrekken"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Draadloze foutopsporing"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Foutopsporingsmodus als wifi is verbonden"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Fout"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Draadloze foutopsporing"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Schakel draadloze foutopsporing in om beschikbare apparaten te bekijken en te gebruiken"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Apparaat koppelen met QR-code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Nieuwe apparaten koppelen via QR-codescanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Apparaat koppelen met koppelingscode"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Nieuwe apparaten koppelen via een zescijferige code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Gekoppelde apparaten"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Momenteel verbonden"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Apparaatgegevens"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Vergeten"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Vingerafdruk van apparaat: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Verbinding mislukt"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Zorg dat <xliff:g id="DEVICE_NAME">%1$s</xliff:g> is verbonden met het juiste netwerk"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Koppelen aan apparaat"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wifi-koppelingscode"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Koppeling mislukt"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Zorg dat het apparaat is verbonden met hetzelfde netwerk."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Apparaat koppelen via wifi door een QR-code te scannen"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Apparaat koppelen…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Kan het apparaat niet koppelen. De QR-code was onjuist of het apparaat is niet verbonden met hetzelfde netwerk."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adres en poort"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR-code scannen"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Apparaat koppelen via wifi door een QR-code te scannen"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, foutopsporing, ontwikkeling"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Snelle link naar bugrapport"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Een knop in het voedingsmenu weergeven om een bugrapport te maken"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Stand-by"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Hardwareversnelling voor tethering gebruiken indien beschikbaar"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB-foutopsporing toestaan?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-foutopsporing is alleen bedoeld voor ontwikkeldoeleinden. Het kan worden gebruikt om gegevens te kopiëren tussen je computer en je apparaat, apps zonder melding op je apparaat te installeren en loggegevens te lezen."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Draadloze foutopsporing toestaan?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Draadloze foutopsporing is alleen bedoeld voor ontwikkeldoeleinden. Het kan worden gebruikt om gegevens te kopiëren tussen je computer en je apparaat, apps zonder melding op je apparaat te installeren en logboekgegevens te lezen."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Toegang tot USB-foutopsporing intrekken voor alle computers waarvoor je dit eerder hebt toegestaan?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ontwikkelingsinstellingen toestaan?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Deze instellingen zijn uitsluitend bedoeld voor ontwikkelingsgebruik. Je apparaat en apps kunnen hierdoor vastlopen of anders reageren."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (rood-groen)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (blauw-geel)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Kleurcorrectie"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Met behulp van kleurcorrectie kunnen mensen die kleurenblind zijn, nauwkeurigere kleuren te zien krijgen"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Overschreven door <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Nog ongeveer <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Nog minder dan <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Nog meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Nog meer dan <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefoon wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Apparaat wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefoon wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Apparaat wordt binnenkort mogelijk uitgeschakeld"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefoon wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Apparaat wordt binnenkort mogelijk uitgeschakeld (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Nog <xliff:g id="TIME">%1$s</xliff:g> tot opgeladen"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> tot opgeladen"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Onbekend"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Opladen"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Snel opladen"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Langzaam opladen"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Wordt niet opgeladen"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Aangesloten, kan nu niet opladen"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Volledig"</string>
diff --git a/packages/SettingsLib/res/values-or/strings.xml b/packages/SettingsLib/res/values-or/strings.xml
index c0489c1..7e7c22d 100644
--- a/packages/SettingsLib/res/values-or/strings.xml
+++ b/packages/SettingsLib/res/values-or/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ଡିବଗ୍‌ ହେଉଛି"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB ସଂଯୁକ୍ତ ହେବାବେଳେ ଡିବଗ୍‌ ମୋଡ୍‌"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ଡିବଗିଙ୍ଗ ଅଧିକାରକୁ କାଢ଼ିଦିଅନ୍ତୁ"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ୱେୟାରଲେସ୍ ଡିବଗିଂ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ୱାଇ-ଫାଇ ସଂଯୁକ୍ତ ଥିବା ବେଳେ ଡିବଗ୍ ମୋଡ୍"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ତ୍ରୁଟି"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ୱେୟାରଲେସ୍ ଡିବଗିଂ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ଉପଲବ୍ଧ ଡିଭାଇସଗୁଡ଼ିକୁ ଦେଖିବାକୁ ଏବଂ ବ୍ୟବହାର କରିବାକୁ ୱେୟାରଲେସ୍ ଡିବଗିଂ ଚାଲୁ କରନ୍ତୁ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR କୋଡରେ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR କୋଡ୍ ସ୍କାନର୍ ବ୍ୟବହାର କରି ନୂଆ ଡିଭାଇସଗୁଡ଼ିକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ପେୟାରିଂ କୋଡରେ ଡିଭାଇସକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ଛଅ ଡିଜିଟ୍ କୋଡ୍ ବ୍ୟବହାର କରି ନୂଆ ଡିଭାଇସଗୁଡ଼ିକୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ପେୟାର୍ ହୋଇଥିବା ଡିଭାଇସଗୁଡ଼ିକ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ବର୍ତ୍ତମାନ ସଂଯୁକ୍ତ ଅଛି"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ଡିଭାଇସ୍ ବିବରଣୀ"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ଭୁଲିଗଲେ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ଡିଭାଇସ୍ ଫିଙ୍ଗରପ୍ରିଣ୍ଟ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ସଂଯୋଗ ବିଫଳ ହେଲା"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> ଫୋନ୍ ନେଟୱାର୍କ ସହ ସଂଯୁକ୍ତ ଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ଡିଭାଇସରୁ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ୱାଇ-ଫାଇ ପେୟାରିଂ କୋଡ୍"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ପେୟାରିଂ ବିଫଳ ହେଲା"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ଡିଭାଇସଟି ସମାନ ନେଟୱାର୍କରେ ସଂଯୋଗ ହୋଇଥିବା ସୁନିଶ୍ଚିତ କରନ୍ତୁ।"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"ଏକ QR କୋଡ୍ ସ୍କାନ୍ କରି ୱାଇ-ଫାଇରେ ଡିଭାଇସ୍ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ଡିଭାଇସ୍ ପେୟାର୍ କରାଯାଉଛି…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ଡିଭାଇସରୁ ପେୟାର୍ ହେବାରେ ବିଫଳ ହୋଇଛି। QR କୋଡ୍ ସଠିକ୍ ନଥିଲା ବା ଡିଭାଇସ୍ ସମାନ ନେଟୱାର୍କରେ ସଂଯୋଗ ହୋଇନାହିଁ।"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ଠିକଣା ଓ ପୋର୍ଟ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR କୋଡ୍ ସ୍କାନ୍ କରନ୍ତୁ"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"ଏକ QR କୋଡ୍ ସ୍କାନ୍ କରି ୱାଇ-ଫାଇରେ ଡିଭାଇସ୍ ପେୟାର୍ କରନ୍ତୁ"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ଡିବଗ୍, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ବଗ୍ ରିପୋର୍ଟ ସର୍ଟକଟ୍‌"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ବଗ୍ ରିପୋର୍ଟ ଦେବାପାଇଁ ପାୱାର୍‌ ମେନୁରେ ଏକ ବଟନ୍‌ ଦେଖନ୍ତୁ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ଜାଗ୍ରତ ରଖନ୍ତୁ"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ଯଦି ଉପଲବ୍ଧ ଥାଏ, ଟିଥରିଙ୍ଗ ହାର୍ଡୱେର୍‌ ଆକ୍ସିଲିରେସନ୍ ବ୍ୟବହାର କରନ୍ତୁ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB ଡିବଗିଙ୍ଗ କରିବେ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ଡିବଗିଂ କେବଳ ଡେଭଲପମେଣ୍ଟ ଉଦ୍ଦେଶ୍ୟ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ଅଟେ। ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର ଏବଂ ଡିଭାଇସ୍‌ ମଧ୍ୟରେ ଡାଟା କପି କରିବାକୁ, ବିନା ବିଜ୍ଞପ୍ତିରେ ଆପଣଙ୍କ ଡିଭାଇସରେ ଆପସ୍‌ ସଂସ୍ଥାପନ କରିବାକୁ, ଏବଂ ଲଗ୍‌ ଡାଟା ପଢିବାକୁ ଏହା ବ୍ୟବହାର କରନ୍ତୁ।"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ୱେୟାରଲେସ୍ ଡିବଗିଂ ପାଇଁ ଅନୁମତି ଦେବେ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ୱେୟାରଲେସ୍ ଡିବଗିଂ କେବଳ ଉନ୍ନତି ଉଦ୍ଦେଶ୍ୟ ପାଇଁ ଉଦ୍ଦିଷ୍ଟ ଅଟେ। ଆପଣଙ୍କ କମ୍ପ୍ୟୁଟର ଏବଂ ଡିଭାଇସ୍ ମଧ୍ୟରେ ଡାଟା କପି କରିବାକୁ, ବିନା ବିଜ୍ଞପ୍ତିରେ ଆପଣଙ୍କ ଡିଭାଇସରେ ଆପ୍ସ ଇନଷ୍ଟଲ୍ କରିବାକୁ ଏବଂ ଲଗ୍ ଡାଟା ପଢ଼ିବା ପାଇଁ ଏହାକୁ ବ୍ୟବହାର କରନ୍ତୁ।"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ଅଧିକୃତ ସମସ୍ତ କମ୍ପ୍ୟୁଟରରୁ USB ଡିବଗ୍‌ କରିବା ଆକ୍ସେସ୍‌ ପ୍ରତ୍ୟାହାର କରିବେ କି?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ଡେଭଲପମେଣ୍ଟ ସେଟିଙ୍ଗ ଅନୁମତି ଦେବେ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ଏହି ସେଟିଙ୍ଗଗୁଡ଼ିକ କେବଳ ବିକାଶ ବ୍ୟବହାର ପାଇଁ ଉଦ୍ଦିଷ୍ଟ। ସେଗୁଡ଼ିକ କାରଣରୁ ଆପଣଙ୍କ ଡିଭାଇସ୍‌ ଓ ଆପ୍ଲିକେଶନ୍‍‍ଗୁଡ଼ିକ ଠିକ୍‌ ଭାବେ କାମ ନକରିପାରେ।"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ପ୍ରୋଟାନୋମାଲି (ଲାଲ୍‌-ସବୁଜ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ନୀଳ-ହଳଦିଆ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ରଙ୍ଗ ସଠିକତା"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ରଙ୍ଗ ଚିହ୍ନିବାରେ ସମସ୍ୟା ଥିବା ଲୋକମାନଙ୍କୁ କଲର୍ କରେକ୍ସନ୍ ସଠିକ୍ ରଙ୍ଗ ଦେଖିବାରେ ସାହାଯ୍ୟ କରିଥାଏ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ଦ୍ୱାରା ଓଭର୍‌ରାଇଡ୍‌ କରାଯାଇଛି"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"ପାଖାପାଖି <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ବଳକା ଅଛି"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ରୁ କମ୍ ସମୟ ବଳକା ଅଛି (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ରୁ ଅଧିକ ସମୟ ବଳକା ଅଛି(<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ରୁ ଅଧିକ ବଳକା ଅଛି"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ଖୁବ୍ ଶୀଘ୍ର ଫୋନ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ଖୁବ୍ ଶୀଘ୍ର ଟାବଲେଟ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ଖୁବ୍ ଶୀଘ୍ର ଫୋନ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ଖୁବ୍ ଶୀଘ୍ର ଟାବଲେଟ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ଖୁବ୍ ଶୀଘ୍ର ଡିଭାଇସ୍‌ଟି ବନ୍ଦ ହୋଇଯାଇପାରେ(<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ଫୋନ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ଟାବଲେଟ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ଫୋନ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ଟାବଲେଟ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ଡିଭାଇସ୍ ଶୀଘ୍ର ବନ୍ଦ ହୋଇଯାଇପାରେ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ଚାର୍ଜ ହେବା ପାଇଁ <xliff:g id="TIME">%1$s</xliff:g> ବାକି ଅଛି"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ଚାର୍ଜ ହେବା ପର୍ଯ୍ୟନ୍ତ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ଅଜ୍ଞାତ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ଚାର୍ଜ ହେଉଛି"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ଶୀଘ୍ର ଚାର୍ଜ ହେଉଛି"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ଧୀରେ ଚାର୍ଜ ହେଉଛି"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ଚାର୍ଜ ହେଉନାହିଁ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ପ୍ଲଗ୍‌ରେ ଲାଗିଛି, ହେଲେ ଏବେ ଚାର୍ଜ କରିପାରିବ ନାହିଁ"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ଚାର୍ଜ ସମ୍ପୂର୍ଣ୍ଣ"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index 7355418..7279f31 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB ਡੀਬਗਿੰਗ"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"ਡੀਬੱਗ ਮੋਡ ਜਦੋਂ USB ਕਨੈਕਟ ਕੀਤੀ ਜਾਏ"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB ਡੀਬਗਿੰਗ ਅਧਿਕਾਰ ਰੱਦ ਕਰੋ"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"ਵਾਈ-ਫਾਈ ਕਨੈਕਟ ਹੋਣ \'ਤੇ ਡੀਬੱਗ ਮੋਡ"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ਗੜਬੜ"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ਉਪਲਬਧ ਡੀਵਾਈਸਾਂ ਨੂੰ ਦੇਖਣ ਅਤੇ ਵਰਤਣ ਲਈ, ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR ਕੋਡ ਸਕੈਨਰ ਵਰਤ ਕੇ ਨਵੇਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"ਜੋੜਾਬੱਧਕਰਨ ਕੋਡ ਨਾਲ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ਛੇ ਅੰਕਾਂ ਵਾਲਾ ਕੋਡ ਵਰਤ ਕੇ ਨਵੇਂ ਡੀਵਾਈਸਾਂ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"ਜੋੜਾਬੱਧ ਕੀਤੇ ਡੀਵਾਈਸ"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ਇਸ ਵੇਲੇ ਕਨੈਕਟ ਹੈ"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"ਡੀਵਾਈਸ ਦੇ ਵੇਰਵੇ"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ਭੁੱਲ ਜਾਓ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ਡੀਵਾਈਸ ਫਿੰਗਰਪ੍ਰਿੰਟ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"ਕਨੈਕਸ਼ਨ ਅਸਫਲ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"ਪੱਕਾ ਕਰੋ ਕਿ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> ਸਹੀ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੈ"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"ਡੀਵਾਈਸ ਨਾਲ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"ਵਾਈ-ਫਾਈ ਜੋੜਾਬੱਧਕਰਨ ਕੋਡ"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"ਜੋੜਾਬੱਧ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ਪੱਕਾ ਕਰੋ ਕਿ ਡੀਵਾਈਸ ਉਸੇ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਹੈ।"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR ਕੋਡ ਸਕੈਨ ਕਰਕੇ ਵਾਈ-ਫਾਈ \'ਤੇ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"ਡੀਵਾਈਸ ਨੂੰ ਜੋੜਾਬੱਧ ਕਰਨਾ ਅਸਫਲ ਰਿਹਾ। ਜਾਂ ਤਾਂ QR ਕੋਡ ਗਲਤ ਸੀ, ਜਾਂ ਡੀਵਾਈਸ ਉਸੇ ਨੈੱਟਵਰਕ ਨਾਲ ਕਨੈਕਟ ਨਹੀਂ ਹੈ।"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ਪਤਾ &amp; ਪੋਰਟ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR ਕੋਡ ਸਕੈਨ ਕਰੋ"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR ਕੋਡ ਸਕੈਨ ਕਰਕੇ ਵਾਈ-ਫਾਈ \'ਤੇ ਡੀਵਾਈਸ ਜੋੜਾਬੱਧ ਕਰੋ"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ਡੀਬੱਗ, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ਬੱਗ ਰਿਪੋਰਟ ਸ਼ਾਰਟਕੱਟ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"ਇੱਕ ਬੱਗ ਰਿਪੋਰਟ ਲੈਣ ਲਈ ਪਾਵਰ ਮੀਨੂ ਵਿੱਚ ਇੱਕ ਬਟਨ ਦਿਖਾਓ"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"ਸੁਚੇਤ ਰਹੋ"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ਉਪਲਬਧ ਹੋਣ \'ਤੇ ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ ਵਰਤੋ"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"ਕੀ USB ਡੀਬਗਿੰਗ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB ਡੀਬਗਿੰਗ ਸਿਰਫ਼ ਵਿਕਾਸ ਮੰਤਵਾਂ ਲਈ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ ਲਈ ਵਰਤੋ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰੋ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹੋ।"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"ਕੀ ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ ਕਰਨ ਦੇਣੀ ਹੈ?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"ਵਾਇਰਲੈੱਸ ਡੀਬੱਗਿੰਗ ਕੇਵਲ ਵਿਕਾਸ ਦੇ ਉਦੇਸ਼ਾਂ ਲਈ ਨਿਯਤ ਕੀਤੀ ਹੁੰਦੀ ਹੈ। ਇਸਨੂੰ ਆਪਣੇ ਕੰਪਿਊਟਰ ਅਤੇ ਆਪਣੇ ਡੀਵਾਈਸ ਵਿਚਕਾਰ ਡਾਟਾ ਕਾਪੀ ਕਰਨ, ਸੂਚਨਾ ਦੇ ਬਿਨਾਂ ਆਪਣੇ ਡੀਵਾਈਸ \'ਤੇ ਐਪਾਂ ਸਥਾਪਤ ਕਰਨ ਅਤੇ ਲੌਗ ਡਾਟਾ ਪੜ੍ਹਨ ਲਈ ਵਰਤੋ।"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ਕੀ ਉਹਨਾਂ ਸਾਰੇ ਕੰਪਿਊਟਰਾਂ ਤੋਂ USB ਡੀਬੱਗਿੰਗ ਤੱਕ ਪਹੁੰਚ ਰੱਦ ਕਰਨੀ ਹੈ, ਜਿਹਨਾਂ ਲਈ ਪਹਿਲਾਂ ਤੁਸੀਂ ਅਧਿਕਾਰਤ ਕੀਤਾ ਹੈ?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ਕੀ ਵਿਕਾਸ ਸੈਟਿੰਗਾਂ ਦੀ ਆਗਿਆ ਦੇਣੀ ਹੈ?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ਇਹ ਸੈਟਿੰਗਾਂ ਕੇਵਲ ਵਿਕਾਸਕਾਰ ਦੀ ਵਰਤੋਂ ਲਈ ਹਨ। ਇਹ ਤੁਹਾਡੇ ਡੀਵਾਈਸ ਅਤੇ ਇਸਤੇ ਮੌਜੂਦ ਐਪਲੀਕੇਸ਼ਨ ਨੂੰ ਬ੍ਰੇਕ ਕਰਨ ਜਾਂ ਦੁਰਵਿਵਹਾਰ ਕਰਨ ਦਾ ਕਾਰਨ ਬਣ ਸਕਦੇ ਹਨ।"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (ਲਾਲ-ਹਰਾ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (ਨੀਲਾ-ਪੀਲਾ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"ਰੰਗ ਸੁਧਾਈ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"ਰੰਗ ਸੁਧਾਈ ਨਾਲ ਰੰਗਾਂ ਦੇ ਅੰਨ੍ਹੇਪਣ ਦੇ ਸ਼ਿਕਾਰ ਲੋਕਾਂ ਦੀ ਵਧੇਰੇ ਸਟੀਕ ਰੰਗਾਂ ਨੂੰ ਦੇਖਣ ਵਿੱਚ ਮਦਦ ਕੀਤੀ ਜਾਂਦੀ ਹੈ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ਦੁਆਰਾ ਓਵਰਰਾਈਡ ਕੀਤਾ"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"ਲਗਭਗ <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਬਾਕੀ"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> ਤੋਂ ਘੱਟ ਸਮਾਂ ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ਤੋਂ ਵੱਧ ਸਮਾਂ ਬਾਕੀ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ਫ਼ੋਨ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ਟੈਬਲੈੱਟ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"ਡੀਵਾਈਸ ਛੇਤੀ ਹੀ ਬੰਦ ਹੋ ਸਕਦਾ ਹੈ (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ਚਾਰਜ ਹੋਣ ਵਿੱਚ <xliff:g id="TIME">%1$s</xliff:g> ਬਾਕੀ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ਤੱਕ ਚਾਰਜ ਹੋ ਜਾਵੇਗੀ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ਅਗਿਆਤ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ਚਾਰਜ ਹੋ ਰਿਹਾ ਹੈ"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ਤੇਜ਼ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"ਹੌਲੀ ਚਾਰਜ ਹੋ ਰਹੀ ਹੈ"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ਚਾਰਜ ਨਹੀਂ ਹੋ ਰਿਹਾ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ਪਲੱਗ ਲੱਗਾ ਹੋਇਆ ਹੈ, ਇਸ ਸਮੇਂ ਚਾਰਜ ਨਹੀਂ ਹੋ ਸਕਦੀ"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"ਪੂਰੀ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index a3ccb07..3b12891 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Debugowanie USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Tryb debugowania, gdy podłączone jest USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Odwołaj dostęp do debugowania USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Debugowanie bezprzewodowe"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Tryb debugowania przy połączeniu z Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Błąd"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Debugowanie bezprzewodowe"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Aby wyświetlić dostępne urządzenia i ich używać, włącz debugowanie bezprzewodowe"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Sparuj urządzenie przy pomocy kodu QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Sparuj nowe urządzenie, skanując kod QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sparuj urządzenie przy pomocy kodu parowania"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sparuj nowe urządzenie przy pomocy 6-cyfrowego kodu"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Sparowane urządzenia"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Obecnie połączone"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Szczegóły urządzenia"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Zapomnij"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Odcisk cyfrowy urządzenia: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Nie można połączyć"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Sprawdź, czy <xliff:g id="DEVICE_NAME">%1$s</xliff:g> jest podłączony do tej samej sieci"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sparuj z urządzeniem"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kod parowania Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Parowanie nie powiodło się"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Upewnij się, że urządzenie jest podłączone do tej samej sieci."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Sparuj urządzenia przez Wi-Fi, skanując kod QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Paruję urządzenie…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Nie udało się sparować z urządzeniem. Kod QR jest nieprawidłowy albo urządzenie nie jest podłączone do tej samej sieci."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adres IP i port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Zeskanuj kod QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Sparuj urządzenia przez Wi-Fi, skanując kod QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Skrót do zgłoszenia błędu"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Pokaż w menu zasilania przycisk zgłaszania błędu"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Pozostaw włączony ekran"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Użyj akceleracji sprzętowej tetheringu, jeśli jest dostępna"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Czy zezwalać na debugowanie USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Debugowanie USB jest przeznaczone wyłącznie do celów programistycznych. Może służyć do kopiowania danych między komputerem a urządzeniem, instalowania aplikacji na urządzeniu bez powiadamiania, a także odczytu danych dziennika."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Zezwalać na debugowanie bezprzewodowe?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Debugowanie bezprzewodowe jest przeznaczone wyłącznie do celów programistycznych. Może służyć do kopiowania danych między komputerem a urządzeniem, instalowania aplikacji na urządzeniu bez powiadamiania, a także odczytu danych dziennika."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Odwołać dostęp wszystkich poprzednio autoryzowanych komputerów do debugowania USB?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Zezwolić na ustawienia programistyczne?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Te ustawienia są przeznaczone wyłącznie dla programistów. Ich użycie może spowodować uszkodzenie lub nieprawidłowe działanie urządzenia i zainstalowanych na nim aplikacji."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (czerwony-zielony)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (niebieski-żółty)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korekcja kolorów"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korekcja kolorów pomaga osobom z zaburzeniami rozpoznawania barw lepiej je widzieć"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Nadpisana przez <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Jeszcze około <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Pozostało mniej niż <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Pozostało ponad: <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Pozostało ponad: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Urządzenie może się wkrótce wyłączyć"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Urządzenie może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Wkrótce telefon może się wyłączyć"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Urządzenie może się wkrótce wyłączyć"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Urządzenie może się wkrótce wyłączyć (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Do naładowania <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – do naładowania <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Nieznane"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Ładowanie"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Szybkie ładowanie"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Wolne ładowanie"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nie podłączony"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Podłączony. Nie można teraz ładować"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Naładowana"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index f4182bf..5e76fe0 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuração USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuração quando o USB estiver conectado"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revogar autorizações de depuração USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuração por Wi-Fi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Parear novos dispositivos usando um leitor de código QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parear novos dispositivos usando um código de seis dígitos"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos pareados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectados no momento"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalhes do dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Esquecer"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Impressão digital do dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Falha na conexão"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Verifique se o <xliff:g id="DEVICE_NAME">%1$s</xliff:g> está conectado à rede correta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Parear com o dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de pareamento de Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Falha no pareamento"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Verifique se o dispositivo está conectado à mesma rede."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pareando dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O código QR está incorreto ou o dispositivo não está conectado à mesma rede."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer ativo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware de tethering quando disponível"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Permitir a depuração USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Permitir a depuração sem fio?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"A depuração sem fio serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revogar o acesso à depuração USB para todos os computadores autorizados?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ativar as configurações de desenvolvimento?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Essas configurações são destinadas apenas para o uso de desenvolvedores. Elas podem causar a desativação ou mau funcionamento do dispositivo e dos apps contidos nele."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"A correção de cores ajuda pessoas com daltonismo a ver cores de forma mais precisa"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"O smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"O tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"O dispositivo pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"O smartphone pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"O smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"O tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"O dispositivo pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"O smartphone pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregando devagar"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Conectado. Não é possível carregar no momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Carregada"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 2f206d4..d1b29f0 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuração USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuração com USB ligado"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revogar autorizações de depur. USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuração sem fios"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando o Wi-Fi está ligado"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Erro."</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração sem fios"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e utilizar dispositivos disponíveis, ative a depuração sem fios."</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Sincronize o dispositivo com o código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Sincronize novos dispositivos com o leitor de códigos QR."</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Sincronize dispositivo com código de sincronização"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Sincronize novos dispositivos através do código de seis dígitos."</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos sincronizados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Atualmente ligado."</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalhes do dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Esquecer"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Impressão digital do dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"A ligação falhou"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Certifique-se de que o dispositivo <xliff:g id="DEVICE_NAME">%1$s</xliff:g> está ligado à rede correta."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Sincronize com o dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de sincronização de Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Sincronização sem êxito"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Certifique-se de que o dispositivo está ligado à mesma rede."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Sincronize o dispositivo através de Wi-Fi ao ler um código QR."</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"A sincronizar o dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao sincronizar o dispositivo. O código QR estava incorreto ou o dispositivo não está ligado à mesma rede."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Porta e endereço IP"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Leia o código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Sincronize o dispositivo através de Wi-Fi ao ler um código QR."</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, depurar, programador"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de erro"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão no menu ligar/desligar para criar um relatório de erro"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Manter ativo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Se disponível, utilizar a aceleração de hardware para ligação (à Internet) via telemóvel"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Permitir depuração USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"A depuração USB é utilizada apenas para fins de programação. Utilize-a para copiar dados entre o computador e o aparelho, instalar aplicações no aparelho sem notificação e ler dados de registo."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Pretende permitir a depuração sem fios?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"A depuração sem fios é utilizada apenas para fins de programação. Utilize-a para copiar dados entre o computador e o dispositivo, instalar apps no dispositivo sem notificação e ler dados de registo."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revogar acesso à depuração USB de todos os computadores anteriormente autorizados?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permitir definições de programação?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Estas definições destinam-se apenas a programação. Podem fazer com que o seu aparelho e as aplicações nele existentes falhem ou funcionem mal."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção da cor"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"A correção de cor ajuda as pessoas com daltonismo a ver cores mais precisas."</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Resta(m) cerca de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Resta(m) menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)."</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Resta(m) mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"O telemóvel poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"O tablet poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"O dispositivo poderá ser encerrado em breve."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"O telemóvel poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"O tablet poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"O dispositivo poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"O telemóvel poderá ser encerrado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"O tablet poderá ser encerrado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"O dispositivo poderá ser encerrado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"O telemóvel poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"O tablet poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"O dispositivo poderá ser encerrado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Falta(m) <xliff:g id="TIME">%1$s</xliff:g> até ficar carregada"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> até ficar carregada"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"A carregar"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregamento rápido"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregamento lento"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está a carregar"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Ligada à corrente, não é possível carregar neste momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Completo"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index f4182bf..5e76fe0 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Depuração USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Modo de depuração quando o USB estiver conectado"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revogar autorizações de depuração USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Depuração por Wi-Fi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modo de depuração quando a rede Wi‑Fi estiver conectada"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Erro"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Depuração por Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para ver e usar dispositivos disponíveis, ative a depuração por Wi-Fi"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parear o dispositivo com um código QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Parear novos dispositivos usando um leitor de código QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Parear o dispositivo com um código de pareamento"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Parear novos dispositivos usando um código de seis dígitos"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispositivos pareados"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectados no momento"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalhes do dispositivo"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Esquecer"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Impressão digital do dispositivo: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Falha na conexão"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Verifique se o <xliff:g id="DEVICE_NAME">%1$s</xliff:g> está conectado à rede correta"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Parear com o dispositivo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Código de pareamento de Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Falha no pareamento"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Verifique se o dispositivo está conectado à mesma rede."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Pareando dispositivo…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Falha ao parear o dispositivo. O código QR está incorreto ou o dispositivo não está conectado à mesma rede."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Endereço IP e porta"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Ler código QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parear dispositivo na rede Wi‑Fi fazendo a leitura do código QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Atalho para relatório de bugs"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Permanecer ativo"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Usar aceleração de hardware de tethering quando disponível"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Permitir a depuração USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"A depuração USB serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Permitir a depuração sem fio?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"A depuração sem fio serve apenas para fins de desenvolvimento. Use-a para copiar dados entre o computador e o dispositivo, instalar apps no seu aparelho sem notificação e ler dados de registro."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revogar o acesso à depuração USB para todos os computadores autorizados?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ativar as configurações de desenvolvimento?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Essas configurações são destinadas apenas para o uso de desenvolvedores. Elas podem causar a desativação ou mau funcionamento do dispositivo e dos apps contidos nele."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalia (vermelho-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalia (azul-amarelo)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Correção de cor"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"A correção de cores ajuda pessoas com daltonismo a ver cores de forma mais precisa"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Substituído por <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Tempo restante aproximado: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Menos de <xliff:g id="THRESHOLD">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s) (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mais de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> restante(s)"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"O smartphone pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"O tablet pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"O dispositivo pode ser desligado em breve"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"O smartphone pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"O smartphone pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"O tablet pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"O dispositivo pode ser desligado em breve"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"O smartphone pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"O tablet pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"O dispositivo pode ser desligado em breve (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Tempo restante até a carga completa: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g>: <xliff:g id="TIME">%2$s</xliff:g> até a carga completa"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Desconhecido"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Carregando"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Carregando rápido"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Carregando devagar"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Não está carregando"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Conectado. Não é possível carregar no momento"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Carregada"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 6e8bbd1..e1aa85b 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Remedierea erorilor prin USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Mod de depanare când este conectat USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Revoc autorizații remediere a erorilor prin USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Remedierea erorilor prin wireless"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Modul de remediere a erorilor când rețeaua Wi-Fi este conectată"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Eroare"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Remedierea erorilor prin wireless"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Activați remedierea erorilor wireless pentru a vedea și a folosi dispozitivele disponibile"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Asociați dispozitivul folosind codul QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Asociați dispozitive noi folosind scannerul de coduri QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Asociați dispozitivul folosind codul de conectare"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Asociați dispozitive noi folosind codul din șase cifre"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Dispozitive asociate"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Conectat"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detalii despre dispozitiv"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Ștergeți"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Amprenta pentru dispozitiv: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Conectare nereușită"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Asigurați-vă că ați conectat <xliff:g id="DEVICE_NAME">%1$s</xliff:g> la rețeaua corectă"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Asociați cu dispozitivul"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Cod de conectare pentru Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Asociere nereușită"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Asigurați-vă că dispozitivul este conectat la aceeași rețea."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Asociați dispozitivul prin Wi-Fi scanând un cod QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Se asociază dispozitivul…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Nu s-a asociat dispozitivul. Codul QR este incorect sau dispozitivul nu este conectat la aceeași rețea."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa IP și portul"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Scanați codul QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Asociați dispozitivul prin Wi-Fi scanând un cod QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, remedierea erorilor, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Comandă rapidă pentru raportul de erori"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Afișați un buton în meniul de pornire pentru a realiza un raport de erori"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Activ permanent"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Folosiți accelerarea hardware pentru tethering, dacă este disponibilă"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Permiteți remedierea erorilor prin USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Remedierea erorilor prin USB are exclusiv scopuri de dezvoltare. Utilizați-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Permiteți remedierea erorilor prin wireless?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Remedierea erorilor prin wireless are exclusiv scopuri de dezvoltare. Folosiți-o pentru a copia date de pe computer pe dispozitiv, pentru a instala aplicații pe dispozitiv fără notificare și pentru a citi datele din jurnale."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Revocați accesul la remedierea erorilor prin USB de pe toate computerele pe care le-ați autorizat anterior?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Permiteți setările pentru dezvoltare?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Aceste setări sunt destinate exclusiv utilizării pentru dezvoltare. Din cauza lor, este posibil ca dispozitivul dvs. și aplicațiile de pe acesta să nu mai funcționeze sau să funcționeze necorespunzător."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalie (roșu-verde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalie (albastru-galben)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Corecția culorii"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Corecția culorii ajută persoanele cu daltonism să vadă culori mai exacte"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Valoare înlocuită de <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Timp aproximativ rămas: <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"A mai rămas mai puțin de <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"A mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"A mai rămas mai mult de <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefonul se poate închide în curând"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tableta se poate închide în curând"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Dispozitivul se poate închide în curând"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefonul se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tableta se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Dispozitivul se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefonul se poate închide în curând"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tableta se poate închide în curând"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Dispozitivul se poate închide în curând"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefonul se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tableta se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Dispozitivul se poate închide în curând (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Au mai rămas <xliff:g id="TIME">%1$s</xliff:g> până la încărcare"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> până la încărcare"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Necunoscut"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Se încarcă"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Se încarcă rapid"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Se încarcă lent"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nu se încarcă"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Conectat, nu se poate încărca chiar acum"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Complet"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 87831c7..3df750d 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -112,7 +112,7 @@
     <string name="bluetooth_opp_profile_summary_use_for" msgid="461981154387015457">"Используется для передачи файлов"</string>
     <string name="bluetooth_hid_profile_summary_use_for" msgid="4289460627406490952">"Использовать для ввода"</string>
     <string name="bluetooth_hearing_aid_profile_summary_use_for" msgid="7689393730163320483">"Использовать для слухового аппарата"</string>
-    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Добавить"</string>
+    <string name="bluetooth_pairing_accept" msgid="2054232610815498004">"Подключить"</string>
     <string name="bluetooth_pairing_accept_all_caps" msgid="2734383073450506220">"ДОБАВИТЬ"</string>
     <string name="bluetooth_pairing_decline" msgid="6483118841204885890">"Отмена"</string>
     <string name="bluetooth_pairing_will_share_phonebook" msgid="3064334458659165176">"Установление соединения обеспечивает доступ к вашим контактам и журналу звонков при подключении."</string>
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Отладка по USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Включить режим отладки при подключении к компьютеру по USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Отозвать доступ для USB-отладки"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Отладка по Wi-Fi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим отладки при подключении к сети Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Ошибка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Отладка по Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Чтобы посмотреть и использовать доступные устройства, включите отладку по Wi-Fi"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Подключить устройство с помощью QR-кода"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Подключение новых устройств с помощью сканера QR-кодов"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Подключить устройство с помощью кода подключения"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Подключение новых устройств с помощью шестизначного кода"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Подключенные устройства"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Текущие подключения"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Сведения об устройстве"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Удалить"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Цифровой отпечаток устройства: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Не удалось установить подключение"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Убедитесь, что устройство \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" подключено к нужной сети."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Подключение к устройству"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код подключения к сети Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Не удалось подключить устройство"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Устройство должно быть подключено к той же самой сети."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Подключение устройства…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Не удалось подключить устройство. QR-код неверный, или устройство находится в другой сети."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адрес и порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканировать QR-код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Подключение устройства через Wi‑Fi с использованием QR-кода"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отладка, разработчик"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Отчет об ошибке"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Показывать в меню кнопки питания пункт для отправки отчета об ошибке"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Не выключать экран"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Использовать аппаратное ускорение в режиме модема (если доступно)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Разрешить отладку по USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Отладка по USB – это режим, который позволяет использовать ваше устройство как внешний накопитель: перемещать файлы (с компьютера и на компьютер), напрямую устанавливать приложения, а также просматривать системные журналы."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Разрешить отладку по Wi-Fi?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Отладка по Wi-Fi – это режим, предназначенный только для разработчиков. Он позволяет перемещать файлы между устройством и компьютером, напрямую устанавливать приложения, а также просматривать системные журналы."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Запретить доступ к USB-отладке для всех компьютеров, которым он был разрешен?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Изменение настроек"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Только для разработчиков. Изменение этих настроек может привести к сбоям или неправильной работе устройства и приложений."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалия (красный/зеленый)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалия (синий/желтый)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Коррекция цвета"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Коррекция цвета помогает пользователям с нарушениями цветового зрения лучше различать изображение на экране"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Новая настройка: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"Уровень заряда – <xliff:g id="PERCENTAGE">%1$s</xliff:g>. <xliff:g id="TIME_STRING">%2$s</xliff:g>."</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Заряда хватит примерно на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит менее чем на <xliff:g id="THRESHOLD">%1$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Уровень заряда батареи: <xliff:g id="LEVEL">%2$s</xliff:g> (хватит более чем на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Хватит более чем на <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон скоро завершит работу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Планшет скоро завершит работу"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Устройство скоро завершит работу"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Уровень заряда батареи: <xliff:g id="LEVEL">%1$s</xliff:g>. Телефон скоро завершит работу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Уровень заряда батареи: <xliff:g id="LEVEL">%1$s</xliff:g>. Планшет скоро завершит работу."</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Уровень заряда батареи: <xliff:g id="LEVEL">%1$s</xliff:g>. Устройство скоро завершит работу."</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон скоро выключится"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Планшет скоро выключится"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Устройство скоро выключится"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон скоро выключится (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшет скоро выключится (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Устройство скоро выключится (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до полной зарядки"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до полной зарядки"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Неизвестно"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Идет зарядка"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Быстрая зарядка"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Медленная зарядка"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряжается"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Подключено, не заряжается"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Батарея заряжена"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index f0a823a..c1452d2 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB නිදොස්කරණය"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB සම්බන්ධ විට නිදොස් ආකාරය"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB නිදොස් කිරීම් අනුමැති අහෝසි කරන්න"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"නොරැහැන් දෝෂාවේක්ෂණය"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi සම්බන්ධ විට දෝෂාවේක්ෂණ ප්‍රකාරය"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"දෝෂයකි"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"නොරැහැන් දෝෂාවේක්ෂණය"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"ලබා ගත හැකි උපාංග බැලීමට, නොරැහැන් දෝෂාවේක්ෂණය ක්‍රියාත්මක කරන්න"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR කේතය සමගින් උපාංගය යුගල කරන්න"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR කේත ස්කෑනරය භාවිතයෙන් නව උපාංග යුගල කරන්න"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"යුගල කිරීමේ කේතය සමගින් උපාංගය යුගල කරන්න"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ඉලක්කම් හයක කේතය භාවිතයෙන් නව උපාංග යුගල කරන්න"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"යුගල කළ උපාංග"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"දැනට සම්බන්ධ වී ඇත"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"උපාංග විස්තර"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"අමතක කරන්න"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"උපාංග ඇඟිලි සලකුණ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"සම්බන්ධය අසාර්ථකයි"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> නිවැරදි ජාලයට සම්බන්ධ කර ඇති බව සහතික කර ගන්න"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"උපංගය සමගින් යුගල කරන්න"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi යුගල කිරීමේ කේතය"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"යුගල කිරීම අසාර්ථකයි"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"උපාංගය එකම ජාලයට සම්බන්ධ කර ඇති බව සහතික කර ගන්න."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR කේතය ස්කෑන් කිරීමෙන් Wi‑Fi හරහා උපාංගය යුගල කරන්න"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"උපාංගය යුගල කරමින්…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"උපාංගය යුගල කිරීමට අසමත් විය. QR කේතය වැරදිය නැතහොත් එකම ජාලයට සම්බන්ධ කර නැත."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP ලිපිනය &amp; තොට"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR කේතය ස්කෑන් කරන්න"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR කේතය ස්කෑන් කිරීමෙන් Wi‑Fi හරහා උපාංගය යුගල කරන්න"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, දෝෂාවෙක්ෂණ, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"දෝෂය වාර්තා කිරීමේ කෙටිමඟ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"දෝෂ වාර්තාවක් ගැනීම සඳහා බල මෙනුව තුළ බොත්තම පෙන්වන"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"අවදියෙන් සිටින්න"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ලබා ගත හැකි නම්, ටෙදරින් දෘඪාංග ත්වරණය භාවිත කරන්න"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB දෝශාවේක්ෂණයට ඉඩ දෙන්නද?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB දෝශාවේක්ෂණය සංවර්ධන කටයුතු සඳහා පමණක් යොදාගැනේ. එය ඔබගේ පරිගණකය සහ ඔබගේ උපාංගය අතර දත්ත පිටපත් කිරීමට පමණක් භාවිතා කරන්න, ඔබගේ උපාංගය මත දැනුම්දීම් රහිතව යෙදුම් ස්ථාපනය කරන්න, සහ ලොග් දත්ත කියවන්න."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"නොරැහැන් දෝෂාවේක්ෂණය ඉඩ දෙන්නද?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"නොරැහැන් දෝෂාවේක්ෂණය සංවර්ධන කටයුතු සඳහා පමණක් අදහස් කරයි. එය ඔබේ පරිගණකය සහ ඔබේ උපාංගය අතර දත්ත පිටපත් කිරීමට, දැනුම් දීමක් නොමැතිව ඔබේ උපාංගයේ යෙදුම් ස්ථාපනය කිරීමට සහ ලොග දත්ත කියවීමට පමණක් භාවිත කරන්න."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ඔබ මින්පෙර අවසර ලබාදුන් සියළුම පරිගණක වෙතින් USB නිදොස්කරණට ප්‍රවේශය අහෝසි කරන්නද?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"සංවර්ධන සැකසීම් වවලට අවසර දෙන්නද?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"මෙම සැකසීම් වර්ධක භාවිතය සඳහා පමණි. ඔබගේ උපාංගයේ සහ යෙදුම්වල අක්‍රිය වීමට හෝ වැරදි ක්‍රියා කෙරුමකට ඒවා බලපෑ හැක."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"වර්ණ දුර්වලතාවය (රතු-කොළ)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"වර්ණ අන්ධතාවය (නිල්-කහ)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"වර්ණ නිවැරදි කිරීම"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"වර්ණ අන්ධතාවෙන් පෙළෙන පුද්ගලයන්ට වඩාත් නිරවද්‍ය වර්ණ බැලීමට වර්ණ නිවැරදි කිරීම සහාය වේ"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> මගින් ඉක්මවන ලදී"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> ක් පමණ ඉතිරියි"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>ට වඩා අඩුවෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>ට වඩා වැඩියෙන් ඉතිරිය (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>කට වඩා වැඩියෙන් ඉතිරිය"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ටැබ්ලටය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"දුරකථනය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ටැබ්ලටය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"උපාංගය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"දුරකථනය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ටැබ්ලට් පරිගණකය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"උපාංගය ඉක්මනින් වැසිය හැකිය"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"දුරකථනය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ටැබ්ලට් පරිගණකය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"උපාංගය ඉක්මනින් වැසිය හැකිය (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ආරෝපණය වන තෙක් <xliff:g id="TIME">%1$s</xliff:g> ඇත"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ආරෝපණය වන තෙක් <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"නොදනී"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ආරෝපණය වෙමින්"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"ශීඝ්‍ර ආරෝපණය"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"සෙමින් ආරෝපණය"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ආරෝපණය නොවේ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"පේනුගත කර ඇත, මේ අවස්ථාවේදී ආරෝපණය කළ නොහැකිය"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"පූර්ණ"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index fc2ba1d..0f1fbce 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Ladenie cez USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Povoliť režim ladenia s pripojeným zariadením USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Odvolať autorizácie na ladenie cez USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Bezdrôtové ladenie"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Režim ladenia pri zapnutej sieti Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Chyba"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Bezdrôtové ladenie"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Ak chcete zobraziť a používať dostupné zariadenia, zapnite bezdrôtové ladenie"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Spárovať zariadenie pomocou QR kódu"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Spárujte nové zariadenia pomocou skenera QR kódov"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Spárovať zariadenie pomocou párovacieho kódu"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Spárujte nové zariadenia pomocou šesťmiestneho kódu"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Spárované zariadenia"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Aktuálne pripojené"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Podrobnosti o zariadení"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Odstrániť"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Digitálny odtlačok zariadenia: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Pripojenie zlyhalo"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Skontrolujte, či je zariadenie <xliff:g id="DEVICE_NAME">%1$s</xliff:g> pripojené k správnej sieti"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Párovanie so zariadením"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Párovací kód siete Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Párovanie zlyhalo"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Skontrolujte, či je zariadenie pripojené k rovnakej sieti."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Spárujte zariadenie cez sieť Wi-Fi naskenovaním QR kódu"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Páruje sa zariadenie…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Zariadenie sa nepodarilo spárovať. Buď bol QR kód nesprávny, alebo zariadenie nie je pripojené k rovnakej sieti."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa IP a port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Naskenujte QR kód"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Spárujte zariadenie cez sieť Wi-Fi naskenovaním QR kódu"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, ladenie, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Skratka hlásenia chyby"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Zobraziť v hlavnej ponuke tlačidlo na vytvorenie hlásenia chyby"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Nevypínať obrazovku"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Ak je k dispozícii hardvérová akcelerácia tetheringu, používať ju"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Povoliť ladenie cez USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ladenie cez USB je určené iba na účely vývoja. Možno ho použiť na kopírovanie dát medzi počítačom a zariadením, inštaláciu aplikácií do zariadenia bez upozornenia a čítanie dát denníka."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Chcete povoliť bezdrôtové ladenie?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Bezdrôtové ladenie je určené iba na účely vývoja. Môžete pomocou neho kopírovať dáta medzi počítačom a zariadením, inštalovať bez upozornenia aplikácie do zariadenia a čítať dáta denníkov."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Chcete všetkým v minulosti autorizovaným počítačom odvolať prístup k ladeniu cez USB?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Povoliť nastavenia pre vývojárov?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Tieto nastavenia sú určené len pre vývojárov. Môžu spôsobiť poruchu alebo nesprávne fungovanie zariadenia a nainštalovaných aplikácií."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomália (červená a zelená)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomália (modrá a žltá)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Úprava farieb"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korekcia farieb pomáha farboslepým ľuďom vidieť presnejšie farby"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Prekonané predvoľbou <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zostáva približne <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zostáva menej ako <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Zostáva viac ako <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefón sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Zariadenie sa môže čoskoro vypnúť"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefón sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Zariadenie sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefón sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Zariadenie sa môže čoskoro vypnúť"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefón sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Zariadenie sa môže čoskoro vypnúť (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zostávajúci čas do úplného nabitia: <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do úplného nabitia"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznáme"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nabíja sa"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Rýchle nabíjanie"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Pomalé nabíjanie"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nenabíja sa"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Pripojené, ale nie je možné nabíjať"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Nabitá"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index cda2e06..08a74fb 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Odpravljanje težav prek USB-ja"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Način za odpravljanje težav, ko je vzpostavljena povezava USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Preklic dovoljenj za odpravljanje težav prek povezave USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Brezžično odpravljanje napak"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Način za odpravljanje napak pri vzpostavljeni povezavi Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Napaka"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Brezžično odpravljanje napak"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Če si želite ogledati in uporabljati razpoložljive naprave, vklopite brezžično odpravljanje napak"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Seznanjanje naprave s kodo QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Seznanjanje novih naprav z optičnim bralnikom kod QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Seznanjanje naprave s kodo za seznanjanje"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Seznanjanje novih naprav s šestmestno kodo"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Seznanjene naprave"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Trenutno povezano"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Podrobnosti o napravi"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Pozabi"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Prstni odtis naprave: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Povezava neuspešna"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Preverite, ali je naprava <xliff:g id="DEVICE_NAME">%1$s</xliff:g> povezana v ustrezno omrežje"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Seznanitev z napravo"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Koda za seznanjanje po Wi‑Fi-ju"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Seznanjanje neuspešno"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Preverite, ali je naprava povezana v isto omrežje."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Seznanitev naprave prek Wi‑Fi-ja z optičnim branjem kode QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Seznanjanje naprave …"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Seznanitev naprave ni uspela. Koda QR je nepravilna ali pa naprava ni povezana v isto omrežje."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Naslov IP in vrata"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Optično branje kode QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Seznanitev naprave prek Wi‑Fi-ja z optičnim branjem kode QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, odpravljanje napak, razvoj"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Bližnjica za poročanje o napakah"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Prikaz gumba za ustvarjanje poročila o napakah v meniju za vklop/izklop"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Brez izklopa zaslona"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Uporabi strojno pospeševanje za internetno povezavo prek mobilnega telefona, če je na voljo"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Ali dovolite odpravljanje težav s povezavo USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Odpravljanje težav s povezavo USB je namenjeno samo za razvoj. Lahko ga uporabljate za kopiranje podatkov med računalnikom in napravo, nameščanje aplikacij v napravo brez obveščanja in branje podatkov v dnevniku."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Ali dovolite brezžično odpravljanje napak?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Brezžično odpravljanje napak je namenjeno samo za razvoj. Lahko ga uporabljate za kopiranje podatkov med računalnikom in napravo, nameščanje aplikacij v napravo brez obveščanja in branje podatkov v dnevniku."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Ali želite preklicati dostop do odpravljanja težav prek povezave USB iz vseh računalnikov, ki ste jih pooblastili?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ali želite omogočiti nastavitve za razvijanje?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Te nastavitve so namenjene samo za razvijanje in lahko povzročijo prekinitev ali napačno delovanje naprave in aplikacij v njej."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomalija (rdeča – zelena)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomalija (modra – rumena)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Popravljanje barv"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Popravljanje barv osebam z barvno slepoto pomaga, da vidijo razločnejše barve"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Preglasila nastavitev: <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Še približno <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Preostanek: manj kot <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Preostali čas delovanja: manj kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Preostali čas delovanja: več kot <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablični računalnik se bo morda kmalu zaustavil"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Naprava se bo morda kmalu zaustavila"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon se bo morda kmalu zaustavil (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablični računalnik se bo morda kmalu zaustavil (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Naprava se bo morda kmalu zaustavila (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablični računalnik se bo morda kmalu zaustavil"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Naprava se bo morda kmalu zaustavila"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon se bo morda kmalu zaustavil (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablični računalnik se bo morda kmalu zaustavil (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Naprava se bo morda kmalu zaustavila (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Še <xliff:g id="TIME">%1$s</xliff:g> do polne napolnjenosti"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> do polne napolnjenosti"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Neznano"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Polnjenje"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hitro polnjenje"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Počasno polnjenje"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Se ne polni"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Priključeno, trenutno ni mogoče polniti"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Poln"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 9854017..1bd9424 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Korrigjimi i USB-së"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Korrigjo gabimet e modalitetit kur UBS-ja është e lidhur"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Anulo autorizimet e korrigjimeve të gabimeve të USB-së"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Korrigjimi me valë"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Regjimi i korrigjimit kur Wi‑Fi është i lidhur"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Gabim"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Korrigjimi me valë"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Për të parë dhe përdorur pajisjet e disponueshme, aktivizo korrigjimin me valë"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Çifto pajisjen me kod QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Çifto pajisjet e reja duke përdorur skanerin e kodeve QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Çifto pajisjen me kodin e çiftimit"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Çifto pajisjet e reja duke përdorur kodin me gjashtë shifra"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Pajisjet e çiftuara"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Të lidhur aktualisht"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Detajet e pajisjes"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Harro"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Gjurma e gishtit e pajisjes: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Lidhja ishte e pasuksesshme"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Sigurohu që <xliff:g id="DEVICE_NAME">%1$s</xliff:g> të jetë e lidhur me rrjetin e duhur"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Çifto me pajisjen"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kodi i çiftimit të Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Çiftimi ishte i pasuksesshëm"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Sigurohu që pajisja të jetë e lidhur me të njëjtin rrjet"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Çifto pajisjen përmes Wi‑Fi duke skanuar një kod QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Po çifton pajisjen…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Çiftimi i pajisjes dështoi. Ose kodi QR nuk ishte i saktë, ose pajisja nuk është e lidhur me të njëjtin rrjet."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Adresa e IP-së dhe porta"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skano kodin QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Çifto pajisjen përmes Wi‑Fi duke skanuar një kod QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, korrigjimi, zhvilluesi"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Shkurtorja e raportit të defektit në kod"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Shfaq një buton në menynë e fikjes për marrjen e raportit të defekteve"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Qëndro zgjuar"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Përdor përshpejtimin e harduerit për ndarjen e lidhjes (internet) nëse është i disponueshëm"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Të lejohet korrigjimi i USB-së?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Korrigjuesi i USB-së është vetëm për qëllime zhvillimore. Përdore për të kopjuar të dhëna mes kompjuterit dhe pajisjes tënde, për të instaluar aplikacione në pajisjen tënde pa asnjë njoftim si dhe për të lexuar të dhënat e ditarit."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Të lejohet korrigjimi me valë?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Korrigjimi me valë është vetëm për qëllime zhvillimore. Përdore për të kopjuar të dhëna mes kompjuterit dhe pajisjes sate, për të instaluar aplikacione në pajisjen tënde pa asnjë njoftim si dhe për të lexuar të dhënat e regjistrit."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Të bllokohet qasja për korrigjim të USB-së nga të gjithë kompjuterët që ke autorizuar më parë?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Të lejohen cilësimet e zhvillimit?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Këto cilësime janë të projektuara vetëm për përdorim në programim. Ato mund të shkaktojnë që pajisja dhe aplikacionet në të, të mos punojnë ose të veprojnë në mënyrë të gabuar."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (e kuqe - e gjelbër)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (e kaltër - e verdhë)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Korrigjimi i ngjyrës"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Korrigjimi i ngjyrës i ndihmon njerëzit me daltonizëm të shohin ngjyra më të sakta"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Mbivendosur nga <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Rreth <xliff:g id="TIME_REMAINING">%1$s</xliff:g> të mbetura"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mbeten më pak se <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mbeten më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mbeten më shumë se <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefoni mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tableti mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Pajisja mund të fiket së shpejti"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefoni mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tableti mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Pajisja mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefoni mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tableti mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Pajisja mund të fiket së shpejti"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefoni mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tableti mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Pajisja mund të fiket së shpejti (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> të mbetura për karikimin"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> deri sa të karikohen"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"I panjohur"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Po karikohet"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Po ngarkon me shpejtësi"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Po karikohet ngadalë"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Nuk po karikohet"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Në prizë, por nuk mund të ngarkohet për momentin"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"E mbushur"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index b59a568..3355c57 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Отклањање USB грешака"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Режим отклањања грешака када је USB повезан"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Опозивање одобрења за уклањање USB грешака"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Бежично отклањање грешака"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Режим за отклањање грешака када је Wi‑Fi повезан"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Грешка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Бежично отклањање грешака"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Да бисте видели и користили доступне уређаје, укључите бежично отклањање грешака"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Упарите уређај помоћу QR кода"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Упарите нове уређаје помоћу читача QR кода"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Упарите уређај помоћу кода за упаривање"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Упарите нове уређаје помоћу шестоцифреног кода"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Упарени уређаји"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Тренутно је повезано"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Детаљи о уређају"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Заборави"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Отисак прста на уређају: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Повезивање није успело"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Уверите се да је <xliff:g id="DEVICE_NAME">%1$s</xliff:g> повезан са одговарајућом мрежом"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Упарите са уређајем"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Кôд за упаривање преко Wi‑Fi-ја"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Упаривање није успело"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Уверите се да је уређај повезан на исту мрежу."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Упарите уређај помоћу Wi‑Fi мреже или тако што ћете скенирати QR кôд"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Упарује се уређај…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Упаривање уређаја није успело. QR кôд је погрешан или уређај није повезан са истом мрежом."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP адреса и порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Скенирај QR кôд"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Упарите уређај помоћу Wi‑Fi мреже или тако што ћете скенирати QR кôд"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, отклањање грешака, програмер"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Пречица за извештај о грешкама"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Прикажи дугме у менију напајања за прављење извештаја о грешкама"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Не закључавај"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Користи хардверско убрзање привезивања ако је доступно"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Дозволи отклањање USB грешака?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Отклањање USB грешака намењено је само за сврхе програмирања. Користите га за копирање података са рачунара на уређај и обрнуто, инсталирање апликација на уређају без обавештења и читање података из евиденције."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Желите да дозволите бежично отклањање грешака?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Бежично отклањање грешака намењено је само програмирању. Користите га за копирање података са рачунара на уређај и обрнуто, инсталирање апликација на уређају без обавештења и читање података из евиденције."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Желите ли да опозовете приступ отклањању USB грешака са свих рачунара које сте претходно одобрили?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Желите ли да омогућите програмерска подешавања?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ова подешавања су намењена само за програмирање. Могу да изазову престанак функционисања или неочекивано понашање уређаја и апликација на њему."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалија (црвено-зелено)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалија (плаво-жуто)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекција боја"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Корекција боја помаже људима који су далтонисти да прецизније виде боје"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замењује га <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g>–<xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Преостало је око <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Преостало је мање од <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Преостало је више од <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Таблет ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Уређај ће се ускоро искључити"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Телефон ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Таблет ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Уређај ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Таблет ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Уређај ће се ускоро искључити"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Таблет ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Уређај ће се ускоро искључити (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Напуниће се за <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – напуниће се за <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Непознато"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Пуни се"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Брзо се пуни"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Споро се пуни"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не пуни се"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Прикључено је, али пуњење тренутно није могуће"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Пуна"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index f9ed6d4..fce23af 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB-felsökning"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Felsökningsläge när USB har anslutits"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Återkalla åtkomst till USB-felsökning"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Trådlös felsökning"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Felsökningsläge vid Wi-Fi-anslutning"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Fel"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Trådlös felsökning"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Aktivera trådlös felsökning om du vill se tillgängliga enheter"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Parkoppla enheten med en QR-kod"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Koppla nya enheter med QR-kodsläsare"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Koppla enheten med en kopplingskod"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Koppla nya enheter med en sexsiffrig kod"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Kopplade enheter"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Anslutna just nu"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Enhetsinformation"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Glöm"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Enhetens signatur: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Det gick inte att ansluta"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Kontrollera att <xliff:g id="DEVICE_NAME">%1$s</xliff:g> är ansluten till rätt nätverk"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Parkoppla med enheten"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi-kopplingskod"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Det gick inte att parkoppla"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Kontrollera att enheten är ansluten till samma nätverk."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Parkoppla enheten via Wi-Fi genom att skanna en QR-kod"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Enheten parkopplas …"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Det gick inte att parkoppla enheten. Antingen var det fel QR-kod eller är enheten inte ansluten till samma nätverk."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-adress och port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skanna QR-kod"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Parkoppla enheten via Wi-Fi genom att skanna en QR-kod"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev, felsöka, felsökning"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Genväg till felrapport"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Visa en knapp för felrapportering i extramenyn"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Håll aktiverad"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Använd maskinvaruacceleration för internetdelning om tillgängligt"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Ska USB-felsökning tillåtas?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB-felsökning ska endast användas i utvecklingssyfte. Använd den för att kopiera data mellan datorn och enheten, installera appar på enheten utan meddelanden och läsa loggdata."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vill du tillåta trådlös felsökning?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Trådlös felsökning ska endast användas i utvecklingssyfte. Använd den för att kopiera data mellan datorn och enheten, installera appar på enheten utan meddelanden och läsa loggdata."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Vill du återkalla åtkomst till USB-felsökning för alla datorer som du tidigare har godkänt?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Tillåt utvecklarinställningar?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Inställningarna är endast avsedda att användas för utvecklingsändamål. De kan orsaka problem med enheten eller apparna som finns installerade på den."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomali (rött-grönt)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomali (blått-gult)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Färgkorrigering"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Med färgkorrigering kan färgblinda personer se mer korrekta färger"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Har åsidosatts av <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cirka <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kvar"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Mindre än <xliff:g id="THRESHOLD">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mer än <xliff:g id="TIME_REMAINING">%1$s</xliff:g> återstår"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Mobilen kan stängas av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Surfplattan kan stängas av snart"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Enheten kan stängas av snart"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Mobilen kan stängas av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Surfplattan kan stängas av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Enheten kan stängas av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefonen kanske stängs av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Surfplattan kanske stängs av snart"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Enheten kanske stängs av snart"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefonen kanske stängs av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Surfplattan kanske stängs av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Enheten kanske stängs av snart (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> kvar till full laddning"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> till full laddning"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Okänd"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Laddar"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Laddas snabbt"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Laddas långsamt"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Laddar inte"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Inkopplad, kan inte laddas just nu"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Fullt"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 40e025a..3ca705f 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Utatuzi wa USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Muundo wa kurekebisha wakati USB imeunganishwa"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Batilisha idhini za kurekebisha USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Utatuzi usiotumia waya"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Hali ya utatuzi wakati Wi-Fi imeunganishwa"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Hitilafu"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Utatuzi usiotumia waya"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Ili kungalia na kutumia vifaa vinavyopatikana, washa utatuzi usiotumia waya"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Oanisha kifaa ukitumia msimbo wa QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Oanisha vifaa vipya ukitumia Kichanganuzi cha Msimbo wa QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Oanisha kifaa ukitumia msimbo wa kuoanisha"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Oanisha vifaa vipya ukitumia msimbo wa tarakimu sita"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Vifaa vilivyooanishwa"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Vilivyounganishwa kwa sasa"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Maelezo ya kifaa"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Sahau"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Alama bainifu ya kifaa: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Imeshindwa kuunganisha"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Hakikisha kuwa <xliff:g id="DEVICE_NAME">%1$s</xliff:g> kimeunganishwa kwenye mtandao sahihi"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Oanisha na kifaa"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Msimbo wa kuoanisha wa Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Imeshindwa kuunganisha"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Hakikisha kuwa kifaa kimeunganishwa kwenye mtandao mmoja."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Oanisha kifaa kupitia Wi-Fi kwa kuchanganua msimbo wa QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Inaoanisha kifaa…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Imeshindwa kuoanisha kifaa. Huenda msimbo wa QR haukuwa sahihi au kifaa hakijaunganishwa kwenye mtandao mmoja."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Anwani ya IP na Mlango"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Changanua msimbo wa QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Oanisha kifaa kupitia Wi-Fi kwa kuchanganua Msimbo wa QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, tatua, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Njia ya mkato ya kuripoti hitilafu"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Onyesha kitufe cha kuripoti hitilafu katika menyu ya kuzima/kuwasha kifaa"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Weka skrini ikiwa imewashwa"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Tumia huduma ya kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao ikiwa inapatikana"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Ruhusu utatuaji USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ueuaji wa USB umekusudiwa kwa malengo ya utengenezaji tu. Itumi kunakili data kati ya kompyuta yako na kifaa chako, kusanidi programu kwa kifaa chako bila arifa, na kusoma data ya rajisi."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Ungependa kuruhusu utatuzi usiotumia waya?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Utatuzi usiotumia waya umekusudiwa kwa malengo ya usanidi tu. Utumie kunakili data kati ya kompyuta yako na kifaa chako, kusakinisha programu kwenye kifaa chako bila arifa na kusoma data ya kumbukumbu."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Unataka kubatilisha ufikiaji wa urekebishaji wa USB kutoka kwenye kompyuta zote ulizotangulia kuidhinisha?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Ruhusu mipangilio ya usanidi?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Mipangilio hii imekusudiwa kwa matumizi ya usanidi tu. Inaweza kusababisha kifaa chako na programu zilizoko kuvunjika au kutofanya kazi vizuri."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (nyekundu-kijani)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (samawati-manjano)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Usahihishaji wa rangi"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Urekebishaji wa rangi huwasaidia watu wenye matatizo ya kutofautisha rangi ili waone rangi nyingi sahihi"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Imetanguliwa na <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Zimesalia takribani <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Zimesalia chini ya <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Zimesalia zaidi ya <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Simu inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Kompyuta kibao inakaribia kuzimika"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Kifaa kinakaribia kuzimika"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Simu inakaribia kuzimika (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Kompyuta kibao inakaribia kuzimika (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Kifaa kinakaribia kuzimika (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Huenda simu ikazima hivi karibuni"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Huenda kompyuta yako kibao ikazima hivi karibuni"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Huenda kifaa kikazima hivi karibuni"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Huenda simu ikazima hivi karibuni (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Huenda kompyuta kibao ikazima hivi karibuni (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Huenda kifaa kikazima hivi karibuni (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Zimesalia <xliff:g id="TIME">%1$s</xliff:g> hadi ijae chaji"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hadi ijae chaji"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Haijulikani"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Inachaji"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Inachaji kwa kasi"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Inachaji pole pole"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Haichaji"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Haiwezi kuchaji kwa sasa"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Imejaa"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index 36a92ed..4f0b779 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -149,7 +149,7 @@
     <string name="tether_settings_title_usb_bluetooth" msgid="1727111807207577322">"டெதெரிங்"</string>
     <string name="tether_settings_title_all" msgid="8910259483383010470">"டெதெரிங் &amp; போர்டபிள் ஹாட்ஸ்பாட்"</string>
     <string name="managed_user_title" msgid="449081789742645723">"எல்லா பணிப் பயன்பாடுகளும்"</string>
-    <string name="user_guest" msgid="6939192779649870792">"வேறொருவர்"</string>
+    <string name="user_guest" msgid="6939192779649870792">"கெஸ்ட்"</string>
     <string name="unknown" msgid="3544487229740637809">"அறியப்படாத"</string>
     <string name="running_process_item_user_label" msgid="3988506293099805796">"பயனர்: <xliff:g id="USER_NAME">%1$s</xliff:g>"</string>
     <string name="launch_defaults_some" msgid="3631650616557252926">"சில இயல்புநிலைகள் அமைக்கப்பட்டன"</string>
@@ -206,6 +206,60 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB பிழைதிருத்தம்"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB இணைக்கப்பட்டிருக்கும்போது பிழைத்திருத்தப் பயன்முறையை அமை"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB பிழைத்திருத்த அங்கீகரிப்புகளை நிராகரி"</string>
+    <!-- no translation found for enable_adb_wireless (6973226350963971018) -->
+    <skip />
+    <!-- no translation found for enable_adb_wireless_summary (7344391423657093011) -->
+    <skip />
+    <!-- no translation found for adb_wireless_error (721958772149779856) -->
+    <skip />
+    <!-- no translation found for adb_wireless_settings (2295017847215680229) -->
+    <skip />
+    <!-- no translation found for adb_wireless_list_empty_off (1713707973837255490) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_title (6982904096137468634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_qrcode_summary (3729901496856458634) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_title (1122590300445142904) -->
+    <skip />
+    <!-- no translation found for adb_pair_method_code_summary (6370414511333685185) -->
+    <skip />
+    <!-- no translation found for adb_paired_devices_title (5268997341526217362) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_connected_summary (3039660790249148713) -->
+    <skip />
+    <!-- no translation found for adb_wireless_device_details_title (7129369670526565786) -->
+    <skip />
+    <!-- no translation found for adb_device_forget (193072400783068417) -->
+    <skip />
+    <!-- no translation found for adb_device_fingerprint_title_format (291504822917843701) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_title (664211177427438438) -->
+    <skip />
+    <!-- no translation found for adb_wireless_connection_failed_message (9213896700171602073) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_title (7141739231018530210) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_pairing_code_label (3639239786669722731) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_title (3426758947882091735) -->
+    <skip />
+    <!-- no translation found for adb_pairing_device_dialog_failed_msg (6611097519661997148) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_summary (8051414549011801917) -->
+    <skip />
+    <!-- no translation found for adb_wireless_verifying_qrcode_text (6123192424916029207) -->
+    <skip />
+    <!-- no translation found for adb_qrcode_pairing_device_failed_msg (6936292092592914132) -->
+    <skip />
+    <!-- no translation found for adb_wireless_ip_addr_preference_title (8335132107715311730) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_title (1906409667944674707) -->
+    <skip />
+    <!-- no translation found for adb_wireless_qrcode_pairing_description (8578868049289910131) -->
+    <skip />
+    <!-- no translation found for keywords_adb_wireless (6507505581882171240) -->
+    <skip />
     <string name="bugreport_in_power" msgid="8664089072534638709">"பிழைப் புகாருக்கான ஷார்ட்கட்"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"பிழை அறிக்கையைப் பெற பவர் மெனுவில் விருப்பத்தைக் காட்டு"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"செயலில் வைத்திரு"</string>
@@ -271,6 +325,10 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை கிடைக்கும் போது, அதைப் பயன்படுத்தும்"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB பிழைதிருத்தத்தை அனுமதிக்கவா?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB பிழைதிருத்தம் மேம்படுத்தல் நோக்கங்களுக்காக மட்டுமே. அதை உங்கள் கணினி மற்றும் சாதனத்திற்கு இடையில் தரவை நகலெடுக்கவும், அறிவிப்பு இல்லாமல் உங்கள் சாதனத்தில் ஆப்ஸை நிறுவவும், பதிவு தரவைப் படிக்கவும் பயன்படுத்தவும்."</string>
+    <!-- no translation found for adbwifi_warning_title (727104571653031865) -->
+    <skip />
+    <!-- no translation found for adbwifi_warning_message (8005936574322702388) -->
+    <skip />
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"நீங்கள் ஏற்கனவே அனுமதித்த எல்லா கணினிகளிலிருந்தும் USB பிழைத்திருத்தத்திற்கான அணுகலைத் திரும்பப்பெற வேண்டுமா?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"மேம்பட்ட அமைப்புகளை அனுமதிக்கவா?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"இந்த அமைப்பு மேம்பட்டப் பயன்பாட்டிற்காக மட்டுமே. உங்கள் சாதனம் மற்றும் அதில் உள்ள பயன்பாடுகளைச் சிதைக்கும் அல்லது தவறாகச் செயல்படும் வகையில் பாதிப்பை ஏற்படுத்தும்."</string>
@@ -403,12 +461,18 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>க்கும் குறைவாகவே பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>க்கும் மேல் பயன்படுத்த முடியும் (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>க்கும் மேல் பயன்படுத்த முடியும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"மொபைல் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"சாதனம் விரைவில் ஆஃப் ஆகக்கூடும்"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"மொபைல் விரைவில் ஆஃப் ஆகக்கூடும் (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"டேப்லெட் விரைவில் ஆஃப் ஆகக்கூடும் (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"சாதனம் விரைவில் ஆஃப் ஆகக்கூடும் (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (137330009791560774) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (145489081521468132) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_only_shutdown_imminent (1070562682853942350) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4429259621177089719) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (7703677921000858479) -->
+    <skip />
+    <!-- no translation found for power_remaining_duration_shutdown_imminent (4374784375644214578) -->
+    <skip />
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"முழு சார்ஜாக <xliff:g id="TIME">%1$s</xliff:g> ஆகும்"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - முழு சார்ஜாக <xliff:g id="TIME">%2$s</xliff:g> ஆகும்"</string>
@@ -439,7 +503,7 @@
     <string name="screen_zoom_summary_large" msgid="4706951482598978984">"பெரியது"</string>
     <string name="screen_zoom_summary_very_large" msgid="7317423942896999029">"கொஞ்சம் பெரியது"</string>
     <string name="screen_zoom_summary_extremely_large" msgid="1438045624562358554">"மிகப் பெரியது"</string>
-    <string name="screen_zoom_summary_custom" msgid="3468154096832912210">"தனிப்பயன் (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
+    <string name="screen_zoom_summary_custom" msgid="3468154096832912210">"பிரத்தியேக (<xliff:g id="DENSITYDPI">%d</xliff:g>)"</string>
     <string name="content_description_menu_button" msgid="6254844309171779931">"மெனு"</string>
     <string name="retail_demo_reset_message" msgid="5392824901108195463">"டெமோ பயன்முறையில் ஆரம்பநிலை மீட்டமைவைச் செயல்படுத்த, கடவுச்சொல்லை உள்ளிடவும்"</string>
     <string name="retail_demo_reset_next" msgid="3688129033843885362">"அடுத்து"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index 5ea380c..3a354e0 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB డీబగ్గింగ్"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB కనెక్ట్ చేయబడినప్పుడు డీబగ్ మోడ్"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB డీబగ్ ప్రామాణీకరణలను ఉపసంహరించు"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"వైర్‌లెస్ డీబగ్గింగ్"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi-Fi కనెక్ట్ అయి ఉన్నప్పుడు, డీబగ్ మోడ్‌లో ఉంచు"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ఎర్రర్"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"వైర్‌లెస్ డీబగ్గింగ్"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"అందుబాటులో వున్న పరికరాలను చూడటానికి, ఉపయోగించడానికి, వైర్‌లెస్ డీబగ్గింగ్‌ను ఆన్ చేయండి"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR కోడ్‌తో పరికరాన్ని పెయిర్ చేయండి"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR కోడ్ స్కానర్‌ను ఉపయోగించి కొత్త పరికరాలను పెయిర్ చేయండి"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"పెయిరింగ్ కోడ్‌తో పరికరాన్ని పెయిర్ చేయండి"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"ఆరు అంకెల కోడ్‌ను ఉపయోగించి కొత్త పరికరాలను పెయిర్ చేయండి"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"పెయిర్ చేయబడిన పరికరాలు"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"ప్రస్తుతం కనెక్ట్ చేయబడింది"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"పరికర వివరాలు"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"విస్మరించు"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"పరికరం వేలిముద్ర: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"కనెక్షన్ విఫలమైంది"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> సరైన నెట్‌వర్క్‌కు కనెక్ట్ అయ్యేలా చూడండి."</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"పరికరంతో పెయిర్ చేయండి"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi పెయిరింగ్ కోడ్"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"పెయిరింగ్ విఫలమైంది"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"పరికరం అదే నెట్‌వర్క్‌కు కనెక్ట్ అయి వుందో లేదో సరి చూసుకోండి."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR కోడ్‌ను స్కాన్ చేయడం ద్వారా Wi-Fiని ఉపయోగించి పరికరాన్ని పెయిర్ చెయ్యండి"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"పరికరం పెయిర్ చేయబడుతోంది…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"పరికరాన్ని పెయిర్ చేయడం విఫలమైంది. QR కోడ్ తప్పుగా ఉండడం గాని, లేదా పరికరం అదే నెట్‌వర్క్‌కు కనెక్ట్ అయి లేకపోవడం గాని జరిగింది."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP చిరునామా &amp; పోర్ట్"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR కోడ్‌ను స్కాన్ చేయండి"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"పరికరాన్ని Wi-Fi ద్వారా పెయిర్ చేయడానికి QR కోడ్‌ను స్కాన్ చేయండి"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, డీబగ్, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"బగ్ నివేదిక షార్ట్‌కట్"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"బగ్ నివేదికను తీసుకోవడానికి పవర్ మెనూలో బటన్‌ను చూపు"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"యాక్టివ్‌గా ఉంచు"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"అందుబాటులో ఉంటే టెథెరింగ్ హార్డ్‌వేర్ వేగవృద్ధిని ఉపయోగించండి"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్ మరియు మీ పరికరం మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో అనువర్తనాలను ఇన్‌స్టాల్ చేయడానికి మరియు లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"వైర్‌లెస్ డీబగ్గింగ్‌ను అనుమతించాలా?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"వైర్‌లెస్ డీబగ్గింగ్ అనేది అభివృద్ధి ప్రయోజనాల కోసం మాత్రమే ఉద్దేశించబడింది. మీ కంప్యూటర్, పరికరాల మధ్య డేటాను కాపీ చేయడానికి, నోటిఫికేషన్ లేకుండా మీ పరికరంలో యాప్‌లను ఇన్‌స్టాల్ చేయడానికి, లాగ్ డేటాను చదవడానికి దీన్ని ఉపయోగించండి."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"మీరు గతంలో ప్రామాణీకరించిన అన్ని కంప్యూటర్‌ల నుండి USB డీబగ్గింగ్‌కు ప్రాప్యతను ఉపసంహరించాలా?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"అభివృద్ధి సెట్టింగ్‌లను అనుమతించాలా?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"ఈ సెట్టింగ్‌లు అభివృద్ధి వినియోగం కోసం మాత్రమే ఉద్దేశించబడినవి. వీటి వలన మీ పరికరం మరియు దీనిలోని యాప్‌లు విచ్ఛిన్నం కావచ్చు లేదా తప్పుగా ప్రవర్తించవచ్చు."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ప్రొటానోమలీ (ఎరుపు-ఆకుపచ్చ రంగు)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ట్రైటనోమలీ (నీలం-పసుపు రంగు)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"రంగు సవరణ"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"రంగులను సరి చేయడం వల్ల, కలర్ బ్లైండ్‌నెస్ ఉన్నవారు మరింత ఖచ్చితమైన రంగులను చూడగలుగుతారు"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> ద్వారా భర్తీ చేయబడింది"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> కంటే తక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> కంటే ఎక్కువ సమయం మిగిలి ఉంది"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"ఫోన్ షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"టాబ్లెట్ షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"ఫోన్ త్వరలో షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"టాబ్లెట్ త్వరలో షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"పరికరం త్వరలో షట్‌డౌన్ కావచ్చు (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%1$s</xliff:g> సమయం మిగిలి ఉంది"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - ఛార్జ్ అవ్వడానికి <xliff:g id="TIME">%2$s</xliff:g> పడుతుంది"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"తెలియదు"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"ఛార్జ్ అవుతోంది"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"వేగవంతమైన ఛార్జింగ్"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"నెమ్మదిగా ఛార్జింగ్"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ఛార్జ్ కావడం లేదు"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"ప్లగ్ ఇన్ చేయబడింది, ప్రస్తుతం ఛార్జ్ చేయడం సాధ్యం కాదు"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"నిండింది"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 15e74ae..e34c548 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"การแก้ไขข้อบกพร่อง USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"โหมดแก้ไขข้อบกพร่องเมื่อเชื่อมต่อ USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"ยกเลิกการให้สิทธิ์การแก้ปัญหา USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"การแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"โหมดแก้ไขข้อบกพร่องเมื่อเชื่อมต่อ Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"ข้อผิดพลาด"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"การแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"หากต้องการดูและใช้อุปกรณ์ที่มีอยู่ ให้เปิดการแก้ไขข้อบกพร่องผ่าน Wi-Fi"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"จับคู่อุปกรณ์ด้วยคิวอาร์โค้ด"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"จับคู่อุปกรณ์เครื่องใหม่โดยใช้เครื่องมือสแกนคิวอาร์โค้ด"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"จับคู่อุปกรณ์ด้วยรหัสการจับคู่"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"จับคู่อุปกรณ์เครื่องใหม่โดยใช้รหัสตัวเลข 6 หลัก"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"อุปกรณ์ที่จับคู่"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"เชื่อมต่ออยู่"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"รายละเอียดอุปกรณ์"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"ไม่จำ"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"ลายนิ้วมือของอุปกรณ์: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"การเชื่อมต่อไม่สำเร็จ"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"ตรวจสอบว่า <xliff:g id="DEVICE_NAME">%1$s</xliff:g> เชื่อมต่อกับเครือข่ายที่ถูกต้อง"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"จับคู่กับอุปกรณ์"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"รหัสการจับคู่ Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"การจับคู่ไม่สำเร็จ"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"ตรวจสอบว่าอุปกรณ์เชื่อมต่อกับเครือข่ายเดียวกัน"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"จับคู่อุปกรณ์ผ่าน Wi‑Fi ด้วยการสแกนคิวอาร์โค้ด"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"กำลังจับคู่อุปกรณ์…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"จับคู่อุปกรณ์ไม่สำเร็จ คิวอาร์โค้ดไม่ถูกต้อง หรืออุปกรณ์ไม่ได้เชื่อมต่อกับเครือข่ายเดียวกัน"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"ที่อยู่ IP และพอร์ต"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"สแกนคิวอาร์โค้ด"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"จับคู่อุปกรณ์ผ่าน Wi‑Fi ด้วยการสแกนคิวอาร์โค้ด"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, แก้ไขข้อบกพร่อง, พัฒนา"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"ทางลัดรายงานข้อบกพร่อง"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"แสดงปุ่มในเมนูเปิด/ปิดสำหรับการใช้รายงานข้อบกพร่อง"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"เปิดหน้าจอค้าง"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"ใช้การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ หากมี"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"อนุญาตให้แก้ไขข้อบกพร่อง USB หรือไม่"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"การแก้ไขข้อบกพร่อง USB มีไว้เพื่อการพัฒนาเท่านั้น ให้ใช้การแก้ไขนี้เพื่อคัดลอกข้อมูลระหว่างคอมพิวเตอร์และอุปกรณ์ ติดตั้งแอปพลิเคชันบนอุปกรณ์โดยไม่มีการแจ้งเตือน และอ่านข้อมูลบันทึก"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"อนุญาตให้แก้ไขข้อบกพร่องผ่าน Wi-Fi ไหม"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"การแก้ไขข้อบกพร่องผ่าน Wi-Fi มีไว้เพื่อการพัฒนาเท่านั้น ให้ใช้การแก้ไขนี้เพื่อคัดลอกข้อมูลระหว่างคอมพิวเตอร์และอุปกรณ์ ติดตั้งแอปในอุปกรณ์โดยไม่มีการแจ้งเตือน และอ่านข้อมูลบันทึก"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"ยกเลิกการเข้าถึงเพื่อแก้ปัญหาผ่าน USB จากคอมพิวเตอร์ทุกเครื่องที่คุณได้ให้สิทธิ์ก่อนหน้านี้ไหม"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"อนุญาตการตั้งค่าสำหรับการพัฒนาหรือไม่"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"การตั้งค่านี้มีไว้เพื่อการพัฒนาเท่านั้น จึงอาจทำให้อุปกรณ์และแอปพลิเคชันที่มีอยู่เสียหายหรือทำงานผิดพลาดได้"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"ตาบอดจางสีแดง (สีแดง/เขียว)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"ตาบอดจางสีน้ำเงิน (สีน้ำเงิน/เหลือง)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"การแก้สี"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"การแก้ไขสีช่วยให้ผู้ที่มีอาการตาบอดสีเห็นสีต่างๆ ได้ตรงตามจริงยิ่งขึ้น"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"เหลืออีกประมาณ <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"เหลือเวลาอีกไม่ถึง <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"เหลือเวลามากกว่า <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"โทรศัพท์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"อุปกรณ์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"โทรศัพท์อาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"อุปกรณ์อาจปิดเครื่องในไม่ช้า"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"โทรศัพท์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"แท็บเล็ตอาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"อุปกรณ์อาจปิดเครื่องในไม่ช้า (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"เหลือ <xliff:g id="TIME">%1$s</xliff:g> จนกว่าจะชาร์จ"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> จนกว่าจะชาร์จ"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"ไม่ทราบ"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"กำลังชาร์จ"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"กำลังชาร์จเร็ว"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"กำลังชาร์จอย่างช้าๆ"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"ไม่ได้ชาร์จ"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"เสียบอยู่ ไม่สามารถชาร์จได้ในขณะนี้"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"เต็ม"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index 8012244..ee04288 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Pag-debug ng USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Debug mode kapag nakakonekta ang USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Bawiin ang mga pahintulot sa pag-debug ng USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Wireless na pag-debug"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Debug mode kapag nakakonekta sa Wi‑Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Error"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Wireless na pag-debug"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Para makita at magamit ang mga available na device, i-on ang wireless na pag-debug"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Magpares ng device gamit ang QR code"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Magpares ng mga bagong device gamit ang QR code Scanner"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Pinapares ang device gamit ang code ng pagpapares"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Magpares ng mga bagong device gamit ang six digit na code"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Mga nakapares na device"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Kasalukuyang nakakonekta"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Mga detalye ng device"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Kalimutan"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Fingerprint ng device: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Hindi nagawang kumonekta"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Tiyaking tama ang network kung saan nakakonekta ang <xliff:g id="DEVICE_NAME">%1$s</xliff:g>"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Ipares sa device"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Code ng pagpapares sa Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Hindi nagawa ang pagpapares"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Tiyaking nakakonekta ang device sa parehong network."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Ipares ang device gamit ang Wi‑Fi sa pamamagitan ng pag-scan ng isang QR code"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Ipinapares ang device…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Hindi nagawang ipares ang device. Hindi tama ang QR code, o hindi nakakonekta ang device sa parehong network."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP address at Port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"I-scan ang QR code"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Ipares ang device gamit ang Wi‑Fi sa pamamagitan ng pag-scan ng isang QR Code"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debug, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Shortcut ng ulat sa bug"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Magpakita ng button sa power menu sa pagkuha ng ulat sa bug"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Manatiling gumagana"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Gamitin ang hardware acceleration para sa pag-tether kung available"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Payagan ang pag-debug ng USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ang pag-debug ng USB ay para lang sa mga layuning pag-develop. Gamitin ito upang kumopya ng data sa pagitan ng iyong computer at iyong device, mag-install ng mga app sa iyong device nang walang notification, at magbasa ng data ng log."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Pahintulutan ang wireless na pag-debug?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Ang wireless na pag-debug ay para lang sa layunin ng pag-develop. Gamitin ito para kumopya ng data sa iyong computer at device mo, mag-install ng mga app sa iyong device nang walang notification, at magbasa ng data ng log."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Bawiin ang access sa pag-debug ng USB mula sa lahat ng computer na dati mong pinahintulutan?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Payagan ang mga setting ng pag-develop?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Nilalayon ang mga setting na ito para sa paggamit sa pag-develop lamang. Maaaring magsanhi ang mga ito ng pagkasira o hindi paggana nang maayos ng iyong device at mga application na nandito."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaly (pula-berde)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaly (asul-dilaw)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Pagtatama ng kulay"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Tinutulungan ng color correction ang mga taong colorblind na makakita ng mas tumpak na kulay"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Na-override ng <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Humigit-kumulang <xliff:g id="TIME_REMAINING">%1$s</xliff:g> ang natitira"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Wala nang <xliff:g id="THRESHOLD">%1$s</xliff:g> ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Mahigit <xliff:g id="TIME_REMAINING">%1$s</xliff:g> pa ang natitira"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Malapit nang mag-shut down ang telepono"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Malapit nang mag-shut down ang tablet"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Malapit nang mag-shut down ang device"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Malapit nang mag-shut down ang telepono (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Malapit nang mag-shutdown ang tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Malapit nang mag-shut down ang device (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Baka mag-shut down na ang telepono"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Baka mag-shut down na ang tablet"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Baka mag-shut down na ang device"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Baka mag-shut down na ang telepono (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Baka mag-shut down na ang tablet (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Baka mag-shut down na ang device (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ang natitira bago matapos mag-charge"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> hanggang matapos mag-charge"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Hindi Kilala"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Nagcha-charge"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Mabilis na charge"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Mabagal na charge"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Hindi nagcha-charge"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Nakasaksak, hindi makapag-charge sa ngayon"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Puno"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index b83ffcb..5015e38 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB hata ayıklaması"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB bağlandığında hata ayıklama modu"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB hata ayıklama yetkilerini kaldır"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Kablosuz hata ayıklama"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Kablosuz bağlandığında hata ayıklama modu"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Hata"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Kablosuz hata ayıklama"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Mevcut cihazları görmek ve kullanmak için kablosuz hata ayıklamayı açın"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Cihazı QR kodu ile eşle"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Yeni cihazları QR kodu Tarayıcıyı kullanarak eşleyin"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Eşleme kodu ile cihaz eşleme"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Yeni cihazları altı basamaklı kodu kullanarak eşleyin"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Eşlenen cihazlar"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Şu anda bağlı"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Cihaz ayrıntıları"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Unut"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Cihaz parmak izi: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Bağlantı başarısız oldu"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> cihazının aynı ağa bağlı olduğundan emin olun"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Cihazla eşle"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Kablosuz eşleme kodu"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Eşleme başarısız oldu"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Cihazın aynı ağa bağlı olduğundan emin olun."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR kodu tarayarak kablosuz ağ üzerinden cihaz eşleyin"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Cihaz eşleniyor…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Cihaz eşlenemedi. QR kodu hatalı ya da cihaz aynı ağa bağlı değil."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP adresi ve Bağlantı noktası"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodunu tara"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR kodu tarayarak kablosuz ağ üzerinden cihaz eşleyin"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, hata ayıklama, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Hata raporu kısayolu"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Hata raporu almak için güç menüsünde bir düğme göster"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Uyanık kal"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Mevcutsa, tethering donanım hızlandırıcısını kullan"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB hata ayıklamasına izin verilsin mi?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB hata ayıklaması yalnızca geliştirme amaçlıdır. Verileri bilgisayarınızla cihazınız arasında kopyalamak, bildirim göndermeksizin uygulamaları cihazınıza yüklemek ve günlük verilerini okumak için kullanın."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Kablosuz hata ayıklamaya izin verilsin mi?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Kablosuz hata ayıklama işlevi yalnızca geliştirme amaçlıdır. Verileri bilgisayarınızla cihazınız arasında kopyalamak, bildirim göndermeksizin uygulamaları cihazınıza yüklemek ve günlük verilerini okumak için kullanın."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Daha önce yetki verdiğiniz tüm bilgisayarların USB hata ayıklama erişimini iptal etmek istiyor musunuz?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Geliştirme amaçlı ayarlara izin verilsin mi?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Bu ayarlar yalnızca geliştirme amaçlıdır. Cihazınızın veya cihazdaki uygulamaların bozulmasına veya hatalı çalışmasına neden olabilir."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Kırmızı renk körlüğü (kırmızı-yeşil)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mavi renk körlüğü (mavi-sarı)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Renk düzeltme"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Renk düzeltme, renk körlüğü olan kişilerin daha doğru renkler görmelerine yardımcı olur"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> tarafından geçersiz kılındı"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Yaklaşık <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"En çok <xliff:g id="THRESHOLD">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"En az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"En az <xliff:g id="TIME_REMAINING">%1$s</xliff:g> kaldı"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Tablet kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Cihaz kısa süre içinde kapanabilir"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Tablet kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Cihaz kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Tablet kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Cihaz kısa süre içinde kapanabilir"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon kısa süre içinde kapanabilir(<xliff:g id="LEVEL">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Tablet kısa süre içinde kapanabilir(<xliff:g id="LEVEL">%1$s</xliff:g>"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Cihaz kısa süre içinde kapanabilir (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Şarj olmaya <xliff:g id="TIME">%1$s</xliff:g> kaldı"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - şarj olmaya <xliff:g id="TIME">%2$s</xliff:g> kaldı"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Bilinmiyor"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Şarj oluyor"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Hızlı şarj oluyor"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Yavaş şarj oluyor"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Şarj olmuyor"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Prize takıldı, şu anda şarj olamıyor"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Dolu"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 5fb46f8..3c8f481 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Налагодження USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Вмикати налагодження, коли телефон підключено через USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Скасувати доступ до налагодження USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Бездротове налагодження"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Вмикати режим налагодження, коли пристрій підключено до мережі Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Помилка"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Бездротове налагодження"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Щоб переглядати та використовувати доступні пристрої, увімкніть бездротове налагодження"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Підключати пристрій за допомогою QR-коду"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Підключати нові пристрої за допомогою сканера QR-кодів"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Підключати пристрій за допомогою коду підключення"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Підключати нові пристрої за допомогою шестизначного коду"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Підключені пристрої"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Поточні підключення"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Про пристрій"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Забути"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Відбиток пристрою: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Помилка з\'єднання"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Переконайтеся, що пристрій \"<xliff:g id="DEVICE_NAME">%1$s</xliff:g>\" підключено до правильної мережі"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Підключитися до пристрою"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Код підключення Wi‑Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Помилка підключення"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Переконайтеся, що пристрій підключено до тієї ж мережі."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Підключати пристрій через Wi‑Fi за допомогою QR-коду"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Підключення пристрою…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Не вдалося підключитися до пристрою. Надано неправильний QR-код або пристрій не підключено до тієї ж мережі."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP-адреса та порт"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Сканувати QR-код"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Підключати пристрій через Wi‑Fi за допомогою QR-коду"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, налагодження, розробка"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Ярлик звіту про помилки"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Показувати в меню живлення кнопку створення звіту про помилки"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Залишати активним"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Якщо доступно, вмикати апаратне прискорення під час використання телефона в режимі модема"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Дозвол. налагодж. USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Налагодження USB застосовується лише з метою розробки. Його можна використовувати для копіювання даних між комп’ютером і пристроєм, встановлення програм на вашому пристрої без сповіщення та читання даних журналу."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Дозволити бездротове налагодження?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Бездротове налагодження застосовується лише з метою розробки. Його можна використовувати, щоб копіювати дані між комп\'ютером і пристроєм, встановлювати додатки на пристрої без сповіщення та переглядати дані журналу."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Скасувати доступ до налагодження USB для всіх комп’ютерів, які раніше отримали таке право?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Дозволити налаштування розробки?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Ці налаштування застосовуються лише з метою розробки. Вони можуть спричиняти вихід з ладу або неправильне функціонування вашого пристрою чи програм у ньому."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Протаномалія (червоний – зелений)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Тританомалія (синій – жовтий)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Корекція кольору"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Корекція кольору допомагає людям із дальтонізмом бачити точніші кольори"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Замінено на <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Залишилося приблизно <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Залишилося менше ніж <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Залишилося понад <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Залишилося понад <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Телефон може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Планшет може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Пристрій може невдовзі вимкнутися"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Телефон може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Планшет може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Пристрій може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Телефон може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Планшет може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Пристрій може невдовзі вимкнутися"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Телефон може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Планшет може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Пристрій може невдовзі вимкнутися (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> до повного заряду"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> до повного заряду"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Невідомо"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Заряджається"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Швидке заряджання"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Повільне заряджання"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Не заряджається"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Підключено. Не вдається зарядити"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Акумулятор заряджено"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index c6c10f0..27e5b20 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"‏USB ڈیبگ کرنا"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"‏USB مربوط ہونے پر ڈيبگ کرنے کی وضع"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"‏USB ڈیبگ کرنے کی اجازت دہندگیوں کو منسوخ کریں"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"وائرلیس ڈیبگنگ"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"‏Wi-Fi سے منسلک ہونے پر ڈیبگ موڈ"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"خرابی"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"وائرلیس ڈیبگنگ"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"دستیاب آلات کو دیکھنے اور استعمال کرنے کے لیے، وائرلیس ڈیبگنگ آن کریں"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"‏QR کوڈ کے ذریعے آلہ کا جوڑا بنائیں"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"‏QR کوڈ اسکینر کا استعمال کر کے نئے آلہ کا جوڑا بنائیں"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"جوڑا بنانے کے کوڈ کے ذریعے آلہ کا جوڑا بنائیں"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"چھ ہندسوں کا کوڈ استعمال کر کے نئے آلات کا جوڑا بنائیں"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"جوڑا بنائے گئے آلات"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"فی الحال منسلک ہے"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"آلہ کی تفصیلات"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"بھول جائیں"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"آلہ کا فنگر پرنٹ: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"کنکشن ناکام ہو گیا"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"یقینی بنائیں کہ <xliff:g id="DEVICE_NAME">%1$s</xliff:g> درست نیٹ ورک سے منسلک ہے"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"آلہ کے ساتھ جوڑا بنائیں"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"‏Wi-Fi سے جوڑا بنانے کا کوڈ"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"جوڑا بنانے میں ناکام"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"یقینی بنائیں کہ آلہ اسی نیٹ ورک سے منسلک ہے۔"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"‏QR کوڈ اسکین کر کے Wi-Fi پر آلہ کا جوڑا بنائیں"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"آلہ کا جوڑا بنایا جا رہا ہے…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"‏آلہ کا جوڑا بنانے میں ناکام۔ یا تو QR کوڈ غلط تھا، یا آلہ اسی نیٹ ورک سے منسلک نہیں ہے۔"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"‏IP پتہ اور پورٹ"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"‏QR کوڈ اسکین کریں"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"‏QR کوڈ اسکین کر کے Wi-Fi پر آلہ کا جوڑا بنائیں"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"‏adb، ڈیبگ، dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"بگ رپورٹ کا شارٹ کٹ"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"بگ رپورٹ لینے کیلئے پاور مینو میں ایک بٹن دکھائیں"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"بیدار رکھیں"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"اگر دستیاب ہو تو ٹیدرنگ ہارڈویئر سرعت کاری کا استعمال کریں"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"‏USB ڈیبگ کرنے کی اجازت دیں؟"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"‏USB ڈیبگ کرنا صرف ڈیولپمنٹ کے مقاصد کیلئے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کیلئے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"وائرلیس ڈیبگ کرنے کی اجازت دیں؟"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"وائرلیس ڈیبگ کرنا صرف ڈیولپمنٹ کے مقاصد کے لیے ہے۔ اپنے کمپیوٹر اور اپنے آلہ کے درمیان ڈیٹا کاپی کرنے کے لیے اسے استعمال کریں، بغیر اطلاع کے اپنے آلہ پر ایپس انسٹال کریں اور لاگ ڈیٹا پڑھیں۔"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"‏اپنے ذریعہ پہلے سے اجازت یافتہ سبھی کمپیوٹرز سے USB ڈیبگ کرنے کی رسائی کو کالعدم کریں؟"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"ڈویلپمنٹ ترتیبات کی اجازت دیں؟"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"یہ ترتیبات صرف ڈویلپمنٹ استعمال کے ارادے سے ہیں۔ ان سے آپ کا آلہ اور اس پر موجود ایپلیکیشنز بریک ہو سکتی یا غلط برتاؤ کر سکتی ہیں۔"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"‏Protanomaly (سرخ سبز)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"‏Tritanomaly (نیلا پیلا)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"رنگ کی اصلاح"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"رنگ کی درستگی رنگ نہ دکھائی دینے والے لوگوں کی رنگوں کو مزید درست طریقے سے دیکھنے میں مدد کرتی ہے"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> کے ذریعہ منسوخ کردیا گیا"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"تقریباً <xliff:g id="TIME_REMAINING">%1$s</xliff:g> باقی ہے"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g> سے کم باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g> سے زیادہ باقی ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"فون جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"آلہ جلد ہی بند ہو سکتا ہے"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"فون جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"آلہ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"فون جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"آلہ جلد ہی بند ہو سکتا ہے"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"فون جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"ٹیبلیٹ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"آلہ جلد ہی بند ہو سکتا ہے (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"‎<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>‎"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"چارج ہونے میں <xliff:g id="TIME">%1$s</xliff:g> باقی"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> چارج ہونے تک"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"نامعلوم"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"چارج ہو رہا ہے"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"تیزی سے چارج ہو رہا ہے"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"آہستہ چارج ہو رہا ہے"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"چارج نہیں ہو رہا ہے"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"پلگ ان ہے، ابھی چارج نہیں کر سکتے"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"مکمل"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index 07a6249..ee78795 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB orqali nosozliklarni aniqlash"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"USB orqali kompyuterga ulanganda tuzatish rejimi yoqilsin"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"USB orqali nosozliklarni tuzatishni taqiqlash"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Simsiz nosozliklarni aniqlash"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Wi‑Fi tarmoqqa ulanganda nosozliklarni aniqlash rejimi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Xato"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Simsiz nosozliklarni aniqlash"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Mavjud qurilmalarni koʻrish va ulardan foydalanish uchun simsiz nosozliklarni aniqlash funksiyasini yoqing"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"QR kod yordamida qurilmani ulang"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"QR kod skaneri yordamida yangi qurilmalarni ulash mumkin"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Ulanish kodi yordamida qurilmani ulang"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Olti xonali kod yordamida yangi qurilmalarni ulash mumkin"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Ulangan qurilmalar"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Hozirda ulangan"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Qurilma tafsilotlari"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Olib tashlash"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Qurilmadagi barmoq izi: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Ulanmadi"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"<xliff:g id="DEVICE_NAME">%1$s</xliff:g> kerakli tarmoqqa ulanganini tekshiring"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Qurilma bilan ulanish"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi ulanish kodi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Ulanmadi"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Qurilma bir xil tarmoqqa ulanganini tekshiring."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"QR kodni skanerlab, Wi-Fi orqali qurilmani ulang"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Qurilma ulanmoqda…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Qurilma ulanmadi. QR kod xato yoki qurilma bir xil tarmoqqa ulanmagan."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP manzil va port"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"QR kodni skanerlash"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"QR kodni skanerlab, Wi-Fi orqali qurilmani ulang"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, debag, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Xatoliklar hisoboti"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Menyuda xatoliklar hisobotini yuborish tugmasi ko‘rsatilsin"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Ekranning yoniq turishi"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Modem rejimida apparatli tezlashtirishdan foydalanish (agar mavjud bo‘lsa)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"USB orqali nosozliklarni tuzatishga ruxsat berilsinmi?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB orqali nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter o‘rtasida ko‘chirish, ilovalarni xabarnomasiz o‘rnatish va jurnal maʼlumotlarini o‘qish uchun foydalaniladi."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Simsiz nosozliklarni aniqlashga ruxsat berilsinmi?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Simsiz nosozliklarni aniqlash faqat dasturlash maqsadlarida yoqiladi. Undan maʼlumotlarni qurilmangiz va kompyuter oʻrtasida koʻchirish, ilovalarni bildirishnomasiz oʻrnatish va jurnal maʼlumotlarini oʻqish uchun foydalaniladi."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"USB orqali nosozliklarni tuzatishga berilgan ruxsat siz hisobingizga kirgan barcha kompyuterlar uchun bekor qilinsinmi?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Dasturlash sozlamalariga ruxsat berilsinmi?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Bu sozlamalar faqat dasturlash maqsadlariga mo‘ljallangan. Shuning uchun, ular qurilmangizga va undagi ilovalariga shikast yetkazib, noto‘g‘ri ishlashiga sabab bo‘lishi mumkin."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Protanomaliya (qizil/yashil)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Tritanomaliya (ko‘k/sariq)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Rangni tuzatish"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Ranglarni sozlash ranglarni farqlashda muammosi bor insonlarga (masalan, daltoniklarga) aniq koʻrishda yordam beradi"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"<xliff:g id="TITLE">%1$s</xliff:g> bilan almashtirildi"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> – <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Taxminan <xliff:g id="TIME_REMAINING">%1$s</xliff:g> qoldi"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"<xliff:g id="THRESHOLD">%1$s</xliff:g>dan kamroq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"<xliff:g id="TIME_REMAINING">%1$s</xliff:g>dan ko‘proq vaqt qoldi"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Telefon tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Planshet tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Qurilma tez orada o‘chib qolishi mumkin"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Telefon tez orada o‘chib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Planshet tez orada o‘chib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Qurilma tez orada o‘chib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Telefon tez orada oʻchib qolishi mumkin"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Planshet tez orada oʻchib qolishi mumkin"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Qurilma tez orada oʻchib qolishi mumkin"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Telefon tez orada oʻchib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Planshet tez orada oʻchib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Qurilma tez orada oʻchib qolishi mumkin (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> ichida toʻliq quvvat oladi"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> ichida toʻliq quvvat oladi"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Noma’lum"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Quvvat olmoqda"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Tezkor quvvat olmoqda"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Sekin quvvat olmoqda"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Quvvat olmayapti"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Ulangan, lekin quvvat olmayapti"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"To‘la"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 7e3944c..6d76962 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Gỡ lỗi qua USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Bật chế độ gỡ lỗi khi kết nối USB"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Thu hồi ủy quyền gỡ lỗi USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Gỡ lỗi không dây"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Chế độ gỡ lỗi khi có kết nối Wi-Fi"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Lỗi"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Gỡ lỗi không dây"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Để xem và sử dụng các thiết bị có sẵn, hãy bật tính năng gỡ lỗi không dây"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Ghép nối thiết bị bằng mã QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Ghép nối các thiết bị mới bằng Trình quét mã QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Ghép nối thiết bị bằng mã ghép nối"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Ghép nối các thiết bị mới bằng mã gồm 6 chữ số"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Thiết bị được ghép nối"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Hiện đang kết nối"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Thông tin chi tiết về thiết bị"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Xóa"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Vân tay trên thiết bị: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Kết nối không thành công"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Đảm bảo bạn kết nối <xliff:g id="DEVICE_NAME">%1$s</xliff:g> với đúng mạng"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Ghép nối với thiết bị"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Mã ghép nối Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Ghép nối không thành công"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Đảm bảo bạn kết nối thiết bị với cùng một mạng."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Ghép nối thiết bị qua Wi-Fi bằng cách quét mã QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Đang ghép nối thiết bị…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Không ghép nối được thiết bị. Mã QR không chính xác hoặc bạn không kết nối thiết bị với cùng một mạng."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Địa chỉ IP và cổng"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Quét mã QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Ghép nối thiết bị qua Wi-Fi bằng cách quét mã QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, gỡ lỗi, nhà phát triển"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Phím tắt báo cáo lỗi"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Hiển thị một nút trong menu nguồn để báo cáo lỗi"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Không khóa màn hình"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Sử dụng tính năng tăng tốc phần cứng khi chia sẻ kết nối nếu có"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Cho phép gỡ lỗi qua USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Gỡ lỗi USB chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị của bạn mà không thông báo và đọc dữ liệu nhật ký."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Bật tính năng gỡ lỗi không dây?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Tính năng gỡ lỗi không dây chỉ dành cho mục đích phát triển. Hãy sử dụng tính năng này để sao chép dữ liệu giữa máy tính và thiết bị của bạn, cài đặt ứng dụng trên thiết bị mà không thông báo và đọc dữ liệu nhật ký."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Thu hồi quyền truy cập gỡ lỗi USB từ tất cả máy tính mà bạn đã ủy quyền trước đó?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Cho phép cài đặt phát triển?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Những cài đặt này chỉ dành cho mục đích phát triển. Chúng có thể làm cho thiết bị và ứng dụng trên thiết bị của bạn bị lỗi và hoạt động sai."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"Mù màu đỏ không hoàn toàn (đỏ-xanh lục)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"Mù màu (xanh lam-vàng)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Sửa màu"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Tính năng hiệu chỉnh màu sắc giúp những người bị mù màu thấy màu sắc chính xác hơn"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Bị ghi đè bởi <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Còn khoảng <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Còn lại không đến <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Còn lại hơn <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Điện thoại có thể sắp tắt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Máy tính bảng có thể sắp tắt"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Thiết bị có thể sắp tắt"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Điện thoại có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Máy tính bảng có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Thiết bị có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Điện thoại có thể sắp tắt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Máy tính bảng có thể sắp tắt"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Thiết bị có thể sắp tắt"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Điện thoại có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Máy tính bảng có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Thiết bị có thể sắp tắt (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"Còn <xliff:g id="TIME">%1$s</xliff:g> nữa là sạc xong"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> – <xliff:g id="TIME">%2$s</xliff:g> nữa là sạc xong"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Không xác định"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Đang sạc"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Đang sạc nhanh"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Đang sạc chậm"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Hiện không sạc"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Đã cắm nhưng không thể sạc ngay"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Đầy"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index 3edbb4d..fbb30ca 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB 调试"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"连接 USB 后启用调试模式"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"撤消 USB 调试授权"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"无线调试"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"连接到 WLAN 后启用调试模式"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"错误"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"无线调试"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"要查看和使用可用的设备,请开启无线调试"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用二维码配对设备"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"使用二维码扫描器配对新设备"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配对码配对设备"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位数验证码配对新设备"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"已配对的设备"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"当前已连接"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"设备详细信息"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"取消保存"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"设备指纹:<xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"连接失败"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"确保<xliff:g id="DEVICE_NAME">%1$s</xliff:g>已连接到正确的网络"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"与设备配对"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"WLAN 配对码"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"配对失败"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"确保设备已连接到同一网络。"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"扫描二维码即可通过 WLAN 配对设备"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"正在配对设备…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"无法配对设备。可能是因为二维码不正确,或者设备未连接到同一网络。"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 地址和端口"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"扫描二维码"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"扫描二维码即可通过 WLAN 配对设备"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"adb, 调试, debug, 开发, dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"错误报告快捷方式"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"在电源菜单中显示用于提交错误报告的按钮"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"不锁定屏幕"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"使用网络共享硬件加速功能(如果可用)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"是否允许 USB 调试?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB 调试仅用于开发目的。该功能可用于在您的计算机和设备之间复制数据、在您的设备上安装应用(事先不发通知)以及读取日志数据。"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"要允许无线调试吗?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"无线调试仅用于开发目的。该功能可用于在您的计算机和设备之间复制数据、在您的设备上安装应用(事先不发通知)以及读取日志数据。"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"是否针对您之前授权的所有计算机撤消 USB 调试的访问权限?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"允许开发设置?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"这些设置仅适用于开发工作。一旦启用,会导致您的设备以及设备上的应用崩溃或出现异常。"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"红色弱视(红绿不分)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"蓝色弱视(蓝黄不分)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"颜色校正功能有助于色盲用户看到更准确的颜色"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已被“<xliff:g id="TITLE">%1$s</xliff:g>”覆盖"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"大约还可使用 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"电量剩余使用时间不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"电量剩余使用时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"电量剩余使用时间超过 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"手机可能即将关机"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"平板电脑可能即将关机"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"设备可能即将关机"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"手机可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"平板电脑可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"设备可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"手机可能即将关机"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"平板电脑可能即将关机"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"设备可能即将关机"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"手机可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"平板电脑可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"设备可能即将关机 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"还剩 <xliff:g id="TIME">%1$s</xliff:g>充满电"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>后充满电"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"正在充电"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充电"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充电"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"未在充电"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"已插入电源,但是现在无法充电"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"电量充足"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index 6174fe9..0b4ee7a 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB 偵錯"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"連接 USB 時進入偵錯模式"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"撤銷 USB 偵錯授權"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"無線偵錯"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"連線至 Wi-Fi 時啟用偵錯模式"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用二維條碼配對裝置"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"使用二維條碼掃瞄器配對新裝置"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"已配對的裝置"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"目前已連接的裝置"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"裝置詳情"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"移除裝置"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"裝置指紋:<xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"連線失敗"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"請確認<xliff:g id="DEVICE_NAME">%1$s</xliff:g> 已連線至相同的網絡。"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"與裝置配對"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi-Fi 配對碼"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"配對失敗"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"請確認裝置已連線至相同的網絡。"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"掃瞄二維條碼即可透過 Wi-Fi 配對裝置"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"正在配對裝置…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"無法配對裝置,可能是二維條碼錯誤,或裝置未連線至相同的網絡。"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 位址和連接埠"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"掃瞄二維條碼"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"掃瞄二維條碼即可透過 Wi-Fi 配對裝置"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, 偵錯, 開發"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"錯誤舉報捷徑"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"在電源選單中顯示提交錯誤舉報的按鈕"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"保持啟用"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"使用網絡共享硬件加速功能 (如果可用)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"允許 USB 偵錯嗎?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB 偵錯是針對應用程式開發而設計的功能,可讓您在電腦與裝置間複製資料、不用通知即可在裝置上安裝應用程式,以及讀取記錄資料。"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"要啟用無線偵錯嗎?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"無線偵錯僅適用於開發用途,可讓您在電腦和裝置之間複製資料、為裝置安裝應用程式而不提出通知,以及讀取記錄資料。"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"要針對先前授權的所有電腦撤銷 USB 偵錯存取權嗎?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"允許開發設定?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"這些設定僅供開發用途,可能會導致您的裝置及應用程式損毀或運作不正常。"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅綠)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍黃)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"色彩校正可以協助色盲人士睇到更加準確嘅顏色"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已由「<xliff:g id="TITLE">%1$s</xliff:g>」覆寫"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"還有大約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"還有少於 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"還有超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"還有超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"手機可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"裝置可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"手機可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"手機可能即將關閉"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"裝置可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"手機可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"還需 <xliff:g id="TIME">%1$s</xliff:g>才能充滿電"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - 還需 <xliff:g id="TIME">%2$s</xliff:g>才能充滿電"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"未知"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"正在快速充電"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"正在慢速充電"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"已插入電源插座,但目前無法充電"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"電量已滿"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index a150d16..487c33d 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"USB 偵錯"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"連接 USB 時進入偵錯模式"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"撤銷 USB 偵錯授權"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"無線偵錯"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"連上 Wi-Fi 時啟用偵錯模式"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"錯誤"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"無線偵錯"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"如要查看並使用可用的裝置,請開啟無線偵錯"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"使用 QR 圖碼配對裝置"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"使用 QR 圖碼掃描器配對新裝置"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"使用配對碼配對裝置"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"使用六位數的配對碼配對新裝置"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"已配對的裝置"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"目前已連線的裝置"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"裝置詳細資料"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"移除裝置"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"裝置指紋:<xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"連線失敗"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"請確認「<xliff:g id="DEVICE_NAME">%1$s</xliff:g>」已連上正確的網路"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"與裝置配對"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Wi‑Fi 配對碼"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"配對失敗"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"請確認裝置已連上相同的網路。"</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"掃描 QR 圖碼即可透過 Wi-Fi 配對裝置"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"正在配對裝置…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"無法配對裝置。可能是QR 圖碼錯誤,或是裝置未連上相同的網路。"</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"IP 位址和通訊埠"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"掃描 QR 圖碼"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"掃描 QR 圖碼即可透過 Wi-Fi 配對裝置"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"ADB, 偵錯, 開發"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"錯誤回報捷徑"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"在電源選單中顯示取得錯誤報告的按鈕"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"螢幕不休眠"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"使用數據連線硬體加速功能 (如果可用的話)"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"允許 USB 偵錯嗎?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"USB 偵錯是針對應用程式開發而設計的功能,可讓你複製電腦和裝置中的資料、不需經由通知即可在裝置上安裝應用程式,以及讀取記錄資料。"</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"要啟用無線偵錯嗎?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"無線偵錯是針對應用程式開發而設計的功能,可讓你複製電腦和裝置中的資料、不必經由通知即可在裝置上安裝應用程式,以及讀取記錄資料。"</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"要針對先前授權的所有電腦撤銷 USB 偵錯權限嗎?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"允許開發設定?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"這些設定僅供開發之用,可能導致你的裝置及裝置中的應用程式毀損或運作異常。"</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"紅色弱視 (紅-綠)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"藍色弱視 (藍-黃)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"色彩校正"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"色彩校正可協助色盲使用者看見較準確的色彩"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"已改為<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"還能使用約 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"電池可用時間不到 <xliff:g id="THRESHOLD">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g> (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"電池可用時間超過 <xliff:g id="TIME_REMAINING">%1$s</xliff:g>"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"手機可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"平板電腦可能即將關機"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"裝置可能即將關機"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"手機可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"手機可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"平板電腦可能即將關機"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"裝置可能即將關機"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"手機可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"平板電腦可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"裝置可能即將關機 (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g>後充飽電"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g>後充飽電"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"不明"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"充電中"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"快速充電中"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"慢速充電中"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"非充電中"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"已接上電源,但現在無法充電"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"電力充足"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 003dda3..684c100 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -206,6 +206,33 @@
     <string name="enable_adb" msgid="8072776357237289039">"Ukulungisa iphutha le-USB"</string>
     <string name="enable_adb_summary" msgid="3711526030096574316">"Lungisa iphutha lemodi lapho i-USB ixhunyiwe"</string>
     <string name="clear_adb_keys" msgid="3010148733140369917">"Buyisa ukugunyaza kokususa iphutha le-USB"</string>
+    <string name="enable_adb_wireless" msgid="6973226350963971018">"Ukulungisa amaphutha okungenantambo"</string>
+    <string name="enable_adb_wireless_summary" msgid="7344391423657093011">"Imodi yokususa iphutha lapho i-Wi-Fi ixhunyiwe"</string>
+    <string name="adb_wireless_error" msgid="721958772149779856">"Iphutha"</string>
+    <string name="adb_wireless_settings" msgid="2295017847215680229">"Ukulungisa amaphutha okungenantambo"</string>
+    <string name="adb_wireless_list_empty_off" msgid="1713707973837255490">"Ukubona futhi usebenzise amadivayisi atholakalayo, vula ukulungisa amaphutha okungenantambo"</string>
+    <string name="adb_pair_method_qrcode_title" msgid="6982904096137468634">"Bhangqa idivayisi ngekhodi ye-QR"</string>
+    <string name="adb_pair_method_qrcode_summary" msgid="3729901496856458634">"Bhangqa amadivayisi amasha usebenzisa iskena sekhodi ye-QR"</string>
+    <string name="adb_pair_method_code_title" msgid="1122590300445142904">"Bhangqa idivayisi ngekhodi yokumatanisa"</string>
+    <string name="adb_pair_method_code_summary" msgid="6370414511333685185">"Bhangqa amadivayisi amasha usebenzisa ikhodi yamadijithi ayisithupha"</string>
+    <string name="adb_paired_devices_title" msgid="5268997341526217362">"Amadivaysi abhangqene"</string>
+    <string name="adb_wireless_device_connected_summary" msgid="3039660790249148713">"Kuxhunyiwe manje"</string>
+    <string name="adb_wireless_device_details_title" msgid="7129369670526565786">"Imininingwane yedivayisi"</string>
+    <string name="adb_device_forget" msgid="193072400783068417">"Khohlwa"</string>
+    <string name="adb_device_fingerprint_title_format" msgid="291504822917843701">"Izigxivizo zeminwe zedivayisi: <xliff:g id="FINGERPRINT_PARAM">%1$s</xliff:g>"</string>
+    <string name="adb_wireless_connection_failed_title" msgid="664211177427438438">"Ukuxhuma akuphumelelanga"</string>
+    <string name="adb_wireless_connection_failed_message" msgid="9213896700171602073">"Qiniseka ukuthi i-<xliff:g id="DEVICE_NAME">%1$s</xliff:g>ixhunywe kunethiwekhi efanele"</string>
+    <string name="adb_pairing_device_dialog_title" msgid="7141739231018530210">"Bhangqa nedivayisi"</string>
+    <string name="adb_pairing_device_dialog_pairing_code_label" msgid="3639239786669722731">"Ikhodi yokubhangqa ye-Wi-Fi"</string>
+    <string name="adb_pairing_device_dialog_failed_title" msgid="3426758947882091735">"Ukubhangqa akuphumelelanga"</string>
+    <string name="adb_pairing_device_dialog_failed_msg" msgid="6611097519661997148">"Qiniseka ukuthi idivayisi ixhunywe kunethiwekhi efanayo."</string>
+    <string name="adb_wireless_qrcode_summary" msgid="8051414549011801917">"Bhangqa idivayisi nge-Wi‑Fi ngokuskena ikhodi ye-QR"</string>
+    <string name="adb_wireless_verifying_qrcode_text" msgid="6123192424916029207">"Ibhangqa idivayisi…"</string>
+    <string name="adb_qrcode_pairing_device_failed_msg" msgid="6936292092592914132">"Yehlulekile ukubhangqa idivayisi. Kungenzeka ukuthi ikhodi ye-QR kade ingalungile, noma idivayisi ayixhunyiwe kunethiwekhi efanayo."</string>
+    <string name="adb_wireless_ip_addr_preference_title" msgid="8335132107715311730">"Ikheli le-IP nembobo"</string>
+    <string name="adb_wireless_qrcode_pairing_title" msgid="1906409667944674707">"Skena ikhodi ye-QR"</string>
+    <string name="adb_wireless_qrcode_pairing_description" msgid="8578868049289910131">"Bhangqa idivayisi nge-Wi‑Fi ngokuskena ikhodi ye-QR"</string>
+    <string name="keywords_adb_wireless" msgid="6507505581882171240">"i-adb, ukulungisa amaphutha, i-dev"</string>
     <string name="bugreport_in_power" msgid="8664089072534638709">"Isinqamuleli sombiko wesiphazamisi"</string>
     <string name="bugreport_in_power_summary" msgid="1885529649381831775">"Bonisa inkinobho kwimenyu yamandla ngokuthatha umbiko wesiphazamiso"</string>
     <string name="keep_screen_on" msgid="1187161672348797558">"Hlala uphapheme"</string>
@@ -271,6 +298,8 @@
     <string name="tethering_hardware_offload_summary" msgid="7801345335142803029">"Sebenzisa i-tethering hardware acceleration uma itholakala"</string>
     <string name="adb_warning_title" msgid="7708653449506485728">"Vumela ukulungisa iphutha le-USB?"</string>
     <string name="adb_warning_message" msgid="8145270656419669221">"Ukulungisa iphutha le-USB kuhloselwe izinjongo zokuthuthukisa kuphela. Ingasebenziselwa ukukopisha idatha phakathi kwekhompyutha yakho nedivaysi yakho, faka izinhlelo zokusebenza kwidivaysi yakho ngaphandle kwesaziso, bese ufunda idatha yefayela lokungena."</string>
+    <string name="adbwifi_warning_title" msgid="727104571653031865">"Vumela ukulungisa amaphutha okungenantambo?"</string>
+    <string name="adbwifi_warning_message" msgid="8005936574322702388">"Ukulungisa iphutha okungenantambo kuhloselwe izinjongo zokuthuthukisa kuphela. Kusebenzisele ukukopisha idatha phakathi kwekhompuyutha yakho nedivaysi yakho, faka izinhlelo zokusebenza kwidivaysi yakho ngaphandle kwesaziso, bese ufunda idatha yelogu."</string>
     <string name="adb_keys_warning_message" msgid="2968555274488101220">"Buyisa ukufinyelela ekususeni iphutha le-USB kusuka kuwo wonke amakhompyutha owagunyaze ngaphambilini?"</string>
     <string name="dev_settings_warning_title" msgid="8251234890169074553">"Vumele izilungiselelo zokuthuthukisa?"</string>
     <string name="dev_settings_warning_message" msgid="37741686486073668">"Lezi zilungiselelo zenzelwe ukusetshenziswa ukuthuthukisa kuphela. Zingadala ukuthi idivayisi yakho kanye nensiza ekuyona ukuthi iphuke noma iziphathe kabi."</string>
@@ -383,8 +412,7 @@
     <string name="daltonizer_mode_protanomaly" msgid="7805583306666608440">"I-Protanomaly (bomvu-luhlaza)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="7135266249220732267">"I-Tritanomaly (luhlaza okwesibhakabhaka-phuzi)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="1810693571332381974">"Ukulungiswa kombala"</string>
-    <!-- no translation found for accessibility_display_daltonizer_preference_subtitle (6178138727195403796) -->
-    <skip />
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="6178138727195403796">"Ukulungisa umbala kusiza abantu abangaboni imibala bobone imibala enembe kakhulu"</string>
     <string name="daltonizer_type_overridden" msgid="4509604753672535721">"Igitshezwe ngaphezulu yi-<xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_settings_home_page" msgid="4885165789445462557">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> - <xliff:g id="TIME_STRING">%2$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="8264199158671531431">"Cishe u-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele"</string>
@@ -403,21 +431,19 @@
     <string name="power_remaining_less_than_duration" msgid="1812668275239801236">"Ngaphansi kuka-<xliff:g id="THRESHOLD">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_more_than_subtext" msgid="7919119719242734848">"Ngaphezu kuka-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> osele (<xliff:g id="LEVEL">%2$s</xliff:g>)"</string>
     <string name="power_remaining_only_more_than_subtext" msgid="3274496164769110480">"Ngaphezulu kokungu-<xliff:g id="TIME_REMAINING">%1$s</xliff:g> okusele"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="6583866940347159957">"Ifoni ingacisha maduze"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="8009177999719462724">"Ithebulethi ingacisha maduze"</string>
-    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="8320892540455268018">"Idivayisi ingacisha maduze"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="6186572170809116621">"Ifoni ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="1338758278145563121">"Ithebhulethi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
-    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="3699579688084774362">"Idivayisi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="default" msgid="137330009791560774">"Ifoni ingacisha maduze"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="tablet" msgid="145489081521468132">"Ithebulethi ingacisha maduze"</string>
+    <string name="power_remaining_duration_only_shutdown_imminent" product="device" msgid="1070562682853942350">"Idivayisi ingacisha maduze"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="default" msgid="4429259621177089719">"Ifoni ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="tablet" msgid="7703677921000858479">"Ithebulethi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
+    <string name="power_remaining_duration_shutdown_imminent" product="device" msgid="4374784375644214578">"Idivayisi ingacisha maduze (<xliff:g id="LEVEL">%1$s</xliff:g>)"</string>
     <string name="power_charging" msgid="6727132649743436802">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="STATE">%2$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="7415639699283965818">"<xliff:g id="TIME">%1$s</xliff:g> esele ize ishaje"</string>
     <string name="power_charging_duration" msgid="5005740040558984057">"<xliff:g id="LEVEL">%1$s</xliff:g> - <xliff:g id="TIME">%2$s</xliff:g> ize igcwale"</string>
     <string name="battery_info_status_unknown" msgid="268625384868401114">"Akwaziwa"</string>
     <string name="battery_info_status_charging" msgid="4279958015430387405">"Iyashaja"</string>
-    <!-- no translation found for battery_info_status_charging_fast (8027559755902954885) -->
-    <skip />
-    <!-- no translation found for battery_info_status_charging_slow (3190803837168962319) -->
-    <skip />
+    <string name="battery_info_status_charging_fast" msgid="8027559755902954885">"Ishaja ngokushesha"</string>
+    <string name="battery_info_status_charging_slow" msgid="3190803837168962319">"Ishaja kancane"</string>
     <string name="battery_info_status_discharging" msgid="6962689305413556485">"Ayishaji"</string>
     <string name="battery_info_status_not_charging" msgid="8330015078868707899">"Kuxhunyiwe, ayikwazi ukushaja khona manje"</string>
     <string name="battery_info_status_full" msgid="4443168946046847468">"Kugcwele"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 59881e7..d25e3e2 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -886,6 +886,11 @@
     <!-- UI debug setting: enable gpu debug layers summary [CHAR LIMIT=50] -->
     <string name="enable_gpu_debug_layers_summary">Allow loading GPU debug layers for debug apps</string>
 
+    <!-- UI debug setting: enable verbose vendor logging [CHAR LIMIT=30] -->
+    <string name="enable_verbose_vendor_logging">Enable verbose vendor logging</string>
+    <!-- UI debug setting: enable verbose vendor logging summary [CHAR LIMIT=100] -->
+    <string name="enable_verbose_vendor_logging_summary">Allow additional vendor logs to be included in bug reports, may contain private information</string>
+
     <!-- UI debug setting: scaling factor for window animations [CHAR LIMIT=25] -->
     <string name="window_animation_scale_title">Window animation scale</string>
 
@@ -1260,9 +1265,12 @@
     <!-- The notice header of Third-party licenses. not translatable -->
     <string name="notice_header" translatable="false"></string>
 
-    <!-- Name of the this device. [CHAR LIMIT=30] -->
-    <string name="media_transfer_this_device_name">This device</string>
+    <!-- Name of the phone device. [CHAR LIMIT=30] -->
+    <string name="media_transfer_this_device_name">Phone speaker</string>
 
     <!-- Warning message to tell user is have problem during profile connect, it need to turn off device and back on. [CHAR_LIMIT=NONE] -->
     <string name="profile_connect_timeout_subtext">Problem connecting. Turn device off &amp; back on</string>
+
+    <!-- Name of the 3.5mm audio device. [CHAR LIMIT=40] -->
+    <string name="media_transfer_wired_device_name">Wired audio device</string>
 </resources>
diff --git a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
index e0ca1ab..a38091d 100644
--- a/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/display/DisplayDensityUtils.java
@@ -97,7 +97,7 @@
 
         final Resources res = context.getResources();
         final DisplayMetrics metrics = new DisplayMetrics();
-        context.getDisplay().getRealMetrics(metrics);
+        context.getDisplayNoVerify().getRealMetrics(metrics);
 
         final int currentDensity = metrics.densityDpi;
         int currentDensityIndex = -1;
diff --git a/packages/SettingsProvider/res/values-af/strings.xml b/packages/SettingsProvider/res/values-af/strings.xml
index 8c2f8b3..24efbb6 100644
--- a/packages/SettingsProvider/res/values-af/strings.xml
+++ b/packages/SettingsProvider/res/values-af/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Instellingsberging"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Veranderings aan jou warmkolinstellings"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Jou warmkolband het verander."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Hierdie toestel steun nie jou voorkeur vir net 5 GHz nie. Hierdie toestel sal pleks daarvan die 5 GHz-band gebruik wanneer dit beskikbaar is."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Warmkolinstellings het verander"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tik om besonderhede te sien"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-am/strings.xml b/packages/SettingsProvider/res/values-am/strings.xml
index 640301a..48fb705 100644
--- a/packages/SettingsProvider/res/values-am/strings.xml
+++ b/packages/SettingsProvider/res/values-am/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"የቅንብሮች ማከማቻ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"በእርስዎ ሆትስፖት ቅንብሮች ላይ ለውጦች"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"የእርስዎ ሆትስፖት ባንድ ተለውጧል።"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ይህ መሣሪያ የእርስዎን ምርጫ ለ5GHz ብቻ አይደግፍም። በምትኩ፣ ይህ መሣሪያ ሲገኝ 5GHz ባንድ ይጠቀማል።"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"የመገናኛ ነጥብ ቅንብሮች ተለውጠዋል"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ዝርዝሮችን ለማየት መታ ያድርጉ"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ar/strings.xml b/packages/SettingsProvider/res/values-ar/strings.xml
index 2675839..6371f2c 100644
--- a/packages/SettingsProvider/res/values-ar/strings.xml
+++ b/packages/SettingsProvider/res/values-ar/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"تخزين الإعدادات"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"التغييرات التي طرأت على إعدادات نقطة الاتصال"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"تمّ تغيير نطاق نقطة الاتصال الخاصة بك."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"لا يتوافق هذا الجهاز مع إعدادك المفضّل الخاص باستخدام النطاق 5 غيغاهرتز فقط. وسيستخدم الجهاز بدلاً من ذلك النطاق 5 غيغاهرتز عندما يكون متاحًا."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"تم تغيير إعدادات نقطة الاتصال."</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"انقر للاطّلاع على التفاصيل."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-as/strings.xml b/packages/SettingsProvider/res/values-as/strings.xml
index b70146a..5235e3c 100644
--- a/packages/SettingsProvider/res/values-as/strings.xml
+++ b/packages/SettingsProvider/res/values-as/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ছেটিংছসমূহৰ সঞ্চয়াগাৰ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"আপোনাৰ হটস্পট ছেটিংসমূহত হোৱা সালসলনিসমূহ"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"আপোনাৰ হটস্পটৰ বেণ্ড সলনি কৰা হৈছে।"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"আপোনাৰ কেৱল ৫ গিগাহাৰ্টজৰ প্ৰতি অগ্ৰাধিকাৰ এই ডিভাচইচটোৱে সমৰ্থন নকৰে। ইয়াৰ পৰিৱৰ্তে, ডিভাচইচটোৱে যেতিয়া ৫ গিগাহাৰ্টজ বেণ্ড উপলব্ধ হ’ব তেতিয়া তাক ব্যৱহাৰ কৰিব।"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-az/strings.xml b/packages/SettingsProvider/res/values-az/strings.xml
index 8b4f75b..b0e8642 100644
--- a/packages/SettingsProvider/res/values-az/strings.xml
+++ b/packages/SettingsProvider/res/values-az/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot ayarlarınızda dəyişiklik"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot diapazonu dəyişib."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Bu cihaz yalnız 5GHz üçün tərcihinizi dəstəkləmir. Əvəzində, əlçatan olduqda bu cihaz 5GHz diapazonundan istifadə edəcək."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot ayarları dəyişib"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Detalları görmək üçün toxunun"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
index 9c3a00e..def4b68 100644
--- a/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsProvider/res/values-b+sr+Latn/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Podešavanja skladišta"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promene podešavanja za hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Opseg hotspota je promenjen."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava podešavanje samo za 5 GHz. Uređaj će koristiti opseg od 5 GHz kada bude dostupan."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Podešavanja hotspota su promenjena"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da biste videli detalje"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-be/strings.xml b/packages/SettingsProvider/res/values-be/strings.xml
index 0e098e7..709178e 100644
--- a/packages/SettingsProvider/res/values-be/strings.xml
+++ b/packages/SettingsProvider/res/values-be/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Сховішча налад"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Змяненні ў наладах хот-спота"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Частата хот-спота змянілася."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Прылада не можа працаваць толькі на частаце 5 ГГц. Гэта частата будзе выкарыстоўвацца, калі гэта магчыма."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Налады хот-спота змяніліся"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Дакраніцеся, каб убачыць падрабязныя звесткі"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-bg/strings.xml b/packages/SettingsProvider/res/values-bg/strings.xml
index 30526f2..b2eae73 100644
--- a/packages/SettingsProvider/res/values-bg/strings.xml
+++ b/packages/SettingsProvider/res/values-bg/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Настройки за хранилище"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промени в настройките ви за точка за достъп"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Честотната лента на точката ви за достъп е променена."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Това устройство не поддържа предпочитанието ви за използване само на честотната лента от 5 ГХц. Вместо това то ще я ползва, когато е възможно."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Настройките за точката за достъп са променени"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Докоснете, за да видите подробности"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-bn/strings.xml b/packages/SettingsProvider/res/values-bn/strings.xml
index 8fc6bbb..c785cd8 100644
--- a/packages/SettingsProvider/res/values-bn/strings.xml
+++ b/packages/SettingsProvider/res/values-bn/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"সেটিংস স্টোরেজ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"আপনার হটস্পট সেটিংসে করা পরিবর্তনগুলি"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"আপনার হটস্পট ব্যান্ড পরিবর্তন করা হয়েছে।"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"এই ডিভাইসটি শুধুমাত্র 5GHz এর জন্য আপনার পছন্দ সমর্থন করে না। পরিবর্তে, এই ডিভাইসটি 5GHz ব্যান্ড ব্যবহার করবে।"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-bs/strings.xml b/packages/SettingsProvider/res/values-bs/strings.xml
index ddacb32..506fea2 100644
--- a/packages/SettingsProvider/res/values-bs/strings.xml
+++ b/packages/SettingsProvider/res/values-bs/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Postavke za pohranu podataka"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promjene postavki pristupne tačke"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Opseg pristupne tačke je promijenjen."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava vašu postavku za mreže od isključivo 5 GHz. Uređaj će koristiti opseg of 5 GHz kada bude dostupan."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Postavke pristupne tačke su promijenjene"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da vidite detalje"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ca/strings.xml b/packages/SettingsProvider/res/values-ca/strings.xml
index 0c2ad73..58d3572e 100644
--- a/packages/SettingsProvider/res/values-ca/strings.xml
+++ b/packages/SettingsProvider/res/values-ca/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Configuració de l\'emmagatzematge"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Canvis en la configuració del punt d\'accés Wi‑Fi"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ha canviat la teva banda del punt d\'accés Wi‑Fi."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Aquest dispositiu no admet utilitzar exclusivament una banda de 5 GHz. El dispositiu utilitzarà una banda de 5 GHz quan estigui disponible."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"La configuració del punt d\'accés Wi‑Fi ha canviat"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toca per veure\'n els detalls"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-cs/strings.xml b/packages/SettingsProvider/res/values-cs/strings.xml
index ab474b1..449c632 100644
--- a/packages/SettingsProvider/res/values-cs/strings.xml
+++ b/packages/SettingsProvider/res/values-cs/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Paměť pro nastavení"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Změny nastavení hotspotu"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pásmo hotspotu se změnilo."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Toto zařízení nepodporuje vaše nastavení jen 5GHz pásma. Zařízení použije pásmo 5 GHz, jen když bude dostupné."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavení hotspotu se změnilo"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Klepnutím zobrazíte podrobnosti"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-da/strings.xml b/packages/SettingsProvider/res/values-da/strings.xml
index 719614c..278d978 100644
--- a/packages/SettingsProvider/res/values-da/strings.xml
+++ b/packages/SettingsProvider/res/values-da/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring af indstillinger"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ændringer af dine indstillinger for hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Dit hotspotbånd er ændret."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Denne enhed understøtter ikke din præference om kun 5 GHz. Denne enhed vil i stedet bruge 5 GHz-båndet, når det er muligt."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Indstillingerne for hotspots har ændret sig"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tryk for at se flere oplysninger"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-de/strings.xml b/packages/SettingsProvider/res/values-de/strings.xml
index 6e253e0..a469936 100644
--- a/packages/SettingsProvider/res/values-de/strings.xml
+++ b/packages/SettingsProvider/res/values-de/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Einstellungsspeicher"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Änderungen an deinen Hotspot-Einstellungen"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Dein Hotspot-Band hat sich geändert."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dieses Gerät unterstützt die ausschließliche Nutzung von 5 GHz nicht. Es greift aber immer auf das 5-GHz-Band zurück, wenn dieses verfügbar ist."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-el/strings.xml b/packages/SettingsProvider/res/values-el/strings.xml
index c47fea2..1bfbf27 100644
--- a/packages/SettingsProvider/res/values-el/strings.xml
+++ b/packages/SettingsProvider/res/values-el/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Αποθηκευτικός χώρος ρυθμίσεων"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Αλλαγές στις ρυθμίσεις σημείου πρόσβασης Wi-Fi"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Το εύρος σημείου πρόσβασης Wi-Fi άλλαξε."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Αυτή η συσκευή δεν υποστηρίζει την προτίμησή σας για αποκλειστική χρήση του εύρους 5 GHz. Αντ\' αυτού, αυτή η συσκευή θα χρησιμοποιεί το εύρος 5 GHz όταν είναι διαθέσιμο."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Οι ρυθμίσεις σημείου πρόσβασης Wi-Fi έχουν αλλάξει"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Πατήστε για προβολή λεπτομερειών."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rAU/strings.xml b/packages/SettingsProvider/res/values-en-rAU/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rAU/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rAU/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rCA/strings.xml b/packages/SettingsProvider/res/values-en-rCA/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rCA/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rGB/strings.xml b/packages/SettingsProvider/res/values-en-rGB/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rGB/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rGB/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rIN/strings.xml b/packages/SettingsProvider/res/values-en-rIN/strings.xml
index fac51d83..4e90cad 100644
--- a/packages/SettingsProvider/res/values-en-rIN/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rIN/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Settings Storage"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Changes to your hotspot settings"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Your hotspot band has changed."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"This device doesn’t support your preference for 5 GHz only. Instead, this device will use the 5 GHz band when available."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot settings have changed"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tap to see details"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-en-rXC/strings.xml b/packages/SettingsProvider/res/values-en-rXC/strings.xml
index fbc348b..4ea5c57 100644
--- a/packages/SettingsProvider/res/values-en-rXC/strings.xml
+++ b/packages/SettingsProvider/res/values-en-rXC/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‏‏‏‎‏‏‎‎‎‏‏‎‏‎‎‎‎‎‏‎‎‏‎‏‎‏‎‏‎‏‎‎‏‏‎‏‏‏‎‏‎‎‏‏‏‎‏‎‏‎‎‎‎‏‏‏‏‏‏‎Settings Storage‎‏‎‎‏‎"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‏‎‎‎‎‏‎‏‏‎‏‏‎‎‎‏‎‎‏‏‏‏‏‎‏‏‏‎‏‎‏‏‏‏‏‎‏‎‎‏‎‏‎‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎Changes to your hotspot settings‎‏‎‎‏‎"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‏‎‎‏‎‏‏‏‏‎‎‎‏‎‏‎‎‏‎‎‏‎‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‎‎Your hotspot band has changed.‎‏‎‎‏‎"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‏‎‎‎‎‏‎‎‏‎‏‏‎‏‏‎‏‎‏‎‎‏‏‎‎‎‎‎‎‎‏‏‏‏‎‏‎‏‎‎‏‎‎‎‎‎‏‏‎‏‏‎‎‏‎‎This device doesn’t support your preference for 5GHz only. Instead, this device will use the 5GHz band when available.‎‏‎‎‏‎"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‏‎‎‎‏‎‎‏‎‏‎‎‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‏‎‏‏‏‏‏‏‏‏‎‏‎‏‎‏‎‏‏‎‎‎‏‏‎‏‎Hotspot settings have changed‎‏‎‎‏‎"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‏‎‎‎‎‏‎‎‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‏‏‏‎‏‎‎‎‎‎‏‏‏‏‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‏‎‎‏‏‏‏‎Tap to see details‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-es-rUS/strings.xml b/packages/SettingsProvider/res/values-es-rUS/strings.xml
index af90257..4345b7a 100644
--- a/packages/SettingsProvider/res/values-es-rUS/strings.xml
+++ b/packages/SettingsProvider/res/values-es-rUS/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios en la configuración de tu hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Cambió la banda de tu hotspot."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Si bien este dispositivo no admite la opción para conectarse exclusivamente a bandas de 5 GHz, las usará cuando estén disponibles."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Se modificó la configuración de hotspot"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Presiona para obtener más información"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-es/strings.xml b/packages/SettingsProvider/res/values-es/strings.xml
index ff4ee38..3f1fa61 100644
--- a/packages/SettingsProvider/res/values-es/strings.xml
+++ b/packages/SettingsProvider/res/values-es/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamiento de configuración"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios en los ajustes del punto de acceso"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La banda de tu punto de acceso ha cambiado."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo no admite la opción de conectarse únicamente a bandas de 5 GHz, pero las usará cuando estén disponibles."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-et/strings.xml b/packages/SettingsProvider/res/values-et/strings.xml
index a0ec593..856ccf1 100644
--- a/packages/SettingsProvider/res/values-et/strings.xml
+++ b/packages/SettingsProvider/res/values-et/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Seadete talletusruum"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Muudatused teie kuumkoha seadetes"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Teie kuumkoha sagedusriba on muutunud."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"See seade ei toeta teie eelistatud ainult 5 GHz riba. Seade kasutab 5 GHz riba ainult siis, kui see on saadaval."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Kuumkoha seaded on muutunud"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Puudutage üksikasjade vaatamiseks"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-eu/strings.xml b/packages/SettingsProvider/res/values-eu/strings.xml
index 220b486..7ca91d8 100644
--- a/packages/SettingsProvider/res/values-eu/strings.xml
+++ b/packages/SettingsProvider/res/values-eu/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ezarpenen biltegia"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Aldaketak egin dira sare publikoaren ezarpenetan"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Aldatu da sare publikoaren banda."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Gailuak ez du onartzen 5 GHz-ko banda soilik erabiltzeko hobespena. Horren ordez, erabilgarri dagoen bakoitzean erabiliko da 5 GHz-ko banda."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Sare publikoaren ezarpenak aldatu dira"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Sakatu hau xehetasunak ikusteko"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-fa/strings.xml b/packages/SettingsProvider/res/values-fa/strings.xml
index 6819d2f..cc0b557 100644
--- a/packages/SettingsProvider/res/values-fa/strings.xml
+++ b/packages/SettingsProvider/res/values-fa/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"تنظیم محل ذخیره"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"تغییرات در تنظیمات نقطه اتصال"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"نوار نقطه اتصال شما تغییر کرد."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"این دستگاه از اولویت فقط ۵ گیگاهرتز شما پشتیبانی نمی‌کند. هرزمان نوار ۵ گیگاهرتزی دردسترس باشد، این دستگاه از آن استفاده خواهد کرد."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"تنظیمات نقطه اتصال تغییر کرده است"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"برای مشاهده جزئیات ضربه بزنید"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-fi/strings.xml b/packages/SettingsProvider/res/values-fi/strings.xml
index 9ad01eb..829bb3b 100644
--- a/packages/SettingsProvider/res/values-fi/strings.xml
+++ b/packages/SettingsProvider/res/values-fi/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Asetuksien tallennus"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot-asetustesi muutokset"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot-taajuutesi on muuttunut."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Tämä laite ei tue asetustasi (vain 5 GHz). Sen sijaan laite käyttää 5 GHz:n taajuutta sen ollessa käytettävissä."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot-asetuksia on muutettu"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Katso lisätiedot napauttamalla"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-fr-rCA/strings.xml b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
index 62951bd..d640845 100644
--- a/packages/SettingsProvider/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsProvider/res/values-fr-rCA/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifications apportées à vos paramètres de point d\'accès"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La bande de votre point d\'accès a changé."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Cet appareil ne prend pas en charge votre préférence pour la bande de 5 GHz seulement. Au lieu de cela, cet appareil utilisera la bande de 5 GHz lorsqu\'elle sera disponible."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Les paramètres de point d\'accès ont changé"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Touchez pour afficher les renseignements"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-fr/strings.xml b/packages/SettingsProvider/res/values-fr/strings.xml
index 56bc65b..ba6ec0b 100644
--- a/packages/SettingsProvider/res/values-fr/strings.xml
+++ b/packages/SettingsProvider/res/values-fr/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stockage des paramètres"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifications apportées à vos paramètres de point d\'accès"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La bande utilisée par votre point d\'accès a été modifiée."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Cet appareil n\'est pas conçu pour utiliser exclusivement la bande 5 GHz, mais il l\'utilisera chaque fois que disponible."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Les paramètres de point d\'accès ont changé"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Appuyer ici pour plus d\'infos"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-gl/strings.xml b/packages/SettingsProvider/res/values-gl/strings.xml
index 771fade..1be162e 100644
--- a/packages/SettingsProvider/res/values-gl/strings.xml
+++ b/packages/SettingsProvider/res/values-gl/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Almacenamento da configuración"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Cambios na configuración da zona wifi"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Modificouse a banda da zona wifi."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo non admite a opción de conectarse só a bandas de 5 GHz, pero usaraas se están dispoñibles."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"A configuración da zona wifi cambiou"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toca a notificación para ver os detalles"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-gu/strings.xml b/packages/SettingsProvider/res/values-gu/strings.xml
index a561924..074675f 100644
--- a/packages/SettingsProvider/res/values-gu/strings.xml
+++ b/packages/SettingsProvider/res/values-gu/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"સેટિંગ્સ સંગ્રહ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"તમારા હૉટસ્પૉટ સેટિંગને બદલે છે"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"તમારું હૉટસ્પૉટ બૅન્ડ બદલાઈ ગયું છે."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"આ ડિવાઇસ તમારી ફક્ત 5GHz માટેની પસંદગીને સપોર્ટ કરતું નથી. તેના બદલે, જ્યારે 5GHz બૅન્ડ ઉપલબ્ધ હશે ત્યારે આ ડિવાઇસ તેનો ઉપયોગ કરશે."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-hi/strings.xml b/packages/SettingsProvider/res/values-hi/strings.xml
index 199a546..9441a59 100644
--- a/packages/SettingsProvider/res/values-hi/strings.xml
+++ b/packages/SettingsProvider/res/values-hi/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिंग मेमोरी"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"आपकी हॉटस्पॉट की सेटिंग में किए गए बदलाव"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"आपका हॉटस्पॉट का बैंड बदल दिया गया है."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"इस डिवाइस पर आप \'सिर्फ़ 5 गीगाहर्ट्ज़\' वाला विकल्प नहीं चुन सकते. इसके बजाय, 5 गीगाहर्ट्ज़ बैंड उपलब्ध होने पर यह डिवाइस उसका इस्तेमाल करेगा."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"हॉटस्पॉट की सेटिंग बदल गई हैं"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"जानकारी देखने के लिए टैप करें"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-hr/strings.xml b/packages/SettingsProvider/res/values-hr/strings.xml
index 9129a04..206f50f 100644
--- a/packages/SettingsProvider/res/values-hr/strings.xml
+++ b/packages/SettingsProvider/res/values-hr/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Postavke pohrane"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Promjene postavki vaše žarišne točke"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Promijenila se frekvencija vaše žarišne točke."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ovaj uređaj ne podržava vašu postavku za upotrebu samo 5 GHz. Upotrebljavat će frekvenciju od 5 GHz kada je dostupna."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Promijenile su se postavke žarišne točke"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dodirnite da biste vidjeli pojedinosti"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-hu/strings.xml b/packages/SettingsProvider/res/values-hu/strings.xml
index a1ed494..a7ca0d2 100644
--- a/packages/SettingsProvider/res/values-hu/strings.xml
+++ b/packages/SettingsProvider/res/values-hu/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Beállítástároló"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"A hotspot beállításainak módosítása"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"A hotspot sávja megváltozott."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ez az eszköz nem támogatja a csak 5 GHz-es sávra vonatkozó beállítást. Az eszköz akkor használ 5 GHz-es sávot, ha a sáv rendelkezésre áll."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"A hotspot beállításai módosultak"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Koppintson a részletek megtekintéséhez"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-hy/strings.xml b/packages/SettingsProvider/res/values-hy/strings.xml
index 6d716f8..4fdb880 100644
--- a/packages/SettingsProvider/res/values-hy/strings.xml
+++ b/packages/SettingsProvider/res/values-hy/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Կարգավորումների պահուստ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Փոփոխություններ թեժ կետի կարգավորումներում"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ձեր թեժ կետի հաճախականությունը փոխվել է։"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Սարքը չի կարող աշխատել միայն 5 ԳՀց հաճախականությամբ։ Այդ հաճախականությունը կօգտագործվի հնարավորության դեպքում։"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Թեժ կետի կարգավորումները փոխվել են"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Հպեք՝ ավելին իմանալու համար"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-in/strings.xml b/packages/SettingsProvider/res/values-in/strings.xml
index 8b1b1f4..911892b 100644
--- a/packages/SettingsProvider/res/values-in/strings.xml
+++ b/packages/SettingsProvider/res/values-in/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Setelan Penyimpanan"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Perubahan pada setelan hotspot Anda"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Band hotspot Anda telah berubah."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Perangkat ini tidak mendukung preferensi Anda, yaitu hanya 5GHz. Sebagai gantinya, perangkat ini akan menggunakan band 5GHz jika tersedia."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Setelan hotspot telah berubah"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ketuk untuk melihat detail"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-is/strings.xml b/packages/SettingsProvider/res/values-is/strings.xml
index 150c084..c72442e 100644
--- a/packages/SettingsProvider/res/values-is/strings.xml
+++ b/packages/SettingsProvider/res/values-is/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stillingageymsla"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Breytingar á stillingum heits reits"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Tíðnisvið heita reitsins hefur breyst."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Þetta tæki styður ekki val þitt fyrir aðeins 5 GHz. Í staðinn mun þetta tæki nota 5 GHz tíðnisvið þegar það er í boði."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Stillingum heits reits hefur verið breytt"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ýttu til að sjá upplýsingar"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-it/strings.xml b/packages/SettingsProvider/res/values-it/strings.xml
index 6715c3c..0e11d06 100644
--- a/packages/SettingsProvider/res/values-it/strings.xml
+++ b/packages/SettingsProvider/res/values-it/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Memoria impostazioni"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modifiche alle tue impostazioni dell\'hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"La banda dell\'hotspot è cambiata."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Questo dispositivo non supporta la tua preferenza esclusiva per 5 GHz. Utilizzerà la banda a 5 GHz solo quando è disponibile."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Le impostazioni di hotspot sono state modificate"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tocca per vedere i dettagli"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-iw/strings.xml b/packages/SettingsProvider/res/values-iw/strings.xml
index dd44329..8d8594d 100644
--- a/packages/SettingsProvider/res/values-iw/strings.xml
+++ b/packages/SettingsProvider/res/values-iw/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"אחסון הגדרות"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"שינויים להגדרות של הנקודה לשיתוף אינטרנט"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"התדר של הנקודה לשיתוף אינטרנט השתנה."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"‏מכשיר זה לא תומך בהעדפות שלך ל-5GHz בלבד. במקום זאת, מכשיר זה ישתמש בתדר 5GHz כשיהיה זמין."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"ההגדרות של הנקודה לשיתוף אינטרנט השתנו"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"יש להקיש להצגת פרטים"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ja/strings.xml b/packages/SettingsProvider/res/values-ja/strings.xml
index 7bbcd46..5b91b2d 100644
--- a/packages/SettingsProvider/res/values-ja/strings.xml
+++ b/packages/SettingsProvider/res/values-ja/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ストレージの設定"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"アクセス ポイントの設定の変更"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"アクセス ポイントの帯域幅が変更されました。"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"このデバイスは 5 GHz のみという設定に対応していません。ただし、5 GHz 周波数帯が利用できるときには利用します。"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"アクセス ポイントの設定が変更されました"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"タップして詳細を確認してください"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ka/strings.xml b/packages/SettingsProvider/res/values-ka/strings.xml
index 86db4f3..70845ac 100644
--- a/packages/SettingsProvider/res/values-ka/strings.xml
+++ b/packages/SettingsProvider/res/values-ka/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"პარამეტრების საცავი"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"თქვენი უსადენო ქსელის პარამეტრების ცვლილება"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"თქვენი უსადენო ქსელის დიაპაზონი შეიცვალა."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ამ მოწყობილობას არ შეუძლია მხოლოდ 5 გჰც სიხშირეზე მუშაობა. აღნიშნული სიხშირის გამოყენება მოხდება მაშინ, როცა ეს შესაძლებელია."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"უსადენო ქსელის პარამეტრები შეიცვალა"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"შეეხეთ დეტალების სანახავად"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-kk/strings.xml b/packages/SettingsProvider/res/values-kk/strings.xml
index a093d08..2823e4e 100644
--- a/packages/SettingsProvider/res/values-kk/strings.xml
+++ b/packages/SettingsProvider/res/values-kk/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Параметрлер жады"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Хотспот параметрлеріне өзгерістер енгізілді"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Хотспот жолағы өзгертілді."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Бұл құрылғы тек 5 ГГц жиілікте жұмыс істей алмайды. Бұл жиілік мүмкін болған жағдайда ғана қолданылады."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Хотспот параметрлері өзгертілді"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Мәліметтерді көру үшін түртіңіз."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-km/strings.xml b/packages/SettingsProvider/res/values-km/strings.xml
index f0a2712..cdae410 100644
--- a/packages/SettingsProvider/res/values-km/strings.xml
+++ b/packages/SettingsProvider/res/values-km/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"កំណត់​ការ​ផ្ទុក"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ប្ដូរ​ទៅ​ការ​កំណត់​ហតស្ប៉ត​របស់អ្នក"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"កម្រិតបញ្ជូន​ហតស្ប៉ត​របស់​អ្នកបាន​ផ្លាស់ប្ដូរ។"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ឧបករណ៍នេះ​មិនស្គាល់​ចំណូលចិត្ត​របស់អ្នក​សម្រាប់តែ 5GHz ប៉ុណ្ណោះ។ ផ្ទុយមកវិញ ឧបករណ៍នេះ​នឹងប្រើ​កម្រិតបញ្ជូន 5GHz នៅពេល​ដែលអាច​ប្រើបាន។"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"បាន​ប្ដូរ​ការកំណត់​ហតស្ប៉ត"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ចុច​ដើម្បី​មើល​ព័ត៌មានលម្អិត"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-kn/strings.xml b/packages/SettingsProvider/res/values-kn/strings.xml
index f2c1d5e..0b0000d 100644
--- a/packages/SettingsProvider/res/values-kn/strings.xml
+++ b/packages/SettingsProvider/res/values-kn/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ಸೆಟ್ಟಿಂಗ್‌ಗಳ ಸಂಗ್ರಹಣೆ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ನಿಮ್ಮ ಹಾಟ್‌ಸ್ಪಾಟ್‌ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿನ ಬದಲಾವಣೆಗಳು"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ನಿಮ್ಮ ಹಾಟ್‌ಸ್ಪಾಟ್‌ ಬ್ಯಾಂಡ್ ಬದಲಾಗಿದೆ."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ಈ ಸಾಧನವು 5GHz ಗೆ ಮಾತ್ರ ನಿಮ್ಮ ಆದ್ಯತೆಯನ್ನು ಬೆಂಬಲಿಸುವುದಿಲ್ಲ. ಬದಲಿಗೆ, ಈ ಸಾಧನವು 5GHz ಬ್ಯಾಂಡ್ ಅನ್ನು ಲಭ್ಯವಿರುವಾಗ ಬಳಸುತ್ತದೆ."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ko/strings.xml b/packages/SettingsProvider/res/values-ko/strings.xml
index 841832d..d76b766 100644
--- a/packages/SettingsProvider/res/values-ko/strings.xml
+++ b/packages/SettingsProvider/res/values-ko/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"설정 저장소"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"핫스팟 설정 변경"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"핫스팟 대역이 변경되었습니다."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"이 기기에서는 5GHz 전용 환경설정이 지원되지 않습니다. 대신 가능할 때만 기기에서 5GHz 대역이 사용됩니다."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"핫스팟 설정 변경됨"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"세부정보를 보려면 탭하세요."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ky/strings.xml b/packages/SettingsProvider/res/values-ky/strings.xml
index 014c66c..e5b82c6 100644
--- a/packages/SettingsProvider/res/values-ky/strings.xml
+++ b/packages/SettingsProvider/res/values-ky/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Жөндөөлөрдү сактоо"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Байланыш түйүнүңүздүн жөндөөлөрү өзгөрүлдү"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Байланыш түйүнүңүздүн жыштыгы өзгөрдү."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Бул түзмөк 5ГГцти гана колдонуу жөндөөсүн колдоого албайт. Анын ордуна, бул түзмөк 5ГГц жыштыгын ал жеткиликтүү болгондо колдонот."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Хотспот жөндөөлөрү өзгөрдү"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Чоо-жайын билүү үчүн басыңыз"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-lo/strings.xml b/packages/SettingsProvider/res/values-lo/strings.xml
index 9d60ba1..c2b5df7 100644
--- a/packages/SettingsProvider/res/values-lo/strings.xml
+++ b/packages/SettingsProvider/res/values-lo/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ບ່ອນເກັບຂໍ້ມູນການຕັ້ງຄ່າ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ການປ່ຽນແປງການຕັ້ງຄ່າຮັອດສະປອດຂອງທ່ານ"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ຄື້ນຄວາມຖີ່ຮັອດສະປອດຂອງທ່ານປ່ຽນແປງແລ້ວ."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ອຸປະກອນນີ້ບໍ່ຮອງຮັບການຕັ້ງຄ່າຂອງທ່ານສຳລັບ 5GHz ເທົ່ານັ້ນ. ແຕ່ວ່າອຸປະກອນນີ້ຈະໃຊ້ຄື້ນຄວາມຖີ່ 5GHz ເມື່ອສາມາດໃຊ້ໄດ້."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"ບັນທຶກການຕັ້ງຄ່າຮັອດສະປອດແລ້ວ"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"ແຕະເພື່ອເບິ່ງລາຍລະອຽດ"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-lt/strings.xml b/packages/SettingsProvider/res/values-lt/strings.xml
index 775d3b9..64f429b 100644
--- a/packages/SettingsProvider/res/values-lt/strings.xml
+++ b/packages/SettingsProvider/res/values-lt/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Nustatymų saugykla"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Viešosios interneto prieigos taško nustatymų pakeitimai"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Viešosios prieigos taško dažnio juosta pasikeitė."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Šiame įrenginyje nepalaikoma tik 5 GHz nuostata. Vietoj to šiame įrenginyje bus naudojama 5 GHz dažnio juosta, kai bus pasiekiama."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Buvo pakeisti viešosios interneto prieigos taško nustatymai"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Palieskite ir peržiūrėkite išsamią informaciją"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-lv/strings.xml b/packages/SettingsProvider/res/values-lv/strings.xml
index f7f3117..e5af8f7 100644
--- a/packages/SettingsProvider/res/values-lv/strings.xml
+++ b/packages/SettingsProvider/res/values-lv/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Iestatījumu krātuve"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Izmaiņas tīklāja iestatījumos"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ir mainīts tīklāja joslas platums."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Šajā ierīcē netiek atbalstīta jūsu preference par tikai 5 GHz joslu. 5 GHz josla ierīcē tiks izmantota, kad tā būs pieejama."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Ir mainīti tīklāja iestatījumi"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Pieskarieties, lai skatītu detalizētāku informāciju."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-mk/strings.xml b/packages/SettingsProvider/res/values-mk/strings.xml
index a245e5f..13ff8a2 100644
--- a/packages/SettingsProvider/res/values-mk/strings.xml
+++ b/packages/SettingsProvider/res/values-mk/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Поставки за меморија"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промени на поставките за точка на пристап"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Опсегот за точка на пристап е променет."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Уредов не ги поддржува вашите поставки за само 5 GHz. Наместо тоа, ќе го користи опсегот од 5 GHz кога е достапен."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Поставките за точка на пристап се променија"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Допрете за да видите детали"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ml/strings.xml b/packages/SettingsProvider/res/values-ml/strings.xml
index b63f20e..54a05fb 100644
--- a/packages/SettingsProvider/res/values-ml/strings.xml
+++ b/packages/SettingsProvider/res/values-ml/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"സംഭരണ ക്രമീകരണം"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"നിങ്ങളുടെ ഹോട്ട്‌സ്‌പോട്ട് ക്രമീകരണത്തിൽ വരുത്തിയ മാറ്റങ്ങൾ"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"നിങ്ങളുടെ ഹോട്ട്‌സ്‌പോട്ട് ബാൻഡ് മാറിയിരിക്കുന്നു."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"നിങ്ങളുടെ മുൻഗണനയനുസരിച്ചുള്ള, 5GHz മാത്രം എന്നത് ഈ ഉപകരണം പിന്തുണയ്ക്കുന്നില്ല. പകരം, 5GHz ബാൻഡ് ലഭ്യമാകുമ്പോൾ അത് ഉപയോഗിക്കും."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-mn/strings.xml b/packages/SettingsProvider/res/values-mn/strings.xml
index c839177..a9c2e8c 100644
--- a/packages/SettingsProvider/res/values-mn/strings.xml
+++ b/packages/SettingsProvider/res/values-mn/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Тохиргооны Сан"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Таны сүлжээний цэгийн тохиргооны өөрчлөлт"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Таны сүлжээний цэгийн хязгаарыг өөрчилсөн."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Энэ төхөөрөмж нь зөвхөн 5Гц гэсэн таны сонголтыг дэмждэггүй. Оронд нь энэ төхөөрөмж 5Гц-н хязгаарыг боломжтой үед нь ашиглах болно."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Сүлжээний цэгийн тохиргоог өөрчиллөө"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Дэлгэрэнгүй мэдээлэл харахын тулд товшино уу"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-mr/strings.xml b/packages/SettingsProvider/res/values-mr/strings.xml
index 0c7041e..0e80f70 100644
--- a/packages/SettingsProvider/res/values-mr/strings.xml
+++ b/packages/SettingsProvider/res/values-mr/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिंग्ज संचयन"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"तुमच्या हॉटस्पॉट सेटिंग्जमधील बदल"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"तुमचा हॉटस्पॉट बँड बदलला गेला आहे."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"हे डिव्हाइस फक्त ५GHz च्या तुमच्या प्राधान्याला सपोर्ट करत नाही. त्याऐवजी, उपलब्ध असेल तेव्हा हे डिव्हाइस ५GHz बँड वापरेल."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-ms/strings.xml b/packages/SettingsProvider/res/values-ms/strings.xml
index a1574df..51a8f2b 100644
--- a/packages/SettingsProvider/res/values-ms/strings.xml
+++ b/packages/SettingsProvider/res/values-ms/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Storan Tetapan"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Perubahan kepada tetapan tempat liputan anda"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Jalur tempat liputan anda telah berubah."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Peranti ini tidak menyokong pilihan anda untuk 5GHz sahaja. Sebaliknya, peranti ini akan menggunakan jalur 5GHz apabila tersedia."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Tetapan tempat liputan telah berubah"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ketik untuk melihat butiran"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-my/strings.xml b/packages/SettingsProvider/res/values-my/strings.xml
index 48d4dba..dc9f531 100644
--- a/packages/SettingsProvider/res/values-my/strings.xml
+++ b/packages/SettingsProvider/res/values-my/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"သိုလှောင်မှုဆက်တင်များ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"သင်၏ဟော့စပေါ့ ဆက်တင်များ ပြောင်းလဲမှု"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"သင်၏ ဟော့စပေါ့လိုင်း ပြောင်းသွားပါပြီ။"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ဤစက်ပစ္စည်းသည် သင်၏ 5GHz သီးသန့်ရွေးချယ်မှုအတွက် ပံ့ပိုးမထားပါ။ ၎င်းအစား ဤစက်ပစ္စည်းသည် ရနိုင်သည့်အခါ 5GHz လိုင်းကို သုံးသွားပါမည်။"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"ဟော့စပေါ့ ဆက်တင်များ ပြောင်းသွားပြီ"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"အသေးစိတ်ကြည့်ရန် တို့ပါ"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-nb/strings.xml b/packages/SettingsProvider/res/values-nb/strings.xml
index e0cbd7e..3bdaf83 100644
--- a/packages/SettingsProvider/res/values-nb/strings.xml
+++ b/packages/SettingsProvider/res/values-nb/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring av innstillinger"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Endres til innstillingene dine for Wi-Fi-soner"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Båndet ditt for Wi-Fi-sone er endret."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Denne enheten støtter ikke innstillingen din for bare 5 GHz. I stedet bruker enheten 5 GHz-båndet når det er tilgjengelig."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Innstillingene for Wi-Fi-sone er endret"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Trykk for å se detaljer"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ne/strings.xml b/packages/SettingsProvider/res/values-ne/strings.xml
index 2fd9b00..bb04b6ba 100644
--- a/packages/SettingsProvider/res/values-ne/strings.xml
+++ b/packages/SettingsProvider/res/values-ne/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"सेटिङहरू भण्डारण"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"तपाईंका हटस्पट सेटिङहरूमा गरिएका परिवर्तनहरू"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"तपाईंको हटस्पट ब्यान्ड परिवर्तन भएको छ।"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"यो यन्त्रले तपाईंको 5GHz मात्रको प्राथमिकतालाई समर्थन गर्दैन। बरु, उपलब्ध भएको खण्डमा यो यन्त्रले 5GHz ब्यान्ड प्रयोग गर्ने छ।"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-nl/strings.xml b/packages/SettingsProvider/res/values-nl/strings.xml
index 0b843ae..91b8542 100644
--- a/packages/SettingsProvider/res/values-nl/strings.xml
+++ b/packages/SettingsProvider/res/values-nl/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Opslagruimte voor instellingen"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Wijzigingen in je hotspot-instellingen"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Je hotspot-band is gewijzigd."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dit apparaat biedt geen ondersteuning voor je voorkeur voor alleen 5 GHz. In plaats daarvan gebruikt dit apparaat de 5-GHz-band wanneer deze beschikbaar is."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot-instellingen zijn gewijzigd"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tik voor meer informatie"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-or/strings.xml b/packages/SettingsProvider/res/values-or/strings.xml
index 53f6104..4b73a55 100644
--- a/packages/SettingsProvider/res/values-or/strings.xml
+++ b/packages/SettingsProvider/res/values-or/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ସେଟିଙ୍ଗ ଷ୍ଟୋରେଜ୍‌"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ଆପଣଙ୍କର ହଟ୍‌ସ୍ପଟ୍ ସେଟିଂସ୍‌କୁ ବଦଳାଇଥାଏ"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ଆପଣଙ୍କର ହଟ୍‌ସ୍ପଟ୍ ପରିବର୍ତ୍ତନ କରାଯାଇଛି।"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"କେବଳ 5GHz ପାଇଁ, ଏହି ଡିଭାଇସ୍ ଆପଣଙ୍କର ପସନ୍ଦକୁ ସମର୍ଥନ କରେ ନାହିଁ। ଏହା ପରିବର୍ତ୍ତେ, ଉପଲବ୍ଧ ହେଲେ ଏହି ଡିଭାଇସ୍ 5GHz ବ୍ୟାଣ୍ଡ ବ୍ୟବହାର କରିବ।"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pa/strings.xml b/packages/SettingsProvider/res/values-pa/strings.xml
index 9a41e36..5af8d6a 100644
--- a/packages/SettingsProvider/res/values-pa/strings.xml
+++ b/packages/SettingsProvider/res/values-pa/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ਸੈਟਿੰਗਾਂ ਸਟੋਰੇਜ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ਤੁਹਾਡੀਆਂ ਹੌਟਸਪੌਟ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਬਦਲਾਅ"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ਤੁਹਾਡਾ ਹੌਟਸਪੌਟ ਬੈਂਡ ਬਦਲ ਗਿਆ ਹੈ।"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ਇਹ ਡੀਵਾਈਸ ਸਿਰਫ਼ 5GHz ਦੀ ਤੁਹਾਡੀ ਤਰਜੀਹ ਦਾ ਸਮਰਥਨ ਨਹੀਂ ਕਰਦਾ ਹੈ। ਇਸਦੀ ਬਜਾਏ, ਇਹ ਡੀਵਾਈਸ ਉਪਲਬਧ ਹੋਣ \'ਤੇ 5GHz ਬੈਂਡ ਵਰਤੇਗਾ।"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-pl/strings.xml b/packages/SettingsProvider/res/values-pl/strings.xml
index 7fd2b13..d86fc4d 100644
--- a/packages/SettingsProvider/res/values-pl/strings.xml
+++ b/packages/SettingsProvider/res/values-pl/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Pamięć ustawień"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Zmieniono ustawienia hotspotu"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Zmieniono pasmo hotspotu."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"To urządzenie nie może korzystać tylko z częstotliwości 5 GHz. Będzie korzystać z tego pasma, jeśli będzie ono dostępne."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Ustawienia hotspotu zostały zmienione"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Kliknij, by zobaczyć szczegóły"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt-rBR/strings.xml b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
index 18db8f6..a860018 100644
--- a/packages/SettingsProvider/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rBR/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mudanças nas suas configurações de ponto de acesso"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Sua banda de ponto de acesso foi modificada."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não é compatível com sua preferência apenas por 5 GHz. Em vez disso, o dispositivo usará a banda de 5 GHz quando ela estiver disponível."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"As configurações de ponto de acesso mudaram"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt-rPT/strings.xml b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
index be88cce..a8a8e07 100644
--- a/packages/SettingsProvider/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsProvider/res/values-pt-rPT/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de definições"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Alterações às definições de zona Wi-Fi"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"A banda da sua zona Wi-Fi foi alterada."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não suporta a sua preferência apenas para 5 GHz. Em alternativa, este dispositivo vai utilizar a banda de 5 GHz quando estiver disponível."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"As definições da zona Wi-Fi foram alteradas"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-pt/strings.xml b/packages/SettingsProvider/res/values-pt/strings.xml
index 18db8f6..a860018 100644
--- a/packages/SettingsProvider/res/values-pt/strings.xml
+++ b/packages/SettingsProvider/res/values-pt/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Armazenamento de configurações"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mudanças nas suas configurações de ponto de acesso"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Sua banda de ponto de acesso foi modificada."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Este dispositivo não é compatível com sua preferência apenas por 5 GHz. Em vez disso, o dispositivo usará a banda de 5 GHz quando ela estiver disponível."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"As configurações de ponto de acesso mudaram"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Toque para ver os detalhes"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ro/strings.xml b/packages/SettingsProvider/res/values-ro/strings.xml
index 3a234e1..561a213 100644
--- a/packages/SettingsProvider/res/values-ro/strings.xml
+++ b/packages/SettingsProvider/res/values-ro/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Stocare setări"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Modificări aduse setărilor pentru hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"S-a schimbat banda de frecvență a hotspotului."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Dispozitivul nu acceptă doar preferința pentru 5 GHz. Dispozitivul va folosi banda de 5 GHz când este disponibilă."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Setările hotspotului s-au modificat"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Atingeți pentru detalii"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ru/strings.xml b/packages/SettingsProvider/res/values-ru/strings.xml
index 184afdd..331fae1 100644
--- a/packages/SettingsProvider/res/values-ru/strings.xml
+++ b/packages/SettingsProvider/res/values-ru/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Хранилище настроек"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Изменения в настройках точки доступа"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Частота точки доступа изменена."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Устройство не может работать только на частоте 5 ГГц. Эта частота будет использоваться, когда это возможно."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Настройки точки доступа изменены"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Нажмите, чтобы узнать больше."</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-si/strings.xml b/packages/SettingsProvider/res/values-si/strings.xml
index 69e04f1..a9c4d0b 100644
--- a/packages/SettingsProvider/res/values-si/strings.xml
+++ b/packages/SettingsProvider/res/values-si/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"සැකසීම් ගබඩාව"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"ඔබගේ හොට්ස්පොට් සැකසීම්වලට වෙනස් කිරීම්"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ඔබගේ හොට්ස්පොට් කලාපය වෙනස් වී ඇත."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"මෙම උපාංගය 5GHz සඳහා ඔබේ මනාපවලට සහාය නොදක්වයි. ඒ වෙනුවට, මෙම උපාංගය ලබා ගත හැකි විට 5GHz කලාපය භාවිතා කරනු ඇත."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"හොට්ස්පොට් සැකසීම් වෙනස් කර ඇත"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"විස්තර බැලීමට තට්ටු කරන්න"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sk/strings.xml b/packages/SettingsProvider/res/values-sk/strings.xml
index a53178d..5712d05 100644
--- a/packages/SettingsProvider/res/values-sk/strings.xml
+++ b/packages/SettingsProvider/res/values-sk/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ukladací priestor nastavení"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Zmeny nastavení hotspotu"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pásmo vášho hotspotu sa zmenilo."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Toto zariadenie nepodporuje vašu predvoľbu používať iba 5 GHz. Namiesto toho bude pásmo 5 GHz používať vtedy, keď bude k dispozícii."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavenia hotspotu boli zmenené"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Klepnutím zobrazíte podrobnosti"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sl/strings.xml b/packages/SettingsProvider/res/values-sl/strings.xml
index ea697fe..4e265fb 100644
--- a/packages/SettingsProvider/res/values-sl/strings.xml
+++ b/packages/SettingsProvider/res/values-sl/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Shramba nastavitev"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Spremembe nastavitev dostopne točke"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Pas dostopne točke je spremenjen."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Ta naprava ne podpira prednostne nastavitve samo za 5-GHz pas. Namesto tega bo ta naprava uporabljala 5-GHz pas, ko bo na voljo."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nastavitve dostopne ročke so spremenjene"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Dotaknite se za ogled podrobnosti"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sq/strings.xml b/packages/SettingsProvider/res/values-sq/strings.xml
index a111576..8bbe2e7 100644
--- a/packages/SettingsProvider/res/values-sq/strings.xml
+++ b/packages/SettingsProvider/res/values-sq/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Hapësira ruajtëse e \"Cilësimeve\""</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ndryshimet në cilësimet e zonës së qasjes për internet"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Brezi yt i zonës së qasjes për internet ka ndryshuar."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Kjo pajisje nuk e mbështet preferencën për vetëm 5 GHz. Përkundrazi, pajisja do të përdorë brezin 5 GHz nëse ka."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Cilësimet e zonës së qasjes për internet kanë ndryshuar"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Trokit për të parë detajet"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sr/strings.xml b/packages/SettingsProvider/res/values-sr/strings.xml
index d473102..4d05762 100644
--- a/packages/SettingsProvider/res/values-sr/strings.xml
+++ b/packages/SettingsProvider/res/values-sr/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Подешавања складишта"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Промене подешавања за хотспот"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Опсег хотспота је промењен."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Овај уређај не подржава подешавање само за 5 GHz. Уређај ће користити опсег од 5 GHz када буде доступан."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Подешавања хотспота су промењена"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Додирните да бисте видели детаље"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sv/strings.xml b/packages/SettingsProvider/res/values-sv/strings.xml
index fea3e5e..5ee4703 100644
--- a/packages/SettingsProvider/res/values-sv/strings.xml
+++ b/packages/SettingsProvider/res/values-sv/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lagring av inställningar"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ändringar i inställningarna för surfzon"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Frekvensbandet för surfzonen har ändrats."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Den här enheten har inte stöd för inställningen för att endast använda 5 GHz. I stället används 5 GHz när det är möjligt."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Inställningarna för surfzon har ändrats"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tryck här för mer information"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-sw/strings.xml b/packages/SettingsProvider/res/values-sw/strings.xml
index 4d05817..59f82a9 100644
--- a/packages/SettingsProvider/res/values-sw/strings.xml
+++ b/packages/SettingsProvider/res/values-sw/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Hifadhi ya Mipangilio"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mabadiliko kwenye mipangilio ya mtandaopepe"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Bendi ya mtandaopepe wako imebadilika."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Kifaa hiki hakitumii mapendeleo yako ya GHz 5 pekee. Badala yake, kifaa hiki kitatumia bendi ya GHz 5 itakapopatikana."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Mipangilio ya mtandaopepe imebadilika"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Gusa ili uangalie maelezo"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ta/strings.xml b/packages/SettingsProvider/res/values-ta/strings.xml
index f518a78..fa6b8cd 100644
--- a/packages/SettingsProvider/res/values-ta/strings.xml
+++ b/packages/SettingsProvider/res/values-ta/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"அமைப்புகளின் சேமிப்பிடம்"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"உங்கள் ஹாட்ஸ்பாட் அமைப்புகளில் செய்யப்பட்டுள்ள மாற்றங்கள்"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"உங்கள் ஹாட்ஸ்பாட்டின் அலைவரிசை வரம்பு மாறிவிட்டது."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"இந்தச் சாதனத்தில், ’5GHz மட்டும்’ எனும் முன்னுரிமைத் தேர்வு ஆதரிக்கப்படவில்லை. எனினும் 5GHz அலைவரிசை வரம்பிற்குள் இருக்கும்போது சாதனம் அதைப் பயன்படுத்திக்கொள்ளும்."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-te/strings.xml b/packages/SettingsProvider/res/values-te/strings.xml
index 6c59223..b1955ed 100644
--- a/packages/SettingsProvider/res/values-te/strings.xml
+++ b/packages/SettingsProvider/res/values-te/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"సెట్టింగ్‌ల నిల్వ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"మీ హాట్‌స్పాట్ సెట్టింగ్‌లకు మార్పులు"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"మీ హాట్‌స్పాట్ బ్యాండ్ మార్చబడింది."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"ఈ పరికరం 5GHz కోసం మాత్రమే మీ ప్రాధాన్యతకు మద్దతు ఇవ్వదు. బదులుగా, ఈ పరికరం అందుబాటులో ఉన్నప్పుడు 5GHz బ్యాండ్‌ను ఉపయోగిస్తుంది."</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-th/strings.xml b/packages/SettingsProvider/res/values-th/strings.xml
index 4bf148f..ed63174 100644
--- a/packages/SettingsProvider/res/values-th/strings.xml
+++ b/packages/SettingsProvider/res/values-th/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ที่เก็บข้อมูลการตั้งค่า"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"มีการเปลี่ยนแปลงการตั้งค่าฮอตสปอต"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"ย่านความถี่ฮอตสปอตมีการเปลี่ยนแปลง"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"อุปกรณ์นี้ไม่รองรับค่ากำหนดของคุณเฉพาะสำหรับ 5 GHz เท่านั้น และจะใช้ย่านความถี่ 5 GHz แทน เมื่อใช้ได้"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"การตั้งค่าฮอตสปอตมีการเปลี่ยนแปลง"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"แตะเพื่อดูรายละเอียด"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-tl/strings.xml b/packages/SettingsProvider/res/values-tl/strings.xml
index 2a36d58..3d6be40 100644
--- a/packages/SettingsProvider/res/values-tl/strings.xml
+++ b/packages/SettingsProvider/res/values-tl/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Storage ng Mga Setting"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Mga pagbabago sa mga setting ng iyong hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Nagbago ang band ng iyong hotspot."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Hindi sinusuportahan ng device na ito ang kagustuhan mong gumamit lang ng 5GHz. Sa halip, gagamitin ng device na ito ang 5GHz na band kapag available."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Nabago ang mga setting ng hotspot"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"I-tap para makita ang mga detalye"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-tr/strings.xml b/packages/SettingsProvider/res/values-tr/strings.xml
index add1fdb..75e908f 100644
--- a/packages/SettingsProvider/res/values-tr/strings.xml
+++ b/packages/SettingsProvider/res/values-tr/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Ayarlar Deposu"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot ayarlarınız değişti"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot bandınız değişti."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Bu cihaz yalnızca 5 GHz bandının kullanılmasına yönelik tercihinizi desteklemiyor. Bunun yerine, bu cihaz 5 GHz bandını mevcut olduğunda kullanacak."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot ayarları değişti"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Ayrıntıları görmek için dokunun"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-uk/strings.xml b/packages/SettingsProvider/res/values-uk/strings.xml
index cd678bc..2dbb360 100644
--- a/packages/SettingsProvider/res/values-uk/strings.xml
+++ b/packages/SettingsProvider/res/values-uk/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Сховище налаштувань"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Зміни в налаштуваннях точки доступу"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Діапазон частот точки доступу змінено."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"На цьому пристрої не підтримується налаштування \"Лише 5 ГГц\". Натомість буде використано діапазон частот 5 ГГц (якщо доступно)."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Налаштування точки доступу змінились"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Торкніться, щоб переглянути докладні відомості"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-ur/strings.xml b/packages/SettingsProvider/res/values-ur/strings.xml
index 2241ce9..2ce44b1 100644
--- a/packages/SettingsProvider/res/values-ur/strings.xml
+++ b/packages/SettingsProvider/res/values-ur/strings.xml
@@ -20,7 +20,8 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"ترتیبات کا اسٹوریج"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"اپنے ہاٹ اسپاٹ کی ترتیبات میں تبدیلیاں"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"آپ کا ہاٹ اسپات بینڈ تبدیل ہو گیا ہے۔"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"‏یہ آلہ صرف 5GHz کے لیے آپ کی ترجیح کو سپورٹ نہیں کرے گا۔ بلکہ 5GHz بینڈ کے دستیاب ہونے پر اس کا استعمال کرے گا۔"</string>
+    <!-- no translation found for wifi_softap_config_change (5688373762357941645) -->
+    <skip />
+    <!-- no translation found for wifi_softap_config_change_summary (8946397286141531087) -->
+    <skip />
 </resources>
diff --git a/packages/SettingsProvider/res/values-uz/strings.xml b/packages/SettingsProvider/res/values-uz/strings.xml
index a266bf0..bb6e22e 100644
--- a/packages/SettingsProvider/res/values-uz/strings.xml
+++ b/packages/SettingsProvider/res/values-uz/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Sozlamalar xotirasi"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Hotspot sozlamalari o‘zgartirildi"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Hotspot chastotasi oʻzgartirildi."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Qurilma faqat 5 GGs chastotada ishlay olmaydi. Bu chastotadan imkoniyatga qarab foydalaniladi."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Hotspot sozlamalari oʻzgardi"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Tafsilotlar uchun bosing"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-vi/strings.xml b/packages/SettingsProvider/res/values-vi/strings.xml
index 74f93b2..4608983 100644
--- a/packages/SettingsProvider/res/values-vi/strings.xml
+++ b/packages/SettingsProvider/res/values-vi/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Lưu trữ bộ nhớ"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Những thay đổi trong mục cài đặt điểm phát sóng của bạn"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Bằng tần của điểm phát sóng đã thay đổi."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Thiết bị này không hỗ trợ tùy chọn chỉ sử dụng băng tần 5 GHz. Thay vào đó, thiết bị này sẽ sử dụng băng tần 5 GHz khi có thể."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Đã thay đổi các tùy chọn cài đặt điểm phát sóng"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Nhấn để xem chi tiết"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rCN/strings.xml b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
index 95b15e0..a08afc8 100644
--- a/packages/SettingsProvider/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rCN/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"设置存储"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"您的热点设置已变更"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"您的热点频段已变更。"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"此设备不支持您的偏好设置(仅限 5GHz),而且会在 5GHz 频段可用时使用该频段。"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"热点设置已更改"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"点按即可查看详细信息"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rHK/strings.xml b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
index 41ebe27..fb91dbb 100644
--- a/packages/SettingsProvider/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rHK/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"您的熱點設定變更"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"您的熱點頻段已變更。"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"此裝置不支援只限 5 GHz 的偏好設定,但會在 5 GHz 頻段可用時採用。"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"熱點設定已變更"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"輕按以查看詳情"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-zh-rTW/strings.xml b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
index d0a30f5..1b8fcb2 100644
--- a/packages/SettingsProvider/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsProvider/res/values-zh-rTW/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"設定儲存空間"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"無線基地台設定變更"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"你的無線基地台頻帶已變更。"</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"這部裝置不支援你的偏好設定 (僅限 5GHz),而是會在 5GHz 可用時使用該頻帶。"</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"無線基地台設定有所變更"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"輕觸即可查看詳細資料"</string>
 </resources>
diff --git a/packages/SettingsProvider/res/values-zu/strings.xml b/packages/SettingsProvider/res/values-zu/strings.xml
index 0440b3b..dad24b4 100644
--- a/packages/SettingsProvider/res/values-zu/strings.xml
+++ b/packages/SettingsProvider/res/values-zu/strings.xml
@@ -20,7 +20,6 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="4567566098528588863">"Izilungiselelo zesitoreji"</string>
-    <string name="wifi_softap_config_change" msgid="5338670993556993667">"Ushintsho kuzilungiselelo zakho ze-hotspot"</string>
-    <string name="wifi_softap_config_change_summary" msgid="7600005249167787750">"Ibhendi yakho ye-hotspot ishintshile."</string>
-    <string name="wifi_softap_config_change_detailed" msgid="2504664754843959730">"Le divayisi ayisekeli okuncamelayo kwe-5GHz kuphela. Kunalokho, le divayisi izosebenzisa ibhendi ye-5GHz uma itholakala."</string>
+    <string name="wifi_softap_config_change" msgid="5688373762357941645">"Izilungiselelo ze-Hotspot zishintshile"</string>
+    <string name="wifi_softap_config_change_summary" msgid="8946397286141531087">"Thepha ukuze ubone imininingwane"</string>
 </resources>
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index aad46e9..2dc6f39 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -989,6 +989,11 @@
                             String value = setting != null ? setting.getValue() : null;
                             updateGlobalSetting(Settings.Global.ADB_ENABLED,
                                     value, null, true, userId, true);
+
+                            setting = getGlobalSetting(Settings.Global.ADB_WIFI_ENABLED);
+                            value = setting != null ? setting.getValue() : null;
+                            updateGlobalSetting(Settings.Global.ADB_WIFI_ENABLED,
+                                    value, null, true, userId, true);
                         }
                     } finally {
                         Binder.restoreCallingIdentity(identity);
diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
index bf817b1..0f2ee6a 100644
--- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
+++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java
@@ -111,6 +111,7 @@
                     Settings.Global.ADAPTIVE_BATTERY_MANAGEMENT_ENABLED,
                     Settings.Global.ADB_ALLOWED_CONNECTION_TIME,
                     Settings.Global.ADB_ENABLED,
+                    Settings.Global.ADB_WIFI_ENABLED,
                     Settings.Global.ADD_USERS_WHEN_LOCKED,
                     Settings.Global.AIRPLANE_MODE_ON,
                     Settings.Global.AIRPLANE_MODE_RADIOS,
@@ -579,7 +580,8 @@
                     Settings.Global.MODEM_STACK_ENABLED_FOR_SLOT,
                     Settings.Global.POWER_BUTTON_LONG_PRESS,
                     Settings.Global.POWER_BUTTON_VERY_LONG_PRESS,
-                    Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER);
+                    Settings.Global.INTEGRITY_CHECK_INCLUDES_RULE_PROVIDER,
+                    Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT);
 
     private static final Set<String> BACKUP_BLACKLISTED_SECURE_SETTINGS =
              newHashSet(
diff --git a/packages/SystemUI/Android.bp b/packages/SystemUI/Android.bp
index de174b1..e066230 100644
--- a/packages/SystemUI/Android.bp
+++ b/packages/SystemUI/Android.bp
@@ -86,7 +86,9 @@
 
 android_library {
     name: "SystemUI-tests",
-    manifest: "tests/AndroidManifest.xml",
+    manifest: "tests/AndroidManifest-base.xml",
+    additional_manifests: ["tests/AndroidManifest.xml"],
+
     resource_dirs: [
         "tests/res",
         "res-product",
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 5458676e..f141578 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -457,6 +457,25 @@
             android:excludeFromRecents="true">
         </activity>
 
+        <!-- started from WirelessDebuggingManager -->
+        <activity android:name=".wifi.WifiDebuggingActivity"
+            android:permission="android.permission.MANAGE_DEBUGGING"
+            android:theme="@style/Theme.SystemUI.Dialog.Alert"
+            android:finishOnCloseSystemDialogs="true"
+            android:excludeFromRecents="true">
+        </activity>
+        <activity-alias
+            android:name=".WifiDebuggingActivityAlias"
+            android:permission="android.permission.DUMP"
+            android:targetActivity=".wifi.WifiDebuggingActivity"
+            android:exported="true">
+        </activity-alias>
+        <activity android:name=".wifi.WifiDebuggingSecondaryUserActivity"
+            android:theme="@style/Theme.SystemUI.Dialog.Alert"
+            android:finishOnCloseSystemDialogs="true"
+            android:excludeFromRecents="true">
+        </activity>
+
         <!-- started from NetworkPolicyManagerService -->
         <activity
             android:name=".net.NetworkOverLimitActivity"
@@ -696,8 +715,7 @@
         <provider
             android:name="com.android.keyguard.clock.ClockOptionsProvider"
             android:authorities="com.android.keyguard.clock"
-            android:enabled="false"
-            android:exported="false"
+            android:exported="true"
             android:grantUriPermissions="true">
         </provider>
 
diff --git a/packages/SystemUI/res/layout/people_strip.xml b/packages/SystemUI/res/layout/people_strip.xml
index 982aa8e..c2dbaca 100644
--- a/packages/SystemUI/res/layout/people_strip.xml
+++ b/packages/SystemUI/res/layout/people_strip.xml
@@ -19,39 +19,34 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="@dimen/notification_section_header_height"
+    android:paddingStart="4dp"
+    android:paddingEnd="4dp"
     android:focusable="true"
     android:clickable="true"
 >
 
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundNormal"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundDimmed"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
     <LinearLayout
         android:id="@+id/people_list"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:gravity="center"
+        android:layout_marginEnd="8dp"
+        android:gravity="bottom"
         android:orientation="horizontal">
 
-        <TextView
+        <FrameLayout
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:layout_marginStart="@dimen/notification_section_header_padding_left"
-            android:gravity="start"
-            android:textAlignment="gravity"
-            android:text="@string/notification_section_header_conversations"
-            android:textSize="12sp"
-            android:textColor="@color/notification_section_header_label_color"
-            android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-        />
+            android:gravity="start|center_vertical"
+            android:layout_weight="1">
+
+            <TextView
+                style="@style/TextAppearance.NotificationSectionHeaderButton"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:text="@string/notification_section_header_conversations"
+            />
+
+        </FrameLayout>
 
         <ImageView
             android:layout_width="48dp"
@@ -84,16 +79,10 @@
         <ImageView
             android:layout_width="48dp"
             android:layout_height="48dp"
-            android:layout_marginEnd="8dp"
             android:padding="8dp"
             android:scaleType="fitCenter"
         />
 
     </LinearLayout>
 
-    <com.android.systemui.statusbar.notification.FakeShadowView
-        android:id="@+id/fake_shadow"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </com.android.systemui.statusbar.notification.stack.PeopleHubView>
diff --git a/packages/SystemUI/res/layout/qs_carrier.xml b/packages/SystemUI/res/layout/qs_carrier.xml
index 28b2d21..a5b8cfa 100644
--- a/packages/SystemUI/res/layout/qs_carrier.xml
+++ b/packages/SystemUI/res/layout/qs_carrier.xml
@@ -14,7 +14,7 @@
   ~ limitations under the License
   -->
 
-<com.android.systemui.qs.QSCarrier
+<com.android.systemui.qs.carrier.QSCarrier
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/linear_carrier"
     android:layout_width="wrap_content"
@@ -46,4 +46,4 @@
         android:singleLine="true"
         android:maxEms="7"/>
 
-</com.android.systemui.qs.QSCarrier>
\ No newline at end of file
+</com.android.systemui.qs.carrier.QSCarrier>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/qs_carrier_group.xml b/packages/SystemUI/res/layout/qs_carrier_group.xml
index f2b0606..fd53a8b 100644
--- a/packages/SystemUI/res/layout/qs_carrier_group.xml
+++ b/packages/SystemUI/res/layout/qs_carrier_group.xml
@@ -15,7 +15,7 @@
   -->
 
 <!-- Extends LinearLayout -->
-<com.android.systemui.qs.QSCarrierGroup
+<com.android.systemui.qs.carrier.QSCarrierGroup
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/qs_mobile"
     android:layout_width="0dp"
@@ -71,4 +71,4 @@
         android:layout_weight="1"
         android:visibility="gone"/>
 
-</com.android.systemui.qs.QSCarrierGroup>
\ No newline at end of file
+</com.android.systemui.qs.carrier.QSCarrierGroup>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_footer.xml b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
index 174a3b8..36ba66a 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_footer.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_footer.xml
@@ -25,9 +25,9 @@
     <com.android.systemui.statusbar.AlphaOptimizedFrameLayout
         android:id="@+id/content"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content" >
+        android:layout_height="wrap_content">
         <com.android.systemui.statusbar.notification.row.FooterViewButton
-            style="@android:style/Widget.Material.Button.Borderless"
+            style="@style/TextAppearance.NotificationSectionHeaderButton"
             android:id="@+id/manage_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -35,10 +35,9 @@
             android:focusable="true"
             android:contentDescription="@string/accessibility_manage_notification"
             android:text="@string/manage_notifications_text"
-            android:textColor="?attr/wallpaperTextColor"
-            android:textAllCaps="false"/>
+        />
         <com.android.systemui.statusbar.notification.row.FooterViewButton
-            style="@android:style/Widget.Material.Button.Borderless"
+            style="@style/TextAppearance.NotificationSectionHeaderButton"
             android:id="@+id/dismiss_text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
@@ -46,6 +45,6 @@
             android:focusable="true"
             android:contentDescription="@string/accessibility_clear_all"
             android:text="@string/clear_all_notifications_text"
-            android:textColor="?attr/wallpaperTextColor"/>
+        />
     </com.android.systemui.statusbar.AlphaOptimizedFrameLayout>
 </com.android.systemui.statusbar.notification.row.FooterView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
index 508619a..0043d7a 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header.xml
@@ -19,32 +19,21 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="@dimen/notification_section_header_height"
+    android:paddingStart="4dp"
+    android:paddingEnd="4dp"
     android:focusable="true"
     android:clickable="true"
     >
 
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundNormal"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-    <com.android.systemui.statusbar.notification.row.NotificationBackgroundView
-        android:id="@+id/backgroundDimmed"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
     <LinearLayout
         android:id="@+id/content"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom"
         android:gravity="center_vertical"
         android:orientation="horizontal"
         >
         <include layout="@layout/status_bar_notification_section_header_contents"/>
     </LinearLayout>
 
-    <com.android.systemui.statusbar.notification.FakeShadowView
-        android:id="@+id/fake_shadow"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" />
-
 </com.android.systemui.statusbar.notification.stack.SectionHeaderView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
index feabd1c..df4b047 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_section_header_contents.xml
@@ -16,26 +16,30 @@
 
 <!-- Used by both status_bar_notification_header and SectionHeaderView -->
 <merge xmlns:android="http://schemas.android.com/apk/res/android" >
-    <TextView
-        android:id="@+id/header_label"
+    <FrameLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:layout_marginStart="@dimen/notification_section_header_padding_left"
-        android:gravity="start"
-        android:textAlignment="gravity"
-        android:text="@string/notification_section_header_gentle"
-        android:textSize="12sp"
-        android:textColor="@color/notification_section_header_label_color"
-        android:fontFamily="@*android:string/config_headlineFontFamilyMedium"
-    />
+        android:gravity="start|center_vertical"
+        android:layout_weight="1">
+
+        <TextView
+            style="@style/TextAppearance.NotificationSectionHeaderButton"
+            android:id="@+id/header_label"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@string/notification_section_header_gentle"
+        />
+
+    </FrameLayout>
     <ImageView
         android:id="@+id/btn_clear_all"
-        android:layout_width="@dimen/notification_section_header_height"
-        android:layout_height="@dimen/notification_section_header_height"
-        android:layout_marginEnd="4dp"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
         android:src="@drawable/status_bar_notification_section_header_clear_btn"
         android:contentDescription="@string/accessibility_notification_section_header_gentle_clear_all"
         android:scaleType="center"
+        android:tint="?attr/wallpaperTextColor"
+        android:tintMode="src_in"
+        android:visibility="gone"
     />
 </merge>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 15575a4..f9b0666 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -744,7 +744,7 @@
     <!-- The top padding of the clear all button -->
     <dimen name="clear_all_padding_top">12dp</dimen>
 
-    <dimen name="notification_section_header_height">48dp</dimen>
+    <dimen name="notification_section_header_height">56dp</dimen>
     <dimen name="notification_section_header_padding_left">16dp</dimen>
 
     <!-- Largest size an avatar might need to be drawn in the user picker, status bar, or
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5e9feff..4aafec8 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -168,6 +168,24 @@
     <!-- Message of notification shown when trying to enable USB debugging but a secondary user is the current foreground user. -->
     <string name="usb_debugging_secondary_user_message">The user currently signed in to this device can\'t turn on USB debugging. To use this feature, switch to the primary user.</string>
 
+    <!-- Title of confirmation dialog for wireless debugging [CHAR LIMIT=NONE] -->
+    <string name="wifi_debugging_title">Allow wireless debugging on this network?</string>
+
+    <!-- Message of confirmation dialog for wireless debugging [CHAR LIMIT=NONE] -->
+    <string name="wifi_debugging_message">Network Name (SSID)\n<xliff:g id="ssid" example="My wifi">%1$s</xliff:g>\n\nWi\u2011Fi Address (BSSID)\n<xliff:g id="bssid" example="AB:CD:EF:12:34:56">%2$s</xliff:g></string>
+
+    <!-- Option to always allow wireless debugging on this network [CHAR LIMIT=NONE] -->
+    <string name="wifi_debugging_always">Always allow on this network</string>
+
+    <!-- Button label for confirming acceptance of enabling wireless debugging [CHAR LIMIT=15] -->
+    <string name="wifi_debugging_allow">Allow</string>
+
+    <!-- Title of notification shown when trying to enable wireless debugging but a secondary user is the current foreground user. [CHAR LIMIT=NONE] -->
+    <string name="wifi_debugging_secondary_user_title">Wireless debugging not allowed</string>
+
+    <!-- Message of notification shown when trying to enable wireless debugging but a secondary user is the current foreground user. [CHAR LIMIT=NONE] -->
+    <string name="wifi_debugging_secondary_user_message">The user currently signed in to this device can\u2019t turn on wireless debugging. To use this feature, switch to the primary user.</string>
+
     <!-- Title of USB contaminant presence dialog [CHAR LIMIT=NONE] -->
     <string name="usb_contaminant_title">USB port disabled</string>
 
@@ -1204,6 +1222,9 @@
     <!-- Section title for notifications that do not vibrate or make noise. [CHAR LIMIT=40] -->
     <string name="notification_section_header_gentle">Silent notifications</string>
 
+    <!-- Section title for notifications that vibrate or make noise. [CHAR LIMIT=40] -->
+    <string name="notification_section_header_alerting">Alerting notifications</string>
+
     <!-- Section title for conversational notifications. [CHAR LIMIT=40] -->
     <string name="notification_section_header_conversations">Conversations</string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 557e2d6..36c4526 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -554,6 +554,14 @@
         <item name="android:gravity">center</item>
     </style>
 
+    <style
+        name="TextAppearance.NotificationSectionHeaderButton"
+        parent="@android:style/Widget.Material.Button.Borderless">
+        <item name="android:textColor">?attr/wallpaperTextColor</item>
+        <item name="android:textAllCaps">false</item>
+        <item name="android:textSize">16sp</item>
+    </style>
+
     <style name="TextAppearance.HeadsUpStatusBarText"
            parent="@*android:style/TextAppearance.DeviceDefault.Notification.Info">
     </style>
@@ -661,5 +669,5 @@
         <item name="android:textSize">12sp</item>
         <item name="android:textColor">@color/control_secondary_text</item>
     </style>
-
+    
 </resources>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
index 2d288ff..b1d39f5 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/ISystemUiProxy.aidl
@@ -123,4 +123,9 @@
      */
      void handleImageAsScreenshot(in Bitmap screenImage, in Rect locationInScreen,
               in Insets visibleInsets, int taskId) = 21;
+
+    /**
+     * Sets the split-screen divider minimized state
+     */
+    void setSplitScreenMinimized(boolean minimized) = 22;
 }
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
index e80b437..7dcf4b0 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/SyncRtSurfaceTransactionApplierCompat.java
@@ -24,6 +24,7 @@
 import android.os.Message;
 import android.os.Trace;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewRootImpl;
 
@@ -39,7 +40,7 @@
 
     private static final int MSG_UPDATE_SEQUENCE_NUMBER = 0;
 
-    private final Surface mTargetSurface;
+    private final SurfaceControl mBarrierSurfaceControl;
     private final ViewRootImpl mTargetViewRootImpl;
     private final Handler mApplyHandler;
 
@@ -52,7 +53,8 @@
      */
     public SyncRtSurfaceTransactionApplierCompat(View targetView) {
         mTargetViewRootImpl = targetView != null ? targetView.getViewRootImpl() : null;
-        mTargetSurface = mTargetViewRootImpl != null ? mTargetViewRootImpl.mSurface : null;
+        mBarrierSurfaceControl = mTargetViewRootImpl != null
+            ? mTargetViewRootImpl.getRenderSurfaceControl() : null;
 
         mApplyHandler = new Handler(new Callback() {
             @Override
@@ -91,7 +93,7 @@
         mTargetViewRootImpl.registerRtFrameCallback(new HardwareRenderer.FrameDrawingCallback() {
             @Override
             public void onFrameDraw(long frame) {
-                if (mTargetSurface == null || !mTargetSurface.isValid()) {
+                if (mBarrierSurfaceControl == null || !mBarrierSurfaceControl.isValid()) {
                     Message.obtain(mApplyHandler, MSG_UPDATE_SEQUENCE_NUMBER, toApplySeqNo, 0)
                             .sendToTarget();
                     return;
@@ -102,7 +104,7 @@
                     SyncRtSurfaceTransactionApplierCompat.SurfaceParams surfaceParams =
                             params[i];
                     SurfaceControlCompat surface = surfaceParams.surface;
-                    t.deferTransactionUntil(surface, mTargetSurface, frame);
+                    t.deferTransactionUntil(surface, mBarrierSurfaceControl, frame);
                     applyParams(t, surfaceParams);
                 }
                 t.setEarlyWakeup();
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
index 073688b..8f4926f 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/TransactionCompat.java
@@ -20,6 +20,7 @@
 import android.graphics.Rect;
 import android.view.Surface;
 import android.view.SurfaceControl.Transaction;
+import android.view.SurfaceControl;
 
 public class TransactionCompat {
 
@@ -87,8 +88,8 @@
     }
 
     public TransactionCompat deferTransactionUntil(SurfaceControlCompat surfaceControl,
-            Surface barrier, long frameNumber) {
-        mTransaction.deferTransactionUntilSurface(surfaceControl.mSurfaceControl, barrier,
+            SurfaceControl barrier, long frameNumber) {
+        mTransaction.deferTransactionUntil(surfaceControl.mSurfaceControl, barrier,
                 frameNumber);
         return this;
     }
@@ -102,4 +103,4 @@
         mTransaction.setColor(surfaceControl.mSurfaceControl, color);
         return this;
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index e475ef1..6f06f69 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -51,7 +51,7 @@
 public class KeyguardClockSwitch extends RelativeLayout {
 
     private static final String TAG = "KeyguardClockSwitch";
-    private static final boolean CUSTOM_CLOCKS_ENABLED = false;
+    private static final boolean CUSTOM_CLOCKS_ENABLED = true;
 
     /**
      * Animation fraction when text is transitioned to/from bold.
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
index 571c4ae..11bf24d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -72,11 +72,12 @@
         @Override
         public void onDisplayChanged(int displayId) {
             if (displayId == DEFAULT_DISPLAY) return;
-            final Display display = mDisplayService.getDisplay(displayId);
-            if (display != null && mShowing) {
-                final Presentation presentation = mPresentations.get(displayId);
-                if (presentation != null && !presentation.getDisplay().equals(display)) {
-                    hidePresentation(displayId);
+            final Presentation presentation = mPresentations.get(displayId);
+            if (presentation != null && mShowing) {
+                hidePresentation(displayId);
+                // update DisplayInfo.
+                final Display display = mDisplayService.getDisplay(displayId);
+                if (display != null) {
                     showPresentation(display);
                 }
             }
@@ -266,6 +267,11 @@
         }
 
         @Override
+        public void cancel() {
+            // Do not allow anything to cancel KeyguardPresetation except KeyguardDisplayManager.
+        }
+
+        @Override
         public void onDetachedFromWindow() {
             mClock.removeCallbacks(mMoveTextRunnable);
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
index 09d4d5f..20b1e0d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSecurityView.java
@@ -57,6 +57,12 @@
     int PROMPT_REASON_PREPARE_FOR_UPDATE = 6;
 
     /**
+     * Primary auth is required because the user uses weak/convenience biometrics and hasn't used
+     * primary auth since a while
+     */
+    int PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT = 7;
+
+    /**
      * Interface back to keyguard to tell it when security
      * @param callback
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 61caf3b..241f96e 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -149,7 +149,7 @@
                             new WindowlessWindowManager(context.getResources().getConfiguration(),
                                     surfaceControl, input);
                     mUniversalSmartspaceViewHost = new SurfaceControlViewHost(context,
-                            context.getDisplay(), windowlessWindowManager);
+                            context.getDisplayNoVerify(), windowlessWindowManager);
                     WindowManager.LayoutParams layoutParams =
                             new WindowManager.LayoutParams(
                                     surfaceControl.getWidth(),
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index e5f6d3c..52ea300 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -80,6 +80,7 @@
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.util.Log;
+import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -91,10 +92,12 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.util.Assert;
 
 import com.google.android.collect.Lists;
 
@@ -107,6 +110,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.TimeZone;
+import java.util.concurrent.Executor;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -263,6 +267,7 @@
     // If the user long pressed the lock icon, disabling face auth for the current session.
     private boolean mLockIconPressed;
     private int mActiveMobileDataSubscription = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+    private final Executor mBackgroundExecutor;
 
     /**
      * Short delay before restarting biometric authentication after a successful try
@@ -319,12 +324,22 @@
                 }
             };
 
+    private class BiometricAuthenticated {
+        private final boolean mAuthenticated;
+        private final boolean mIsStrongBiometric;
+
+        BiometricAuthenticated(boolean authenticated, boolean isStrongBiometric) {
+            this.mAuthenticated = authenticated;
+            this.mIsStrongBiometric = isStrongBiometric;
+        }
+    }
+
     private SparseBooleanArray mUserIsUnlocked = new SparseBooleanArray();
     private SparseBooleanArray mUserHasTrust = new SparseBooleanArray();
     private SparseBooleanArray mUserTrustIsManaged = new SparseBooleanArray();
     private SparseBooleanArray mUserTrustIsUsuallyManaged = new SparseBooleanArray();
-    private SparseBooleanArray mUserFingerprintAuthenticated = new SparseBooleanArray();
-    private SparseBooleanArray mUserFaceAuthenticated = new SparseBooleanArray();
+    private SparseArray<BiometricAuthenticated> mUserFingerprintAuthenticated = new SparseArray<>();
+    private SparseArray<BiometricAuthenticated> mUserFaceAuthenticated = new SparseArray<>();
     private SparseBooleanArray mUserFaceUnlockRunning = new SparseBooleanArray();
     private Map<Integer, Intent> mSecondaryLockscreenRequirement = new HashMap<Integer, Intent>();
 
@@ -341,7 +356,7 @@
 
     @Override
     public void onTrustChanged(boolean enabled, int userId, int flags) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserHasTrust.put(userId, enabled);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -360,7 +375,7 @@
     }
 
     private void handleSimSubscriptionInfoChanged() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG_SIM_STATES) {
             Log.v(TAG, "onSubscriptionInfoChanged()");
             List<SubscriptionInfo> sil = mSubscriptionManager
@@ -403,7 +418,7 @@
     }
 
     private void callbacksRefreshCarrierInfo() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -466,7 +481,7 @@
 
     @Override
     public void onTrustManagedChanged(boolean managed, int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserTrustIsManaged.put(userId, managed);
         mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -522,10 +537,11 @@
     }
 
     @VisibleForTesting
-    protected void onFingerprintAuthenticated(int userId) {
-        checkIsHandlerThread();
+    protected void onFingerprintAuthenticated(int userId, boolean isStrongBiometric) {
+        Assert.isMainThread();
         Trace.beginSection("KeyGuardUpdateMonitor#onFingerPrintAuthenticated");
-        mUserFingerprintAuthenticated.put(userId, true);
+        mUserFingerprintAuthenticated.put(userId,
+                new BiometricAuthenticated(true, isStrongBiometric));
         // Update/refresh trust state only if user can skip bouncer
         if (getUserCanSkipBouncer(userId)) {
             mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FINGERPRINT);
@@ -535,7 +551,8 @@
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
-                cb.onBiometricAuthenticated(userId, BiometricSourceType.FINGERPRINT);
+                cb.onBiometricAuthenticated(userId, BiometricSourceType.FINGERPRINT,
+                        isStrongBiometric);
             }
         }
 
@@ -545,11 +562,23 @@
         // Only authenticate fingerprint once when assistant is visible
         mAssistantVisible = false;
 
+        // Report unlock with strong or non-strong biometric
+        reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+
         Trace.endSection();
     }
 
+    private void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
+        mBackgroundExecutor.execute(new Runnable() {
+            @Override
+            public void run() {
+                mLockPatternUtils.reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+            }
+        });
+    }
+
     private void handleFingerprintAuthFailed() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -561,7 +590,7 @@
     }
 
     private void handleFingerprintAcquired(int acquireInfo) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (acquireInfo != FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
             return;
         }
@@ -573,7 +602,7 @@
         }
     }
 
-    private void handleFingerprintAuthenticated(int authUserId) {
+    private void handleFingerprintAuthenticated(int authUserId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#handlerFingerPrintAuthenticated");
         try {
             final int userId;
@@ -591,7 +620,7 @@
                 Log.d(TAG, "Fingerprint disabled by DPM for userId: " + userId);
                 return;
             }
-            onFingerprintAuthenticated(userId);
+            onFingerprintAuthenticated(userId, isStrongBiometric);
         } finally {
             setFingerprintRunningState(BIOMETRIC_STATE_STOPPED);
         }
@@ -599,7 +628,7 @@
     }
 
     private void handleFingerprintHelp(int msgId, String helpString) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -618,7 +647,7 @@
     };
 
     private void handleFingerprintError(int msgId, String errString) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED && mHandler.hasCallbacks(
                 mCancelNotReceived)) {
             mHandler.removeCallbacks(mCancelNotReceived);
@@ -671,7 +700,7 @@
     }
 
     private void notifyFingerprintRunningStateChanged() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -682,10 +711,11 @@
     }
 
     @VisibleForTesting
-    protected void onFaceAuthenticated(int userId) {
+    protected void onFaceAuthenticated(int userId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#onFaceAuthenticated");
-        checkIsHandlerThread();
-        mUserFaceAuthenticated.put(userId, true);
+        Assert.isMainThread();
+        mUserFaceAuthenticated.put(userId,
+                new BiometricAuthenticated(true, isStrongBiometric));
         // Update/refresh trust state only if user can skip bouncer
         if (getUserCanSkipBouncer(userId)) {
             mTrustManager.unlockedByBiometricForUser(userId, BiometricSourceType.FACE);
@@ -696,7 +726,8 @@
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
                 cb.onBiometricAuthenticated(userId,
-                        BiometricSourceType.FACE);
+                        BiometricSourceType.FACE,
+                        isStrongBiometric);
             }
         }
 
@@ -706,11 +737,14 @@
         // Only authenticate face once when assistant is visible
         mAssistantVisible = false;
 
+        // Report unlock with strong or non-strong biometric
+        reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+
         Trace.endSection();
     }
 
     private void handleFaceAuthFailed() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         setFaceRunningState(BIOMETRIC_STATE_STOPPED);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -723,7 +757,7 @@
     }
 
     private void handleFaceAcquired(int acquireInfo) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (acquireInfo != FaceManager.FACE_ACQUIRED_GOOD) {
             return;
         }
@@ -736,7 +770,7 @@
         }
     }
 
-    private void handleFaceAuthenticated(int authUserId) {
+    private void handleFaceAuthenticated(int authUserId, boolean isStrongBiometric) {
         Trace.beginSection("KeyGuardUpdateMonitor#handlerFaceAuthenticated");
         try {
             if (mGoingToSleep) {
@@ -759,7 +793,7 @@
                 return;
             }
             if (DEBUG_FACE) Log.d(TAG, "Face auth succeeded for user " + userId);
-            onFaceAuthenticated(userId);
+            onFaceAuthenticated(userId, isStrongBiometric);
         } finally {
             setFaceRunningState(BIOMETRIC_STATE_STOPPED);
         }
@@ -767,7 +801,7 @@
     }
 
     private void handleFaceHelp(int msgId, String helpString) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG_FACE) Log.d(TAG, "Face help received: " + helpString);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -787,7 +821,7 @@
     };
 
     private void handleFaceError(int msgId, String errString) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG_FACE) Log.d(TAG, "Face error received: " + errString);
         if (msgId == FaceManager.FACE_ERROR_CANCELED && mHandler.hasCallbacks(mCancelNotReceived)) {
             mHandler.removeCallbacks(mCancelNotReceived);
@@ -842,7 +876,7 @@
     }
 
     private void notifyFaceRunningStateChanged() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -853,7 +887,7 @@
     }
 
     private void handleFaceUnlockStateChanged(boolean running, int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserFaceUnlockRunning.put(userId, running);
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -913,9 +947,13 @@
      * Returns whether the user is unlocked with biometrics.
      */
     public boolean getUserUnlockedWithBiometric(int userId) {
-        boolean fingerprintOrFace = mUserFingerprintAuthenticated.get(userId)
-                || mUserFaceAuthenticated.get(userId);
-        return fingerprintOrFace && isUnlockingWithBiometricAllowed();
+        BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
+        BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
+        boolean fingerprintAllowed = fingerprint != null && fingerprint.mAuthenticated
+                && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric);
+        boolean faceAllowed = face != null && face.mAuthenticated
+                && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric);
+        return fingerprintAllowed || faceAllowed;
     }
 
     public boolean getUserTrustIsManaged(int userId) {
@@ -965,12 +1003,12 @@
      * Cached version of {@link TrustManager#isTrustUsuallyManaged(int)}.
      */
     public boolean isTrustUsuallyManaged(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         return mUserTrustIsUsuallyManaged.get(userId);
     }
 
-    public boolean isUnlockingWithBiometricAllowed() {
-        return mStrongAuthTracker.isUnlockingWithBiometricAllowed();
+    public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
+        return mStrongAuthTracker.isUnlockingWithBiometricAllowed(isStrongBiometric);
     }
 
     public boolean isUserInLockdown(int userId) {
@@ -996,7 +1034,7 @@
     }
 
     private void notifyStrongAuthStateChanged(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -1010,7 +1048,7 @@
     }
 
     private void dispatchErrorMessage(CharSequence message) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -1168,7 +1206,7 @@
         @Override
         public void onAuthenticationSucceeded(AuthenticationResult result) {
             Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
-            handleFingerprintAuthenticated(result.getUserId());
+            handleFingerprintAuthenticated(result.getUserId(), result.isStrongBiometric());
             Trace.endSection();
         }
 
@@ -1200,7 +1238,7 @@
         @Override
         public void onAuthenticationSucceeded(FaceManager.AuthenticationResult result) {
             Trace.beginSection("KeyguardUpdateMonitor#onAuthenticationSucceeded");
-            handleFaceAuthenticated(result.getUserId());
+            handleFaceAuthenticated(result.getUserId(), result.isStrongBiometric());
             Trace.endSection();
         }
 
@@ -1304,9 +1342,9 @@
             mStrongAuthRequiredChangedCallback = strongAuthRequiredChangedCallback;
         }
 
-        public boolean isUnlockingWithBiometricAllowed() {
+        public boolean isUnlockingWithBiometricAllowed(boolean isStrongBiometric) {
             int userId = getCurrentUser();
-            return isBiometricAllowedForUser(userId);
+            return isBiometricAllowedForUser(isStrongBiometric, userId);
         }
 
         public boolean hasUserAuthenticatedSinceBoot() {
@@ -1323,7 +1361,7 @@
 
     protected void handleStartedWakingUp() {
         Trace.beginSection("KeyguardUpdateMonitor#handleStartedWakingUp");
-        checkIsHandlerThread();
+        Assert.isMainThread();
         updateBiometricListeningState();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1335,7 +1373,7 @@
     }
 
     protected void handleStartedGoingToSleep(int arg1) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mLockIconPressed = false;
         clearBiometricRecognized();
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1349,7 +1387,7 @@
     }
 
     protected void handleFinishedGoingToSleep(int arg1) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mGoingToSleep = false;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1361,7 +1399,7 @@
     }
 
     private void handleScreenTurnedOn() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -1373,7 +1411,7 @@
     private void handleScreenTurnedOff() {
         final String tag = "KeyguardUpdateMonitor#handleScreenTurnedOff";
         DejankUtils.startDetectingBlockingIpcs(tag);
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mHardwareFingerprintUnavailableRetryCount = 0;
         mHardwareFaceUnavailableRetryCount = 0;
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1386,7 +1424,7 @@
     }
 
     private void handleDreamingStateChanged(int dreamStart) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mIsDreaming = dreamStart == 1;
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -1398,7 +1436,7 @@
     }
 
     private void handleUserInfoChanged(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -1408,7 +1446,7 @@
     }
 
     private void handleUserUnlocked(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserIsUnlocked.put(userId, true);
         mNeedsSlowUnlockTransition = resolveNeedsSlowUnlockTransition();
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1420,27 +1458,31 @@
     }
 
     private void handleUserStopped(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserIsUnlocked.put(userId, mUserManager.isUserUnlocked(userId));
     }
 
     @VisibleForTesting
     void handleUserRemoved(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserIsUnlocked.delete(userId);
         mUserTrustIsUsuallyManaged.delete(userId);
     }
 
     @VisibleForTesting
     @Inject
-    protected KeyguardUpdateMonitor(Context context, @Main Looper mainLooper,
+    protected KeyguardUpdateMonitor(
+            Context context,
+            @Main Looper mainLooper,
             BroadcastDispatcher broadcastDispatcher,
-            DumpController dumpController) {
+            DumpController dumpController,
+            @Background Executor backgroundExecutor) {
         mContext = context;
         mSubscriptionManager = SubscriptionManager.from(context);
         mDeviceProvisioned = isDeviceProvisionedInSettingsDb();
         mStrongAuthTracker = new StrongAuthTracker(context, this::notifyStrongAuthStateChanged);
         dumpController.registerDumpable(this);
+        mBackgroundExecutor = backgroundExecutor;
 
         mHandler = new Handler(mainLooper) {
             @Override
@@ -1750,14 +1792,16 @@
     }
 
     private boolean shouldListenForFingerprintAssistant() {
+        BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(getCurrentUser());
         return mAssistantVisible && mKeyguardOccluded
-                && !mUserFingerprintAuthenticated.get(getCurrentUser(), false)
+                && !(fingerprint != null && fingerprint.mAuthenticated)
                 && !mUserHasTrust.get(getCurrentUser(), false);
     }
 
     private boolean shouldListenForFaceAssistant() {
+        BiometricAuthenticated face = mUserFaceAuthenticated.get(getCurrentUser());
         return mAssistantVisible && mKeyguardOccluded
-                && !mUserFaceAuthenticated.get(getCurrentUser(), false)
+                && !(face != null && face.mAuthenticated)
                 && !mUserHasTrust.get(getCurrentUser(), false);
     }
 
@@ -1814,7 +1858,7 @@
     public void onLockIconPressed() {
         mLockIconPressed = true;
         final int userId = getCurrentUser();
-        mUserFaceAuthenticated.put(userId, false);
+        mUserFaceAuthenticated.put(userId, null);
         updateFaceListeningState();
         mStrongAuthTracker.onStrongAuthRequiredChanged(userId);
     }
@@ -1962,7 +2006,7 @@
      * @param hasLockscreenWallpaper Whether Keyguard has a lockscreen wallpaper.
      */
     public void setHasLockscreenWallpaper(boolean hasLockscreenWallpaper) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (hasLockscreenWallpaper != mHasLockscreenWallpaper) {
             mHasLockscreenWallpaper = hasLockscreenWallpaper;
             for (int i = 0; i < mCallbacks.size(); i++) {
@@ -1985,7 +2029,7 @@
      * Handle {@link #MSG_DPM_STATE_CHANGED}
      */
     private void handleDevicePolicyManagerStateChanged(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         updateFingerprintListeningState();
         updateSecondaryLockscreenRequirement(userId);
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -2000,7 +2044,7 @@
      * Handle {@link #MSG_USER_SWITCHING}
      */
     private void handleUserSwitching(int userId, IRemoteCallback reply) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserTrustIsUsuallyManaged.put(userId, mTrustManager.isTrustUsuallyManaged(userId));
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -2018,7 +2062,7 @@
      * Handle {@link #MSG_USER_SWITCH_COMPLETE}
      */
     private void handleUserSwitchComplete(int userId) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -2031,7 +2075,7 @@
      * Handle {@link #MSG_DEVICE_PROVISIONED}
      */
     private void handleDeviceProvisioned() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -2049,7 +2093,7 @@
      * Handle {@link #MSG_PHONE_STATE_CHANGED}
      */
     private void handlePhoneStateChanged(String newState) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handlePhoneStateChanged(" + newState + ")");
         if (TelephonyManager.EXTRA_STATE_IDLE.equals(newState)) {
             mPhoneState = TelephonyManager.CALL_STATE_IDLE;
@@ -2070,7 +2114,7 @@
      * Handle {@link #MSG_RINGER_MODE_CHANGED}
      */
     private void handleRingerModeChange(int mode) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handleRingerModeChange(" + mode + ")");
         mRingMode = mode;
         for (int i = 0; i < mCallbacks.size(); i++) {
@@ -2085,7 +2129,7 @@
      * Handle {@link #MSG_TIME_UPDATE}
      */
     private void handleTimeUpdate() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handleTimeUpdate");
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -2099,7 +2143,7 @@
      * Handle (@line #MSG_TIMEZONE_UPDATE}
      */
     private void handleTimeZoneUpdate(String timeZone) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handleTimeZoneUpdate");
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
@@ -2115,7 +2159,7 @@
      * Handle {@link #MSG_BATTERY_UPDATE}
      */
     private void handleBatteryUpdate(BatteryStatus status) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handleBatteryUpdate");
         final boolean batteryUpdateInteresting = isBatteryUpdateInteresting(mBatteryStatus, status);
         mBatteryStatus = status;
@@ -2134,7 +2178,7 @@
      */
     @VisibleForTesting
     void updateTelephonyCapable(boolean capable) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (capable == mTelephonyCapable) {
             return;
         }
@@ -2152,7 +2196,7 @@
      */
     @VisibleForTesting
     void handleSimStateChange(int subId, int slotId, int state) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG_SIM_STATES) {
             Log.d(TAG, "handleSimStateChange(subId=" + subId + ", slotId="
                     + slotId + ", state=" + state + ")");
@@ -2236,7 +2280,7 @@
      * <p>Needs to be called from the main thread.
      */
     public void onKeyguardVisibilityChanged(boolean showing) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         Log.d(TAG, "onKeyguardVisibilityChanged(" + showing + ")");
         mKeyguardIsVisible = showing;
 
@@ -2279,7 +2323,7 @@
      * @see #sendKeyguardBouncerChanged(boolean)
      */
     private void handleKeyguardBouncerChanged(int bouncer) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.d(TAG, "handleKeyguardBouncerChanged(" + bouncer + ")");
         boolean isBouncer = (bouncer == 1);
         mBouncer = isBouncer;
@@ -2305,7 +2349,7 @@
      * Handle {@link #MSG_REPORT_EMERGENCY_CALL_ACTION}
      */
     private void handleReportEmergencyCallAction() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         for (int i = 0; i < mCallbacks.size(); i++) {
             KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
             if (cb != null) {
@@ -2344,7 +2388,7 @@
      * @param callback The callback to remove
      */
     public void removeCallback(KeyguardUpdateMonitorCallback callback) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) {
             Log.v(TAG, "*** unregister callback for " + callback);
         }
@@ -2359,7 +2403,7 @@
      * @param callback The callback to register
      */
     public void registerCallback(KeyguardUpdateMonitorCallback callback) {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         if (DEBUG) Log.v(TAG, "*** register callback for " + callback);
         // Prevent adding duplicate callbacks
 
@@ -2448,7 +2492,7 @@
         if (!bypassHandler) {
             mHandler.obtainMessage(MSG_REPORT_EMERGENCY_CALL_ACTION).sendToTarget();
         } else {
-            checkIsHandlerThread();
+            Assert.isMainThread();
             handleReportEmergencyCallAction();
         }
     }
@@ -2466,7 +2510,7 @@
     }
 
     public void clearBiometricRecognized() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         mUserFingerprintAuthenticated.clear();
         mUserFaceAuthenticated.clear();
         mTrustManager.clearAllBiometricRecognized(BiometricSourceType.FINGERPRINT);
@@ -2653,7 +2697,7 @@
     }
 
     private void updateLogoutEnabled() {
-        checkIsHandlerThread();
+        Assert.isMainThread();
         boolean logoutEnabled = mDevicePolicyManager.isLogoutEnabled();
         if (mLogoutEnabled != logoutEnabled) {
             mLogoutEnabled = logoutEnabled;
@@ -2667,13 +2711,6 @@
         }
     }
 
-    private void checkIsHandlerThread() {
-        if (!mHandler.getLooper().isCurrentThread()) {
-            Log.wtfStack(TAG, "must call on mHandler's thread "
-                    + mHandler.getLooper().getThread() + ", not " + Thread.currentThread());
-        }
-    }
-
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardUpdateMonitor state:");
@@ -2695,9 +2732,11 @@
         if (mFpm != null && mFpm.isHardwareDetected()) {
             final int userId = ActivityManager.getCurrentUser();
             final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
+            BiometricAuthenticated fingerprint = mUserFingerprintAuthenticated.get(userId);
             pw.println("  Fingerprint state (user=" + userId + ")");
-            pw.println("    allowed=" + isUnlockingWithBiometricAllowed());
-            pw.println("    auth'd=" + mUserFingerprintAuthenticated.get(userId));
+            pw.println("    allowed=" + fingerprint != null
+                    && isUnlockingWithBiometricAllowed(fingerprint.mIsStrongBiometric));
+            pw.println("    auth'd=" + fingerprint != null && fingerprint.mAuthenticated);
             pw.println("    authSinceBoot="
                     + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
             pw.println("    disabled(DPM)=" + isFingerprintDisabled(userId));
@@ -2710,9 +2749,11 @@
         if (mFaceManager != null && mFaceManager.isHardwareDetected()) {
             final int userId = ActivityManager.getCurrentUser();
             final int strongAuthFlags = mStrongAuthTracker.getStrongAuthForUser(userId);
+            BiometricAuthenticated face = mUserFaceAuthenticated.get(userId);
             pw.println("  Face authentication state (user=" + userId + ")");
-            pw.println("    allowed=" + isUnlockingWithBiometricAllowed());
-            pw.println("    auth'd=" + mUserFaceAuthenticated.get(userId));
+            pw.println("    allowed=" + face != null
+                    && isUnlockingWithBiometricAllowed(face.mIsStrongBiometric));
+            pw.println("    auth'd=" + face != null && face.mAuthenticated);
             pw.println("    authSinceBoot="
                     + getStrongAuthTracker().hasUserAuthenticatedSinceBoot());
             pw.println("    disabled(DPM)=" + isFaceDisabled(userId));
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 49f72a9..12e0ecd 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -239,7 +239,8 @@
      * @param userId the user id for which the biometric sample was authenticated
      * @param biometricSourceType
      */
-    public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) { }
+    public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) { }
 
     /**
      * Called when biometric authentication provides help string (e.g. "Try again")
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 9cd4aec..0367464 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -149,8 +149,6 @@
         LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context));
 
         addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
-        addBuiltinClock(() -> new BubbleClockController(res, layoutInflater, colorExtractor));
-        addBuiltinClock(() -> new AnalogClockController(res, layoutInflater, colorExtractor));
 
         // Store the size of the display for generation of clock preview.
         DisplayMetrics dm = res.getDisplayMetrics();
@@ -211,7 +209,8 @@
         return mContentObserver;
     }
 
-    private void addBuiltinClock(Supplier<ClockPlugin> pluginSupplier) {
+    @VisibleForTesting
+    void addBuiltinClock(Supplier<ClockPlugin> pluginSupplier) {
         ClockPlugin plugin = pluginSupplier.get();
         mPreviewClocks.addClockPlugin(plugin);
         mBuiltinClocks.add(pluginSupplier);
diff --git a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
index 8503396..85ce313 100644
--- a/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
+++ b/packages/SystemUI/src/com/android/systemui/CornerHandleView.java
@@ -57,7 +57,6 @@
         mPaint.setStyle(Paint.Style.STROKE);
         mPaint.setStrokeCap(Paint.Cap.ROUND);
         mPaint.setStrokeWidth(getStrokePx());
-        setLayerType(View.LAYER_TYPE_SOFTWARE, mPaint);
 
         final int dualToneDarkTheme = Utils.getThemeAttr(mContext, R.attr.darkIconTheme);
         final int dualToneLightTheme = Utils.getThemeAttr(mContext, R.attr.lightIconTheme);
@@ -118,14 +117,8 @@
         // Handle color is same as home handle color.
         int color = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
                 mLightColor, mDarkColor);
-        // Shadow color is inverse of handle color.
-        int shadowColor = (int) ArgbEvaluator.getInstance().evaluate(darkIntensity,
-                mDarkColor, mLightColor);
         if (mPaint.getColor() != color) {
             mPaint.setColor(color);
-            mPaint.setShadowLayer(/** radius */ getResources().getDimensionPixelSize(
-                    com.android.internal.R.dimen.assist_handle_shadow_radius), /** shadowDx */ 0,
-                    /** shadowDy */ 0, /** color */ shadowColor);
             if (getVisibility() == VISIBLE && getAlpha() > 0) {
                 invalidate();
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index d317b7e..69bc259 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -60,6 +60,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.DevicePolicyManagerWrapper;
 import com.android.systemui.shared.system.PackageManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.NotificationListener;
@@ -327,6 +328,7 @@
     @Inject Lazy<DisplayImeController> mDisplayImeController;
     @Inject Lazy<RecordingController> mRecordingController;
     @Inject Lazy<ProtoTracer> mProtoTracer;
+    @Inject Lazy<Divider> mDivider;
 
     @Inject
     public Dependency() {
@@ -527,6 +529,7 @@
         mProviders.put(AutoHideController.class, mAutoHideController::get);
 
         mProviders.put(RecordingController.class, mRecordingController::get);
+        mProviders.put(Divider.class, mDivider::get);
 
         sDependency = this;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java b/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
deleted file mode 100644
index 5c0df17..0000000
--- a/packages/SystemUI/src/com/android/systemui/DockedStackExistsListener.java
+++ /dev/null
@@ -1,92 +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.systemui;
-
-import android.os.RemoteException;
-import android.util.Log;
-import android.view.IDockedStackListener;
-import android.view.WindowManagerGlobal;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.function.Consumer;
-
-/**
- * Utility wrapper to listen for whether or not a docked stack exists, to be
- * used for things like the different overview icon in that mode.
- */
-public class DockedStackExistsListener {
-
-    private static final String TAG = "DockedStackExistsListener";
-
-    private static ArrayList<WeakReference<Consumer<Boolean>>> sCallbacks = new ArrayList<>();
-    private static boolean mLastExists;
-
-    static {
-        try {
-            WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
-                    new IDockedStackListener.Stub() {
-                        @Override
-                        public void onDividerVisibilityChanged(boolean b) throws RemoteException {
-
-                        }
-
-                        @Override
-                        public void onDockedStackExistsChanged(boolean exists)
-                                throws RemoteException {
-                            DockedStackExistsListener.onDockedStackExistsChanged(exists);
-                        }
-
-                        @Override
-                        public void onDockedStackMinimizedChanged(boolean b, long l, boolean b1)
-                                throws RemoteException {
-
-                        }
-
-                        @Override
-                        public void onAdjustedForImeChanged(boolean b, long l)
-                                throws RemoteException {
-
-                        }
-
-                        @Override
-                        public void onDockSideChanged(int i) throws RemoteException {
-
-                        }
-                    });
-        } catch (RemoteException e) {
-            Log.e(TAG, "Failed registering docked stack exists listener", e);
-        }
-    }
-
-
-    private static void onDockedStackExistsChanged(boolean exists) {
-        mLastExists = exists;
-        synchronized (sCallbacks) {
-            sCallbacks.removeIf(wf -> {
-                Consumer<Boolean> l = wf.get();
-                if (l != null) l.accept(exists);
-                return l == null;
-            });
-        }
-    }
-
-    public static void register(Consumer<Boolean> callback) {
-        callback.accept(mLastExists);
-        synchronized (sCallbacks) {
-            sCallbacks.add(new WeakReference<>(callback));
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/LatencyTester.java b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
index 1a47dac..dc0cb03 100644
--- a/packages/SystemUI/src/com/android/systemui/LatencyTester.java
+++ b/packages/SystemUI/src/com/android/systemui/LatencyTester.java
@@ -96,6 +96,7 @@
     private void fakeWakeAndUnlock() {
         mBiometricUnlockController.onBiometricAcquired(BiometricSourceType.FINGERPRINT);
         mBiometricUnlockController.onBiometricAuthenticated(
-                KeyguardUpdateMonitor.getCurrentUser(), BiometricSourceType.FINGERPRINT);
+                KeyguardUpdateMonitor.getCurrentUser(), BiometricSourceType.FINGERPRINT,
+                true /* isStrongBiometric */);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index c9104dc..6ce6353 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -96,6 +96,7 @@
     private static final boolean DEBUG_SCREENSHOT_ROUNDED_CORNERS =
             SystemProperties.getBoolean("debug.screenshot_rounded_corners", false);
     private static final boolean VERBOSE = false;
+    private static final boolean DEBUG_COLOR = DEBUG_SCREENSHOT_ROUNDED_CORNERS;
 
     private DisplayManager mDisplayManager;
     private boolean mIsRegistered;
@@ -454,6 +455,9 @@
 
     private void updateColorInversion(int colorsInvertedValue) {
         int tint = colorsInvertedValue != 0 ? Color.WHITE : Color.BLACK;
+        if (DEBUG_COLOR) {
+            tint = Color.RED;
+        }
         ColorStateList tintList = ColorStateList.valueOf(tint);
 
         if (mOverlays == null) {
diff --git a/packages/SystemUI/src/com/android/systemui/TransactionPool.java b/packages/SystemUI/src/com/android/systemui/TransactionPool.java
new file mode 100644
index 0000000..801cf8a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/TransactionPool.java
@@ -0,0 +1,55 @@
+/*
+ * 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.systemui;
+
+import android.util.Pools;
+import android.view.SurfaceControl;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+/**
+ * Provides a synchronized pool of {@link SurfaceControl.Transaction}s to minimize allocations.
+ */
+@Singleton
+public class TransactionPool {
+    private final Pools.SynchronizedPool<SurfaceControl.Transaction> mTransactionPool =
+            new Pools.SynchronizedPool<>(4);
+
+    @Inject
+    TransactionPool() {
+    }
+
+    /** Gets a transaction from the pool. */
+    public SurfaceControl.Transaction acquire() {
+        SurfaceControl.Transaction t = mTransactionPool.acquire();
+        if (t == null) {
+            return new SurfaceControl.Transaction();
+        }
+        return t;
+    }
+
+    /**
+     * Return a transaction to the pool. DO NOT call {@link SurfaceControl.Transaction#close()} if
+     * returning to pool.
+     */
+    public void release(SurfaceControl.Transaction t) {
+        if (!mTransactionPool.release(t)) {
+            t.close();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
index 8a5aad8..cf5a4d3 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleData.java
@@ -443,20 +443,7 @@
             mStateChange.orderChanged |= repackAll();
         }
 
-        if (reason == BubbleController.DISMISS_AGED) {
-            if (DEBUG_BUBBLE_DATA) {
-                Log.d(TAG, "overflowing bubble: " + bubbleToRemove);
-            }
-            mOverflowBubbles.add(0, bubbleToRemove);
-            if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
-                // Remove oldest bubble.
-                if (DEBUG_BUBBLE_DATA) {
-                    Log.d(TAG, "Overflow full. Remove bubble: " + mOverflowBubbles.get(
-                            mOverflowBubbles.size() - 1));
-                }
-                mOverflowBubbles.remove(mOverflowBubbles.size() - 1);
-            }
-        }
+        overflowBubble(reason, bubbleToRemove);
 
         // Note: If mBubbles.isEmpty(), then mSelectedBubble is now null.
         if (Objects.equals(mSelectedBubble, bubbleToRemove)) {
@@ -468,6 +455,25 @@
         maybeSendDeleteIntent(reason, bubbleToRemove.getEntry());
     }
 
+    void overflowBubble(@DismissReason int reason, Bubble bubble) {
+        if (reason == BubbleController.DISMISS_AGED
+                || reason == BubbleController.DISMISS_USER_GESTURE) {
+            if (DEBUG_BUBBLE_DATA) {
+                Log.d(TAG, "overflowing bubble: " + bubble);
+            }
+            mOverflowBubbles.add(0, bubble);
+
+            if (mOverflowBubbles.size() == mMaxOverflowBubbles + 1) {
+                // Remove oldest bubble.
+                if (DEBUG_BUBBLE_DATA) {
+                    Log.d(TAG, "Overflow full. Remove bubble: " + mOverflowBubbles.get(
+                            mOverflowBubbles.size() - 1));
+                }
+                mOverflowBubbles.remove(mOverflowBubbles.size() - 1);
+            }
+        }
+    }
+
     public void dismissAll(@DismissReason int reason) {
         if (DEBUG_BUBBLE_DATA) {
             Log.d(TAG, "dismissAll: reason=" + reason);
@@ -478,9 +484,7 @@
         setExpandedInternal(false);
         setSelectedBubbleInternal(null);
         while (!mBubbles.isEmpty()) {
-            Bubble bubble = mBubbles.remove(0);
-            maybeSendDeleteIntent(reason, bubble.getEntry());
-            mStateChange.bubbleRemoved(bubble, reason);
+            doRemove(mBubbles.get(0).getKey(), reason);
         }
         dispatchPendingChanges();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
index 756c598..eb836b1 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleOverflowActivity.java
@@ -55,7 +55,6 @@
     private BubbleOverflowAdapter mAdapter;
     private RecyclerView mRecyclerView;
     private List<Bubble> mOverflowBubbles = new ArrayList<>();
-    private int mMaxBubbles;
 
     @Inject
     public BubbleOverflowActivity(BubbleController controller) {
@@ -68,7 +67,6 @@
         setContentView(R.layout.bubble_overflow_activity);
         setBackgroundColor();
 
-        mMaxBubbles = getResources().getInteger(R.integer.bubbles_max_rendered);
         mEmptyState = findViewById(R.id.bubble_overflow_empty_state);
         mRecyclerView = findViewById(R.id.bubble_overflow_recycler);
         mRecyclerView.setLayoutManager(
@@ -95,11 +93,7 @@
 
     void onDataChanged(List<Bubble> bubbles) {
         mOverflowBubbles.clear();
-        if (bubbles.size() > mMaxBubbles) {
-            mOverflowBubbles.addAll(bubbles.subList(mMaxBubbles, bubbles.size()));
-        } else {
-            mOverflowBubbles.addAll(bubbles);
-        }
+        mOverflowBubbles.addAll(bubbles);
         mAdapter.notifyDataSetChanged();
 
         if (mOverflowBubbles.isEmpty()) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index 3d9865c..955edcf 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -648,7 +648,7 @@
         String appName = topBubble.getAppName();
         Notification notification = topBubble.getEntry().getSbn().getNotification();
         CharSequence titleCharSeq = notification.extras.getCharSequence(Notification.EXTRA_TITLE);
-        String titleStr = getResources().getString(R.string.stream_notification);
+        String titleStr = getResources().getString(R.string.notification_bubble_title);
         if (titleCharSeq != null) {
             titleStr = titleCharSeq.toString();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
index 6a64c83..f719cc6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/FalsingManagerImpl.java
@@ -130,7 +130,8 @@
             new KeyguardUpdateMonitorCallback() {
                 @Override
                 public void onBiometricAuthenticated(int userId,
-                        BiometricSourceType biometricSourceType) {
+                        BiometricSourceType biometricSourceType,
+                        boolean isStrongBiometric) {
                     if (userId == KeyguardUpdateMonitor.getCurrentUser()
                             && biometricSourceType == BiometricSourceType.FACE) {
                         mJustUnlockedWithFace = true;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
index 2f3e336..a084ae6 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/BrightLineFalsingManager.java
@@ -78,7 +78,8 @@
             new KeyguardUpdateMonitorCallback() {
                 @Override
                 public void onBiometricAuthenticated(int userId,
-                        BiometricSourceType biometricSourceType) {
+                        BiometricSourceType biometricSourceType,
+                        boolean isStrongBiometric) {
                     if (userId == KeyguardUpdateMonitor.getCurrentUser()
                             && biometricSourceType == BiometricSourceType.FACE) {
                         mJustUnlockedWithFace = true;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
index 7f45cc8..0329183 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/DistanceClassifier.java
@@ -38,10 +38,10 @@
 class DistanceClassifier extends FalsingClassifier {
 
     private static final float HORIZONTAL_FLING_THRESHOLD_DISTANCE_IN = 1;
-    private static final float VERTICAL_FLING_THRESHOLD_DISTANCE_IN = 1;
+    private static final float VERTICAL_FLING_THRESHOLD_DISTANCE_IN = 1.5f;
     private static final float HORIZONTAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
     private static final float VERTICAL_SWIPE_THRESHOLD_DISTANCE_IN = 3;
-    private static final float VELOCITY_TO_DISTANCE = 80f;
+    private static final float VELOCITY_TO_DISTANCE = 30f;
     private static final float SCREEN_FRACTION_MAX_DISTANCE = 0.8f;
 
     private final float mVerticalFlingThresholdPx;
diff --git a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
index 957ea8d..a796f3c 100644
--- a/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
+++ b/packages/SystemUI/src/com/android/systemui/classifier/brightline/ZigZagClassifier.java
@@ -42,8 +42,8 @@
     // most swipes will follow somewhat of a 'C' or 'S' shape, we allow more deviance along the
     // `SECONDARY` axis.
     private static final float MAX_X_PRIMARY_DEVIANCE = .05f;
-    private static final float MAX_Y_PRIMARY_DEVIANCE = .1f;
-    private static final float MAX_X_SECONDARY_DEVIANCE = .6f;
+    private static final float MAX_Y_PRIMARY_DEVIANCE = .15f;
+    private static final float MAX_X_SECONDARY_DEVIANCE = .4f;
     private static final float MAX_Y_SECONDARY_DEVIANCE = .3f;
 
     private final float mMaxXPrimaryDeviance;
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
index 87bdfa8..6ff1bbc 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsBindingControllerImpl.kt
@@ -22,7 +22,6 @@
 import android.os.UserHandle
 import android.service.controls.Control
 import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsSubscriber
 import android.service.controls.IControlsSubscription
 import android.service.controls.actions.ControlAction
@@ -63,12 +62,6 @@
     private val componentMap: MutableMap<Key, ControlsProviderLifecycleManager> =
             ArrayMap<Key, ControlsProviderLifecycleManager>()
 
-    private val loadCallbackService = object : IControlsLoadCallback.Stub() {
-        override fun accept(token: IBinder, controls: MutableList<Control>) {
-            backgroundExecutor.execute(OnLoadRunnable(token, controls))
-        }
-    }
-
     private val actionCallbackService = object : IControlsActionCallback.Stub() {
         override fun accept(
             token: IBinder,
@@ -106,7 +99,6 @@
         return ControlsProviderLifecycleManager(
                 context,
                 backgroundExecutor,
-                loadCallbackService,
                 actionCallbackService,
                 subscriberService,
                 currentUser,
@@ -130,7 +122,7 @@
         callback: ControlsBindingController.LoadCallback
     ) {
         val provider = retrieveLifecycleManager(component)
-        provider.maybeBindAndLoad(callback)
+        provider.maybeBindAndLoad(LoadSubscriber(callback))
     }
 
     override fun subscribe(controls: List<ControlInfo>) {
@@ -216,7 +208,8 @@
 
     private inner class OnLoadRunnable(
         token: IBinder,
-        val list: List<Control>
+        val list: List<Control>,
+        val callback: ControlsBindingController.LoadCallback
     ) : CallbackRunnable(token) {
         override fun run() {
             if (provider == null) {
@@ -233,9 +226,7 @@
                     return
                 }
             }
-            provider.lastLoadCallback?.accept(list) ?: run {
-                Log.w(TAG, "Null callback")
-            }
+            callback.accept(list)
             provider.unbindService()
         }
     }
@@ -277,7 +268,7 @@
     ) : CallbackRunnable(token) {
         override fun run() {
             provider?.let {
-                Log.i(TAG, "onComplete receive from '${provider.componentName}'")
+                Log.i(TAG, "onComplete receive from '${it.componentName}'")
             }
         }
     }
@@ -288,7 +279,7 @@
     ) : CallbackRunnable(token) {
         override fun run() {
             provider?.let {
-                Log.e(TAG, "onError receive from '${provider.componentName}': $error")
+                Log.e(TAG, "onError receive from '${it.componentName}': $error")
             }
         }
     }
@@ -308,6 +299,44 @@
             }
         }
     }
+
+    private inner class OnLoadErrorRunnable(
+        token: IBinder,
+        val error: String,
+        val callback: ControlsBindingController.LoadCallback
+    ) : CallbackRunnable(token) {
+        override fun run() {
+            callback.error(error)
+            provider?.let {
+                Log.e(TAG, "onError receive from '${it.componentName}': $error")
+            }
+        }
+    }
+
+    private inner class LoadSubscriber(
+        val callback: ControlsBindingController.LoadCallback
+    ) : IControlsSubscriber.Stub() {
+        val loadedControls = ArrayList<Control>()
+        var hasError = false
+
+        override fun onSubscribe(token: IBinder, subs: IControlsSubscription) {
+            backgroundExecutor.execute(OnSubscribeRunnable(token, subs))
+        }
+
+        override fun onNext(token: IBinder, c: Control) {
+            backgroundExecutor.execute { loadedControls.add(c) }
+        }
+        override fun onError(token: IBinder, s: String) {
+            hasError = true
+            backgroundExecutor.execute(OnLoadErrorRunnable(token, s, callback))
+        }
+
+        override fun onComplete(token: IBinder) {
+            if (!hasError) {
+                backgroundExecutor.execute(OnLoadRunnable(token, loadedControls, callback))
+            }
+        }
+    }
 }
 
-private data class Key(val component: ComponentName, val user: UserHandle)
\ No newline at end of file
+private data class Key(val component: ComponentName, val user: UserHandle)
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
index d7f3c73..883f8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsFavoritePersistenceWrapper.kt
@@ -135,7 +135,7 @@
     }
 
     private fun parseXml(parser: XmlPullParser): List<ControlInfo> {
-        var type = 0
+        var type: Int
         val infos = mutableListOf<ControlInfo>()
         while (parser.next().also { type = it } != XmlPullParser.END_DOCUMENT) {
             if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
index 9ec71c7..a53fcd4 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManager.kt
@@ -29,7 +29,6 @@
 import android.service.controls.ControlsProviderService.CALLBACK_BUNDLE
 import android.service.controls.ControlsProviderService.CALLBACK_TOKEN
 import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
 import android.service.controls.IControlsSubscriber
 import android.service.controls.IControlsSubscription
@@ -48,8 +47,6 @@
  *
  * @property context A SystemUI context for binding to the services
  * @property executor A delayable executor for posting timeouts
- * @property loadCallbackService a callback interface to hand the remote service for loading
- *                               controls
  * @property actionCallbackService a callback interface to hand the remote service for sending
  *                                 action responses
  * @property subscriberService an "subscriber" interface for requesting and accepting updates for
@@ -60,15 +57,12 @@
 class ControlsProviderLifecycleManager(
     private val context: Context,
     private val executor: DelayableExecutor,
-    private val loadCallbackService: IControlsLoadCallback.Stub,
     private val actionCallbackService: IControlsActionCallback.Stub,
     private val subscriberService: IControlsSubscriber.Stub,
     val user: UserHandle,
     val componentName: ComponentName
 ) : IBinder.DeathRecipient {
 
-    var lastLoadCallback: ControlsBindingController.LoadCallback? = null
-        private set
     val token: IBinder = Binder()
     @GuardedBy("subscriptions")
     private val subscriptions = mutableListOf<IControlsSubscription>()
@@ -156,9 +150,12 @@
             bindService(false)
             return
         }
-        if (Message.Load in queue) {
-            load()
+
+        queue.filter { it is Message.Load }.forEach {
+            val msg = it as Message.Load
+            load(msg.subscriber)
         }
+
         queue.filter { it is Message.Subscribe }.flatMap { (it as Message.Subscribe).list }.run {
             if (this.isNotEmpty()) {
                 subscribe(this)
@@ -193,12 +190,12 @@
         }
     }
 
-    private fun load() {
+    private fun load(subscriber: IControlsSubscriber.Stub) {
         if (DEBUG) {
             Log.d(TAG, "load $componentName")
         }
-        if (!(wrapper?.load(loadCallbackService) ?: false)) {
-            queueMessage(Message.Load)
+        if (!(wrapper?.load(subscriber) ?: false)) {
+            queueMessage(Message.Load(subscriber))
             binderDied()
         }
     }
@@ -213,27 +210,23 @@
     }
 
     /**
-     * Request a call to [ControlsProviderService.loadAvailableControls].
+     * Request a call to [IControlsProvider.load].
      *
      * If the service is not bound, the call will be queued and the service will be bound first.
-     * The service will be bound after the controls are returned or the call times out.
+     * The service will be unbound after the controls are returned or the call times out.
      *
-     * @param callback a callback in which to return the result back. If the call times out
-     *                 [ControlsBindingController.LoadCallback.error] will be called instead.
+     * @param subscriber the subscriber that manages coordination for loading controls
      */
-    fun maybeBindAndLoad(callback: ControlsBindingController.LoadCallback) {
+    fun maybeBindAndLoad(subscriber: IControlsSubscriber.Stub) {
         unqueueMessage(Message.Unbind)
-        lastLoadCallback = callback
         onLoadCanceller = executor.executeDelayed({
             // Didn't receive a response in time, log and send back error
             Log.d(TAG, "Timeout waiting onLoad for $componentName")
-            callback.error("Timeout waiting onLoad")
-            // Don't accept load callbacks after this
-            lastLoadCallback = null
+            subscriber.onError(token, "Timeout waiting onLoad")
             unbindService()
         }, LOAD_TIMEOUT_SECONDS, TimeUnit.SECONDS)
 
-        invokeOrQueue(::load, Message.Load)
+        invokeOrQueue({ load(subscriber) }, Message.Load(subscriber))
     }
 
     /**
@@ -324,7 +317,6 @@
      * Request unbind from the service.
      */
     fun unbindService() {
-        lastLoadCallback = null
         onLoadCanceller?.run()
         onLoadCanceller = null
 
@@ -344,7 +336,7 @@
      */
     sealed class Message {
         abstract val type: Int
-        object Load : Message() {
+        class Load(val subscriber: IControlsSubscriber.Stub) : Message() {
             override val type = MSG_LOAD
         }
         object Unbind : Message() {
diff --git a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
index b90f892..b2afd3c 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/controller/ServiceWrapper.kt
@@ -18,7 +18,6 @@
 
 import android.service.controls.actions.ControlAction
 import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
 import android.service.controls.IControlsSubscriber
 import android.service.controls.IControlsSubscription
@@ -45,9 +44,9 @@
         }
     }
 
-    fun load(cb: IControlsLoadCallback): Boolean {
+    fun load(subscriber: IControlsSubscriber): Boolean {
         return callThroughService {
-            service.load(cb)
+            service.load(subscriber)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
index 89caace..ac5e089 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/AppAdapter.kt
@@ -58,13 +58,13 @@
     private var listOfServices = emptyList<CandidateInfo>()
 
     private val callback = object : ControlsListingController.ControlsListingCallback {
-        override fun onServicesUpdated(list: List<CandidateInfo>) {
+        override fun onServicesUpdated(candidates: List<CandidateInfo>) {
             backgroundExecutor.execute {
-                val collator = Collator.getInstance(resources.getConfiguration().locale)
+                val collator = Collator.getInstance(resources.configuration.locales[0])
                 val localeComparator = compareBy<CandidateInfo, CharSequence>(collator) {
                     it.loadLabel()
                 }
-                listOfServices = list.sortedWith(localeComparator)
+                listOfServices = candidates.sortedWith(localeComparator)
                 uiExecutor.execute(::notifyDataSetChanged)
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
index 9952b97..af4a977 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsFavoritingActivity.kt
@@ -70,7 +70,7 @@
             target: RecyclerView.ViewHolder
         ): Boolean {
             return currentModel?.onMoveItem(
-                    viewHolder.adapterPosition, target.adapterPosition) != null
+                    viewHolder.layoutPosition, target.layoutPosition) != null
         }
 
         override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {}
diff --git a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
index d893caa..8e47f64 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/management/ControlsListingController.kt
@@ -45,6 +45,6 @@
 
     @FunctionalInterface
     interface ControlsListingCallback {
-        fun onServicesUpdated(list: List<CandidateInfo>)
+        fun onServicesUpdated(candidates: List<CandidateInfo>)
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 98cdf28..f4fd375 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -130,8 +130,7 @@
     private val listingCallback = object : ControlsListingController.ControlsListingCallback {
         override fun onServicesUpdated(candidates: List<CandidateInfo>) {
             bgExecutor.execute {
-                val collator = Collator.getInstance(context.getResources()
-                        .getConfiguration().locale)
+                val collator = Collator.getInstance(context.resources.configuration.locales[0])
                 val localeComparator = compareBy<CandidateInfo, CharSequence>(collator) {
                     it.loadLabel()
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 071198b..d3d4287 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -42,7 +42,7 @@
     val intent: PendingIntent
 ) : Dialog(parentContext) {
 
-    lateinit var activityView: ActivityView
+    var activityView: ActivityView
 
     val stateCallback: ActivityView.StateCallback = object : ActivityView.StateCallback() {
         override fun onActivityViewReady(view: ActivityView) {
@@ -61,24 +61,28 @@
         override fun onTaskRemovalStarted(taskId: Int) {}
     }
 
-    init {
-        val window = getWindow()
-        window.requestFeature(Window.FEATURE_NO_TITLE)
+    @Suppress("DEPRECATION")
+    private fun Window.setWindowParams() {
+        requestFeature(Window.FEATURE_NO_TITLE)
 
         // Inflate the decor view, so the attributes below are not overwritten by the theme.
-        window.getDecorView()
-        window.getAttributes().systemUiVisibility =
-            (window.getAttributes().systemUiVisibility
-                or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
-                or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
+        decorView
+        attributes.systemUiVisibility =
+                (attributes.systemUiVisibility
+                        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
+                        or View.SYSTEM_UI_FLAG_LAYOUT_STABLE)
 
-        window.setLayout(MATCH_PARENT, MATCH_PARENT)
-        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
-        window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-            or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-            or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
-        window.setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
-        window.getAttributes().setFitInsetsTypes(0 /* types */)
+        setLayout(MATCH_PARENT, MATCH_PARENT)
+        clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+        addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                or WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+                or WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED)
+        setType(WindowManager.LayoutParams.TYPE_VOLUME_OVERLAY)
+        getAttributes().setFitInsetsTypes(0 /* types */)
+    }
+
+    init {
+        getWindow()?.setWindowParams()
 
         setContentView(R.layout.controls_detail_dialog)
 
@@ -89,9 +93,9 @@
     }
 
     override fun show() {
-        val attrs = getWindow().getAttributes()
-        attrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
-        getWindow().setAttributes(attrs)
+        val attrs = getWindow()?.attributes
+        attrs?.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
+        getWindow()?.attributes = attrs
 
         activityView.setCallback(stateCallback)
 
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
index 45d7397..cca56c2 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ToggleRangeBehavior.kt
@@ -60,7 +60,7 @@
 
         val gestureListener = ToggleRangeGestureListener(cvh.layout)
         val gestureDetector = GestureDetector(context, gestureListener)
-        cvh.layout.setOnTouchListener({ v: View, e: MotionEvent ->
+        cvh.layout.setOnTouchListener { _: View, e: MotionEvent ->
             if (gestureDetector.onTouchEvent(e)) {
                 return@setOnTouchListener true
             }
@@ -72,7 +72,7 @@
             }
 
             return@setOnTouchListener false
-        })
+        }
     }
 
     override fun bind(cws: ControlWithState) {
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index a57ec5b..3e257b6 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -38,8 +38,10 @@
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.ShadeControllerImpl;
+import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedControllerImpl;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -92,10 +94,14 @@
 
     @Singleton
     @Provides
-    static HeadsUpManagerPhone provideHeadsUpManagerPhone(Context context,
+    static HeadsUpManagerPhone provideHeadsUpManagerPhone(
+            Context context,
             StatusBarStateController statusBarStateController,
-            KeyguardBypassController bypassController) {
-        return new HeadsUpManagerPhone(context, statusBarStateController, bypassController);
+            KeyguardBypassController bypassController,
+            NotificationGroupManager groupManager,
+            ConfigurationController configurationController) {
+        return new HeadsUpManagerPhone(context, statusBarStateController, bypassController,
+                groupManager, configurationController);
     }
 
     @Binds
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index b1db7df..2e6c955 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -22,6 +22,7 @@
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.SOME_AUTH_REQUIRED_AFTER_USER_REQUEST;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_DPM_LOCK_NOW;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_LOCKOUT;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE;
 import static com.android.systemui.DejankUtils.whitelistIpcs;
@@ -80,7 +81,8 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.Dependency;
+import com.android.systemui.DumpController;
+import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
@@ -144,7 +146,7 @@
  * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
  * thread of the keyguard.
  */
-public class KeyguardViewMediator extends SystemUI {
+public class KeyguardViewMediator extends SystemUI implements Dumpable {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     private static final long KEYGUARD_DONE_PENDING_TIMEOUT_MS = 3000;
 
@@ -222,10 +224,10 @@
     private final FalsingManager mFalsingManager;
 
     /** High level access to the power manager for WakeLocks */
-    private PowerManager mPM;
+    private final PowerManager mPM;
 
     /** TrustManager for letting it know when we change visibility */
-    private TrustManager mTrustManager;
+    private final TrustManager mTrustManager;
 
     /**
      * Used to keep the device awake while to ensure the keyguard finishes opening before
@@ -283,7 +285,7 @@
 
     // the properties of the keyguard
 
-    private KeyguardUpdateMonitor mUpdateMonitor;
+    private final KeyguardUpdateMonitor mUpdateMonitor;
 
     /**
      * Last SIM state reported by the telephony system.
@@ -537,7 +539,8 @@
         }
 
         @Override
-        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
+        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
+                boolean isStrongBiometric) {
             if (mLockPatternUtils.isSecure(userId)) {
                 mLockPatternUtils.getDevicePolicyManager().reportSuccessfulBiometricAttempt(
                         userId);
@@ -610,6 +613,7 @@
         @Override
         public void keyguardGone() {
             Trace.beginSection("KeyguardViewMediator.mViewMediatorCallback#keyguardGone");
+            mNotificationShadeWindowController.setKeyguardGoingAway(false);
             mKeyguardDisplayManager.hide();
             Trace.endSection();
         }
@@ -673,6 +677,9 @@
                 return KeyguardSecurityView.PROMPT_REASON_AFTER_LOCKOUT;
             } else if (any && (strongAuth & STRONG_AUTH_REQUIRED_FOR_UNATTENDED_UPDATE) != 0) {
                 return KeyguardSecurityView.PROMPT_REASON_PREPARE_FOR_UPDATE;
+            } else if (any && (strongAuth
+                    & STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT) != 0) {
+                return KeyguardSecurityView.PROMPT_REASON_NON_STRONG_BIOMETRIC_TIMEOUT;
             }
             return KeyguardSecurityView.PROMPT_REASON_NONE;
         }
@@ -696,7 +703,9 @@
             NotificationShadeWindowController notificationShadeWindowController,
             Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
             DismissCallbackRegistry dismissCallbackRegistry,
-            @UiBackground Executor uiBgExecutor) {
+            KeyguardUpdateMonitor keyguardUpdateMonitor, DumpController dumpController,
+            @UiBackground Executor uiBgExecutor, PowerManager powerManager,
+            TrustManager trustManager) {
         super(context);
         mFalsingManager = falsingManager;
         mLockPatternUtils = lockPatternUtils;
@@ -705,6 +714,10 @@
         mStatusBarKeyguardViewManagerLazy = statusBarKeyguardViewManagerLazy;
         mDismissCallbackRegistry = dismissCallbackRegistry;
         mUiBgExecutor = uiBgExecutor;
+        mUpdateMonitor = keyguardUpdateMonitor;
+        mPM = powerManager;
+        mTrustManager = trustManager;
+        dumpController.registerDumpable(this);
         mShowHomeOverLockscreen = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_SYSTEMUI,
                 NAV_BAR_HANDLE_SHOW_OVER_LOCKSCREEN,
@@ -731,9 +744,6 @@
     }
 
     private void setupLocked() {
-        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
-        mTrustManager = mContext.getSystemService(TrustManager.class);
-
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
 
@@ -754,8 +764,6 @@
 
         mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
-        mUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
-
         KeyguardUpdateMonitor.setCurrentUser(ActivityManager.getCurrentUser());
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure, unless Keyguard
@@ -1839,6 +1847,13 @@
             mShowKeyguardWakeLock.release();
         }
         mKeyguardDisplayManager.show();
+
+        // schedule 4hr idle timeout after which non-strong biometrics (i.e. weak or convenience
+        // biometric) can't be used to unlock device until unlocking with strong biometric or
+        // primary auth (i.e. PIN/pattern/password)
+        mLockPatternUtils.scheduleNonStrongBiometricIdleTimeout(
+                KeyguardUpdateMonitor.getCurrentUser());
+
         Trace.endSection();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 2c023ca..2ba0315 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -16,9 +16,13 @@
 
 package com.android.systemui.keyguard.dagger;
 
+import android.app.trust.TrustManager;
 import android.content.Context;
+import android.os.PowerManager;
 
 import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
@@ -54,6 +58,10 @@
             NotificationShadeWindowController notificationShadeWindowController,
             Lazy<StatusBarKeyguardViewManager> statusBarKeyguardViewManagerLazy,
             DismissCallbackRegistry dismissCallbackRegistry,
+            KeyguardUpdateMonitor updateMonitor,
+            DumpController dumpController,
+            PowerManager powerManager,
+            TrustManager trustManager,
             @UiBackground Executor uiBgExecutor) {
         return new KeyguardViewMediator(
                 context,
@@ -63,6 +71,10 @@
                 notificationShadeWindowController,
                 statusBarKeyguardViewManagerLazy,
                 dismissCallbackRegistry,
-                uiBgExecutor);
+                updateMonitor,
+                dumpController,
+                uiBgExecutor,
+                powerManager,
+                trustManager);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 019cb14..17aaff1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -25,10 +25,13 @@
 import android.content.res.Configuration;
 import android.graphics.drawable.Animatable;
 import android.util.AttributeSet;
+import android.util.Pair;
 import android.util.SparseArray;
+import android.view.DisplayCutout;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.ViewStub;
+import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.ImageView;
 import android.widget.LinearLayout;
@@ -42,6 +45,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.phone.StatusBarWindowView;
 
 public class QSDetail extends LinearLayout {
 
@@ -274,6 +278,32 @@
         }
     }
 
+    @Override
+    public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        DisplayCutout cutout = insets.getDisplayCutout();
+
+        Pair<Integer, Integer> padding = StatusBarWindowView.cornerCutoutMargins(
+                cutout, getDisplay());
+
+        if (padding == null) {
+            mQsDetailHeader.setPaddingRelative(
+                    getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding),
+                    getPaddingTop(),
+                    getResources().getDimensionPixelSize(R.dimen.qs_detail_header_padding),
+                    getPaddingBottom()
+            );
+        } else {
+            mQsDetailHeader.setPadding(
+                    padding.first,
+                    getPaddingTop(),
+                    padding.second,
+                    getPaddingBottom()
+            );
+        }
+
+        return super.onApplyWindowInsets(insets);
+    }
+
     private void handleToggleStateChanged(boolean state, boolean toggleEnabled) {
         mSwitchState = state;
         if (mAnimatingOpen) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
index 6c69718..011893d 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSMediaPlayer.java
@@ -244,7 +244,10 @@
         ActivityStarter mActivityStarter = Dependency.get(ActivityStarter.class);
         mSeamless.setOnClickListener(v -> {
             final Intent intent = new Intent()
-                    .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT);
+                    .setAction(MediaOutputSliceConstants.ACTION_MEDIA_OUTPUT)
+                    .putExtra(MediaOutputSliceConstants.EXTRA_PACKAGE_NAME,
+                        mController.getPackageName())
+                    .putExtra(MediaOutputSliceConstants.KEY_MEDIA_SESSION_TOKEN, token);
             mActivityStarter.startActivity(intent, false, true /* dismissShade */,
                     Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
         });
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index 8cd70cf..d422dd7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -60,6 +60,7 @@
 import com.android.systemui.plugins.DarkIconDispatcher;
 import com.android.systemui.plugins.DarkIconDispatcher.DarkReceiver;
 import com.android.systemui.qs.QSDetail.Callback;
+import com.android.systemui.qs.carrier.QSCarrierGroup;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconController.TintedIconManager;
@@ -435,23 +436,22 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+        // Handle padding of SystemIconsView
         DisplayCutout cutout = insets.getDisplayCutout();
-
-        // Handle padding of QuickStatusBarHeader
         Pair<Integer, Integer> cornerCutoutPadding = StatusBarWindowView.cornerCutoutMargins(
                 cutout, getDisplay());
         Pair<Integer, Integer> padding =
                 StatusBarWindowView.paddingNeededForCutoutAndRoundedCorner(
                         cutout, cornerCutoutPadding, mRoundedCornerPadding);
-        setPadding(padding.first, 0, padding.second, getPaddingBottom());
-
-        // Handle padding of SystemIconsView
         final int waterfallTopInset = cutout == null ? 0 : cutout.getWaterfallInsets().top;
-        mSystemIconsView.setPaddingRelative(
-                getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start),
-                waterfallTopInset,
-                getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end),
-                0);
+        int statusBarPaddingLeft = isLayoutRtl()
+                ? getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end)
+                : getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start);
+        int statusBarPaddingRight = isLayoutRtl()
+                ? getResources().getDimensionPixelSize(R.dimen.status_bar_padding_start)
+                : getResources().getDimensionPixelSize(R.dimen.status_bar_padding_end);
+        mSystemIconsView.setPadding(padding.first + statusBarPaddingLeft, waterfallTopInset,
+                padding.second + statusBarPaddingRight, 0);
 
         return super.onApplyWindowInsets(insets);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
index 867677a..d899acb 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeaderController.java
@@ -17,6 +17,7 @@
 package com.android.systemui.qs;
 
 import com.android.systemui.R;
+import com.android.systemui.qs.carrier.QSCarrierGroupController;
 
 import javax.inject.Inject;
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt
new file mode 100644
index 0000000..663f3f0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/CellSignalState.kt
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.carrier
+
+/**
+ * Represents the state of cell signal for a particular slot.
+ *
+ * To be used between [QSCarrierGroupController] and [QSCarrier].
+ */
+data class CellSignalState(
+    @JvmField val visible: Boolean = false,
+    @JvmField val mobileSignalIconId: Int = 0,
+    @JvmField val contentDescription: String? = null,
+    @JvmField val typeContentDescription: String? = null,
+    @JvmField val roaming: Boolean = false
+) {
+    /**
+     * Changes the visibility of this state by returning a copy with the visibility changed.
+     *
+     * If the visibility would not change, the same state is returned.
+     *
+     * @param visible the new visibility state
+     * @return `this` if `this.visible == visible`. Else, a new copy with the visibility changed.
+     */
+    fun changeVisibility(visible: Boolean): CellSignalState {
+        if (this.visible == visible) return this
+        else return copy(visible = visible)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
rename to packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index 5a9c360..ad275f1 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.carrier;
 
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -29,6 +29,7 @@
 import com.android.settingslib.graph.SignalDrawable;
 import com.android.systemui.DualToneHandler;
 import com.android.systemui.R;
+import com.android.systemui.qs.QuickStatusBarHeader;
 
 import java.util.Objects;
 
@@ -41,7 +42,7 @@
     private DualToneHandler mDualToneHandler;
     private ColorStateList mColorForegroundStateList;
     private float mColorForegroundIntensity;
-    private QSCarrierGroupController.CellSignalState mLastSignalState;
+    private CellSignalState mLastSignalState;
 
     public QSCarrier(Context context) {
         super(context);
@@ -76,8 +77,13 @@
         mColorForegroundIntensity = QuickStatusBarHeader.getColorIntensity(colorForeground);
     }
 
-    public void updateState(QSCarrierGroupController.CellSignalState state) {
-        if (Objects.equals(state, mLastSignalState)) return;
+    /**
+     * Update the state of this view
+     * @param state the current state of the signal for this view
+     * @return true if the state was actually changed
+     */
+    public boolean updateState(CellSignalState state) {
+        if (Objects.equals(state, mLastSignalState)) return false;
         mLastSignalState = state;
         mMobileGroup.setVisibility(state.visible ? View.VISIBLE : View.GONE);
         if (state.visible) {
@@ -103,6 +109,7 @@
             }
             mMobileSignal.setContentDescription(contentDescription);
         }
+        return true;
     }
 
     private boolean hasValidTypeContentDescription(String typeContentDescription) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
similarity index 93%
rename from packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
rename to packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
index 346c75d..d03563f 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.carrier;
 
 import android.content.Context;
 import android.util.AttributeSet;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
similarity index 86%
rename from packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
rename to packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
index eb5b4cc..f9b1473 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSCarrierGroupController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroupController.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.carrier;
 
 import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
 
@@ -29,7 +29,6 @@
 import android.view.View;
 import android.widget.TextView;
 
-import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import com.android.keyguard.CarrierTextController;
@@ -38,7 +37,6 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.NetworkController;
 
-import java.util.Objects;
 import java.util.function.Consumer;
 
 import javax.inject.Inject;
@@ -82,11 +80,13 @@
                         Log.e(TAG, "Invalid SIM slot index for subscription: " + subId);
                         return;
                     }
-                    mInfos[slotIndex].visible = statusIcon.visible;
-                    mInfos[slotIndex].mobileSignalIconId = statusIcon.icon;
-                    mInfos[slotIndex].contentDescription = statusIcon.contentDescription;
-                    mInfos[slotIndex].typeContentDescription = typeContentDescription.toString();
-                    mInfos[slotIndex].roaming = roaming;
+                    mInfos[slotIndex] = new CellSignalState(
+                            statusIcon.visible,
+                            statusIcon.icon,
+                            statusIcon.contentDescription,
+                            typeContentDescription.toString(),
+                            roaming
+                    );
                     mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
                 }
 
@@ -94,7 +94,7 @@
                 public void setNoSims(boolean hasNoSims, boolean simDetected) {
                     if (hasNoSims) {
                         for (int i = 0; i < SIM_SLOTS; i++) {
-                            mInfos[i].visible = false;
+                            mInfos[i] = mInfos[i].changeVisibility(false);
                         }
                     }
                     mMainHandler.obtainMessage(H.MSG_UPDATE_STATE).sendToTarget();
@@ -236,7 +236,7 @@
                                         + info.subscriptionIds[i]);
                         continue;
                     }
-                    mInfos[slot].visible = true;
+                    mInfos[slot] = mInfos[slot].changeVisibility(true);
                     slotSeen[slot] = true;
                     mCarrierGroups[slot].setCarrierText(
                             info.listOfCarriers[i].toString().trim());
@@ -244,7 +244,7 @@
                 }
                 for (int i = 0; i < SIM_SLOTS; i++) {
                     if (!slotSeen[i]) {
-                        mInfos[i].visible = false;
+                        mInfos[i] = mInfos[i].changeVisibility(false);
                         mCarrierGroups[i].setVisibility(View.GONE);
                     }
                 }
@@ -255,7 +255,7 @@
             // No sims or airplane mode (but not WFC). Do not show QSCarrierGroup, instead just show
             // info.carrierText in a different view.
             for (int i = 0; i < SIM_SLOTS; i++) {
-                mInfos[i].visible = false;
+                mInfos[i] = mInfos[i].changeVisibility(false);
                 mCarrierGroups[i].setCarrierText("");
                 mCarrierGroups[i].setVisibility(View.GONE);
             }
@@ -295,35 +295,6 @@
         }
     }
 
-    static final class CellSignalState {
-        boolean visible;
-        int mobileSignalIconId;
-        String contentDescription;
-        String typeContentDescription;
-        boolean roaming;
-
-        @Override
-        public boolean equals(@Nullable Object obj) {
-            if (this == obj) return true;
-            if (!(obj instanceof CellSignalState)) return false;
-            CellSignalState other = (CellSignalState) obj;
-            return this.visible == other.visible
-                    && this.mobileSignalIconId == other.mobileSignalIconId
-                    && Objects.equals(this.contentDescription, other.contentDescription)
-                    && Objects.equals(this.typeContentDescription, other.typeContentDescription)
-                    && this.roaming == other.roaming;
-        }
-
-        @Override
-        public int hashCode() {
-            return Objects.hash(visible,
-                    mobileSignalIconId,
-                    contentDescription,
-                    typeContentDescription,
-                    roaming);
-        }
-    }
-
     public static class Builder {
         private QSCarrierGroup mView;
         private final ActivityStarter mActivityStarter;
@@ -343,7 +314,7 @@
             mCarrierTextControllerBuilder = carrierTextControllerBuilder;
         }
 
-        Builder setQSCarrierGroup(QSCarrierGroup view) {
+        public Builder setQSCarrierGroup(QSCarrierGroup view) {
             mView = view;
             return this;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
index 0c86157..1ab77f3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/HotspotTile.java
@@ -17,9 +17,9 @@
 package com.android.systemui.qs.tiles;
 
 import android.annotation.Nullable;
-import android.content.ComponentName;
 import android.content.Intent;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.service.quicksettings.Tile;
 import android.util.Log;
 import android.widget.Switch;
@@ -36,9 +36,6 @@
 
 /** Quick settings tile: Hotspot **/
 public class HotspotTile extends QSTileImpl<BooleanState> {
-    private static final Intent TETHER_SETTINGS = new Intent().setComponent(new ComponentName(
-            "com.android.settings", "com.android.settings.TetherSettings"));
-
     private final Icon mEnabledStatic = ResourceIcon.get(R.drawable.ic_hotspot);
 
     private final HotspotController mHotspotController;
@@ -79,7 +76,7 @@
 
     @Override
     public Intent getLongClickIntent() {
-        return new Intent(TETHER_SETTINGS);
+        return new Intent(Settings.ACTION_TETHER_SETTINGS);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
index 84891ec..6663237 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/ScreenRecordTile.java
@@ -108,7 +108,7 @@
         Log.d(TAG, "Starting countdown");
         // Close QS, otherwise the permission dialog appears beneath it
         getHost().collapsePanels();
-        mController.launchRecordPrompt(this);
+        mController.launchRecordPrompt();
     }
 
     private void cancelCountdown() {
@@ -129,6 +129,11 @@
         }
 
         @Override
+        public void onCountdownEnd() {
+            refreshState();
+        }
+
+        @Override
         public void onRecordingStart() {
             refreshState();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index ad49364..34cad51 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -380,6 +380,14 @@
                     taskId, mHandler, null);
         }
 
+        @Override
+        public void setSplitScreenMinimized(boolean minimized) {
+            Divider divider = mDividerOptional.get();
+            if (divider != null) {
+                divider.setMinimized(minimized);
+            }
+        }
+
         private boolean verifyCaller(String reason) {
             final int callerId = Binder.getCallingUserHandle().getIdentifier();
             if (callerId != mCurrentBoundedUserId) {
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
index 6ad9c40..8dad08e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/RecordingController.java
@@ -23,7 +23,6 @@
 import android.os.CountDownTimer;
 import android.util.Log;
 
-import com.android.systemui.qs.tiles.ScreenRecordTile;
 import com.android.systemui.statusbar.policy.CallbackController;
 
 import java.util.ArrayList;
@@ -62,7 +61,7 @@
     /**
      * Show dialog of screen recording options to user.
      */
-    public void launchRecordPrompt(ScreenRecordTile tileToUpdate) {
+    public void launchRecordPrompt() {
         final ComponentName launcherComponent = new ComponentName(SYSUI_PACKAGE,
                 SYSUI_SCREENRECORD_LAUNCHER);
         final Intent intent = new Intent();
@@ -73,15 +72,17 @@
 
     /**
      * Start counting down in preparation to start a recording
-     * @param ms Time in ms to count down
+     * @param ms Total time in ms to wait before starting
+     * @param interval Time in ms per countdown step
      * @param startIntent Intent to start a recording
      * @param stopIntent Intent to stop a recording
      */
-    public void startCountdown(long ms, PendingIntent startIntent, PendingIntent stopIntent) {
+    public void startCountdown(long ms, long interval, PendingIntent startIntent,
+            PendingIntent stopIntent) {
         mIsStarting = true;
         mStopIntent = stopIntent;
 
-        mCountDownTimer = new CountDownTimer(ms, 1000) {
+        mCountDownTimer = new CountDownTimer(ms, interval) {
             @Override
             public void onTick(long millisUntilFinished) {
                 for (RecordingStateChangeCallback cb : mListeners) {
@@ -94,7 +95,7 @@
                 mIsStarting = false;
                 mIsRecording = true;
                 for (RecordingStateChangeCallback cb : mListeners) {
-                    cb.onRecordingEnd();
+                    cb.onCountdownEnd();
                 }
                 try {
                     startIntent.send();
@@ -120,7 +121,7 @@
         mIsStarting = false;
 
         for (RecordingStateChangeCallback cb : mListeners) {
-            cb.onRecordingEnd();
+            cb.onCountdownEnd();
         }
     }
 
@@ -144,16 +145,12 @@
      * Stop the recording
      */
     public void stopRecording() {
-        updateState(false);
         try {
             mStopIntent.send();
+            updateState(false);
         } catch (PendingIntent.CanceledException e) {
             Log.e(TAG, "Error stopping: " + e.getMessage());
         }
-
-        for (RecordingStateChangeCallback cb : mListeners) {
-            cb.onRecordingEnd();
-        }
     }
 
     /**
@@ -193,6 +190,12 @@
         default void onCountdown(long millisUntilFinished) {}
 
         /**
+         * Called when a countdown to recording has ended. This is a separate method so that if
+         * needed, listeners can handle cases where recording fails to start
+         */
+        default void onCountdownEnd() {}
+
+        /**
          * Called when a screen recording has started
          */
         default void onRecordingStart() {}
diff --git a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
index 566f12b..26973d0 100644
--- a/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/screenrecord/ScreenRecordDialog.java
@@ -34,6 +34,7 @@
  */
 public class ScreenRecordDialog extends Activity {
     private static final long DELAY_MS = 3000;
+    private static final long INTERVAL_MS = 1000;
 
     private final RecordingController mController;
     private Switch mAudioSwitch;
@@ -83,6 +84,6 @@
                 RecordingService.REQUEST_CODE,
                 RecordingService.getStopIntent(this),
                 PendingIntent.FLAG_UPDATE_CURRENT);
-        mController.startCountdown(DELAY_MS, startIntent, stopIntent);
+        mController.startCountdown(DELAY_MS, INTERVAL_MS, startIntent, stopIntent);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 9e1e347..f06cd54 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -497,9 +497,9 @@
         flashOutAnimator.addUpdateListener(animation ->
                 mScreenshotFlash.setAlpha((float) animation.getAnimatedValue()));
 
-        final PointF startPos = new PointF((float) bounds.left, (float) bounds.top);
-        final PointF finalPos = new PointF(mScreenshotOffsetXPx,
-                mDisplayMetrics.heightPixels - mScreenshotOffsetYPx - height * cornerScale);
+        final PointF startPos = new PointF(bounds.centerX(), bounds.centerY());
+        final PointF finalPos = new PointF(mScreenshotOffsetXPx + width * cornerScale / 2f,
+                mDisplayMetrics.heightPixels - mScreenshotOffsetYPx - height * cornerScale / 2f);
 
         ValueAnimator toCorner = ValueAnimator.ofFloat(0, 1);
         toCorner.setDuration(SCREENSHOT_TO_CORNER_Y_DURATION_MS);
@@ -517,11 +517,13 @@
             }
 
             if (t < xPositionPct) {
-                mScreenshotView.setX(MathUtils.lerp(
-                        startPos.x, finalPos.x, mFastOutSlowIn.getInterpolation(t / xPositionPct)));
+                float xCenter = MathUtils.lerp(startPos.x, finalPos.x,
+                        mFastOutSlowIn.getInterpolation(t / xPositionPct));
+                mScreenshotView.setX(xCenter - width * mScreenshotView.getScaleX() / 2f);
             }
-            mScreenshotView.setY(MathUtils.lerp(
-                    startPos.y, finalPos.y, mFastOutSlowIn.getInterpolation(t)));
+            float yCenter = MathUtils.lerp(startPos.y, finalPos.y,
+                    mFastOutSlowIn.getInterpolation(t));
+            mScreenshotView.setY(yCenter - height * mScreenshotView.getScaleY() / 2f);
         });
 
         toCorner.addListener(new AnimatorListenerAdapter() {
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
index 7de70f5..2571521 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/SaveImageInBackgroundTask.java
@@ -281,7 +281,8 @@
                         .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
                         .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
                                 mSmartActionsEnabled)
-                        .setAction(Intent.ACTION_SEND),
+                        .setAction(Intent.ACTION_SEND)
+                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
                 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
 
         Notification.Action.Builder shareActionBuilder = new Notification.Action.Builder(
@@ -310,7 +311,8 @@
                         .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
                         .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
                                 mSmartActionsEnabled)
-                        .setAction(Intent.ACTION_EDIT),
+                        .setAction(Intent.ACTION_EDIT)
+                        .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
                 PendingIntent.FLAG_CANCEL_CURRENT, UserHandle.SYSTEM);
         Notification.Action.Builder editActionBuilder = new Notification.Action.Builder(
                 Icon.createWithResource(r, R.drawable.ic_screenshot_edit),
@@ -324,7 +326,8 @@
                             .putExtra(GlobalScreenshot.SCREENSHOT_URI_ID, uri.toString())
                             .putExtra(GlobalScreenshot.EXTRA_ID, mScreenshotId)
                             .putExtra(GlobalScreenshot.EXTRA_SMART_ACTIONS_ENABLED,
-                                    mSmartActionsEnabled),
+                                    mSmartActionsEnabled)
+                            .addFlags(Intent.FLAG_RECEIVER_FOREGROUND),
                     PendingIntent.FLAG_CANCEL_CURRENT | PendingIntent.FLAG_ONE_SHOT);
             Notification.Action.Builder deleteActionBuilder = new Notification.Action.Builder(
                     Icon.createWithResource(r, R.drawable.ic_screenshot_delete),
@@ -361,9 +364,9 @@
             String actionType = extras.getString(
                     ScreenshotNotificationSmartActionsProvider.ACTION_TYPE,
                     ScreenshotNotificationSmartActionsProvider.DEFAULT_ACTION_TYPE);
-            Intent intent = new Intent(context,
-                    GlobalScreenshot.SmartActionsReceiver.class).putExtra(
-                    GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent);
+            Intent intent = new Intent(context, GlobalScreenshot.SmartActionsReceiver.class)
+                    .putExtra(GlobalScreenshot.EXTRA_ACTION_INTENT, action.actionIntent)
+                    .addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
             addIntentExtras(mScreenshotId, intent, actionType, mSmartActionsEnabled);
             PendingIntent broadcastIntent = PendingIntent.getBroadcast(context,
                     mRandom.nextInt(),
diff --git a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
index 5ae0954..4f20492 100644
--- a/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
+++ b/packages/SystemUI/src/com/android/systemui/shortcut/ShortcutKeyDispatcher.java
@@ -22,10 +22,8 @@
 import android.content.Context;
 import android.content.res.Configuration;
 import android.os.RemoteException;
-import android.util.Log;
 import android.view.IWindowManager;
 import android.view.KeyEvent;
-import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.policy.DividerSnapAlgorithm;
@@ -94,29 +92,24 @@
     }
 
     private void handleDockKey(long shortcutCode) {
-        try {
-            int dockSide = mWindowManagerService.getDockedStackSide();
-            if (dockSide == WindowManager.DOCKED_INVALID) {
-                // Split the screen
-                mRecents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
-                        ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
-                        : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
-            } else {
-                // If there is already a docked window, we respond by resizing the docking pane.
-                DividerView dividerView = mDivider.getView();
-                DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
-                int dividerPosition = dividerView.getCurrentPosition();
-                DividerSnapAlgorithm.SnapTarget currentTarget =
-                        snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
-                DividerSnapAlgorithm.SnapTarget target = (shortcutCode == SC_DOCK_LEFT)
-                        ? snapAlgorithm.getPreviousTarget(currentTarget)
-                        : snapAlgorithm.getNextTarget(currentTarget);
-                dividerView.startDragging(true /* animate */, false /* touching */);
-                dividerView.stopDragging(target.position, 0f, false /* avoidDismissStart */,
-                        true /* logMetrics */);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "handleDockKey() failed.");
+        if (mDivider == null || !mDivider.inSplitMode()) {
+            // Split the screen
+            mRecents.splitPrimaryTask((shortcutCode == SC_DOCK_LEFT)
+                    ? SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT
+                    : SPLIT_SCREEN_CREATE_MODE_BOTTOM_OR_RIGHT, null, -1);
+        } else {
+            // If there is already a docked window, we respond by resizing the docking pane.
+            DividerView dividerView = mDivider.getView();
+            DividerSnapAlgorithm snapAlgorithm = dividerView.getSnapAlgorithm();
+            int dividerPosition = dividerView.getCurrentPosition();
+            DividerSnapAlgorithm.SnapTarget currentTarget =
+                    snapAlgorithm.calculateNonDismissingSnapTarget(dividerPosition);
+            DividerSnapAlgorithm.SnapTarget target = (shortcutCode == SC_DOCK_LEFT)
+                    ? snapAlgorithm.getPreviousTarget(currentTarget)
+                    : snapAlgorithm.getNextTarget(currentTarget);
+            dividerView.startDragging(true /* animate */, false /* touching */);
+            dividerView.stopDragging(target.position, 0f, false /* avoidDismissStart */,
+                    true /* logMetrics */);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
index 90cc0e57..56cdff4 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
@@ -17,69 +17,284 @@
 package com.android.systemui.stackdivider;
 
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
+import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.graphics.Rect;
+import android.os.Handler;
 import android.os.RemoteException;
+import android.provider.Settings;
 import android.util.Log;
-import android.view.IDockedStackListener;
+import android.util.Slog;
+import android.view.IWindowContainer;
 import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
 import android.view.View;
-import android.view.WindowManagerGlobal;
+import android.view.WindowContainerTransaction;
 
+import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
+import com.android.systemui.TransactionPool;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.wm.DisplayChangeController;
+import com.android.systemui.wm.DisplayController;
+import com.android.systemui.wm.DisplayImeController;
+import com.android.systemui.wm.DisplayLayout;
+import com.android.systemui.wm.SystemWindows;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 import java.util.Optional;
+import java.util.function.Consumer;
+
+import javax.inject.Singleton;
 
 import dagger.Lazy;
 
 /**
  * Controls the docked stack divider.
  */
-public class Divider extends SystemUI implements DividerView.DividerCallbacks {
+@Singleton
+public class Divider extends SystemUI implements DividerView.DividerCallbacks,
+        DisplayController.OnDisplaysChangedListener {
     private static final String TAG = "Divider";
+
+    static final boolean DEBUG = true;
+
+    static final int DEFAULT_APP_TRANSITION_DURATION = 336;
+
     private final Optional<Lazy<Recents>> mRecentsOptionalLazy;
 
     private DividerWindowManager mWindowManager;
     private DividerView mView;
     private final DividerState mDividerState = new DividerState();
-    private DockDividerVisibilityListener mDockDividerVisibilityListener;
     private boolean mVisible = false;
     private boolean mMinimized = false;
     private boolean mAdjustedForIme = false;
     private boolean mHomeStackResizable = false;
     private ForcedResizableInfoActivityController mForcedResizableController;
+    private SystemWindows mSystemWindows;
+    final SurfaceSession mSurfaceSession = new SurfaceSession();
+    private DisplayController mDisplayController;
+    private DisplayImeController mImeController;
+    final TransactionPool mTransactionPool;
 
-    public Divider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy) {
+    // Keeps track of real-time split geometry including snap positions and ime adjustments
+    private SplitDisplayLayout mSplitLayout;
+
+    // Transient: this contains the layout calculated for a new rotation requested by WM. This is
+    // kept around so that we can wait for a matching configuration change and then use the exact
+    // layout that we sent back to WM.
+    private SplitDisplayLayout mRotateSplitLayout;
+
+    private Handler mHandler;
+    private KeyguardStateController mKeyguardStateController;
+
+    private final ArrayList<WeakReference<Consumer<Boolean>>> mDockedStackExistsListeners =
+            new ArrayList<>();
+
+    private SplitScreenTaskOrganizer mSplits = new SplitScreenTaskOrganizer(this);
+
+    private DisplayChangeController.OnDisplayChangingListener mRotationController =
+            (display, fromRotation, toRotation, t) -> {
+                DisplayLayout displayLayout =
+                        new DisplayLayout(mDisplayController.getDisplayLayout(display));
+                SplitDisplayLayout sdl = new SplitDisplayLayout(mContext, displayLayout, mSplits);
+                sdl.rotateTo(toRotation);
+                mRotateSplitLayout = sdl;
+                int position = mMinimized ? mView.mSnapTargetBeforeMinimized.position
+                        : mView.getCurrentPosition();
+                DividerSnapAlgorithm snap = sdl.getSnapAlgorithm();
+                final DividerSnapAlgorithm.SnapTarget target =
+                        snap.calculateNonDismissingSnapTarget(position);
+                sdl.resizeSplits(target.position, t);
+
+                if (inSplitMode()) {
+                    WindowManagerProxy.applyHomeTasksMinimized(sdl, mSplits.mSecondary.token, t);
+                }
+            };
+
+    private IWindowContainer mLastImeTarget = null;
+    private boolean mShouldAdjustForIme = false;
+
+    private DisplayImeController.ImePositionProcessor mImePositionProcessor =
+            new DisplayImeController.ImePositionProcessor() {
+                private int mStartTop = 0;
+                private int mFinalTop = 0;
+                @Override
+                public void onImeStartPositioning(int displayId, int imeTop, int finalImeTop,
+                        boolean showing, SurfaceControl.Transaction t) {
+                    mStartTop = imeTop;
+                    mFinalTop = finalImeTop;
+                    if (showing) {
+                        try {
+                            mLastImeTarget = ActivityTaskManager.getTaskOrganizerController()
+                                    .getImeTarget(displayId);
+                            mShouldAdjustForIme = mLastImeTarget != null
+                                    && !mSplitLayout.mDisplayLayout.isLandscape()
+                                    && (mLastImeTarget.asBinder()
+                                    == mSplits.mSecondary.token.asBinder());
+                        } catch (RemoteException e) {
+                            Slog.w(TAG, "Failed to get IME target", e);
+                        }
+                    }
+                    if (!mShouldAdjustForIme) {
+                        setAdjustedForIme(false);
+                        return;
+                    }
+                    mView.setAdjustedForIme(showing, showing
+                            ? DisplayImeController.ANIMATION_DURATION_SHOW_MS
+                            : DisplayImeController.ANIMATION_DURATION_HIDE_MS);
+                    // Reposition the server's secondary split position so that it evaluates
+                    // insets properly.
+                    WindowContainerTransaction wct = new WindowContainerTransaction();
+                    if (showing) {
+                        mSplitLayout.updateAdjustedBounds(finalImeTop, imeTop, finalImeTop);
+                        wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mAdjustedSecondary);
+                    } else {
+                        wct.setBounds(mSplits.mSecondary.token, mSplitLayout.mSecondary);
+                    }
+                    try {
+                        ActivityTaskManager.getTaskOrganizerController()
+                                .applyContainerTransaction(wct, null /* organizer */);
+                    } catch (RemoteException e) {
+                    }
+                    setAdjustedForIme(showing);
+                }
+
+                @Override
+                public void onImePositionChanged(int displayId, int imeTop,
+                        SurfaceControl.Transaction t) {
+                    if (!mShouldAdjustForIme) {
+                        return;
+                    }
+                    mSplitLayout.updateAdjustedBounds(imeTop, mStartTop, mFinalTop);
+                    mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary,
+                            mSplitLayout.mAdjustedSecondary);
+                    final boolean showing = mFinalTop < mStartTop;
+                    final float progress = ((float) (imeTop - mStartTop)) / (mFinalTop - mStartTop);
+                    final float fraction = showing ? progress : 1.f - progress;
+                    mView.setResizeDimLayer(t, true /* primary */, fraction * 0.3f);
+                }
+
+                @Override
+                public void onImeEndPositioning(int displayId, int imeTop,
+                        boolean showing, SurfaceControl.Transaction t) {
+                    if (!mShouldAdjustForIme) {
+                        return;
+                    }
+                    mSplitLayout.updateAdjustedBounds(imeTop, mStartTop, mFinalTop);
+                    mView.resizeSplitSurfaces(t, mSplitLayout.mAdjustedPrimary,
+                            mSplitLayout.mAdjustedSecondary);
+                    mView.setResizeDimLayer(t, true /* primary */, showing ? 0.3f : 0.f);
+                }
+            };
+
+    public Divider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy,
+            DisplayController displayController, SystemWindows systemWindows,
+            DisplayImeController imeController, Handler handler,
+            KeyguardStateController keyguardStateController, TransactionPool transactionPool) {
         super(context);
+        mDisplayController = displayController;
+        mSystemWindows = systemWindows;
+        mImeController = imeController;
+        mHandler = handler;
+        mKeyguardStateController = keyguardStateController;
         mRecentsOptionalLazy = recentsOptionalLazy;
+        mForcedResizableController = new ForcedResizableInfoActivityController(context, this);
+        mTransactionPool = transactionPool;
     }
 
     @Override
     public void start() {
-        mWindowManager = new DividerWindowManager(mContext);
-        update(mContext.getResources().getConfiguration());
-        mDockDividerVisibilityListener = new DockDividerVisibilityListener();
-        try {
-            WindowManagerGlobal.getWindowManagerService().registerDockedStackListener(
-                    mDockDividerVisibilityListener);
-        } catch (Exception e) {
-            Log.e(TAG, "Failed to register docked stack listener", e);
-        }
-        mForcedResizableController = new ForcedResizableInfoActivityController(mContext);
+        mWindowManager = new DividerWindowManager(mSystemWindows);
+        mDisplayController.addDisplayWindowListener(this);
+        // Hide the divider when keyguard is showing. Even though keyguard/statusbar is above
+        // everything, it is actually transparent except for notifications, so we still need to
+        // hide any surfaces that are below it.
+        // TODO(b/148906453): Figure out keyguard dismiss animation for divider view.
+        mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
+            @Override
+            public void onUnlockedChanged() {
+
+            }
+
+            @Override
+            public void onKeyguardShowingChanged() {
+                if (!inSplitMode() || mView == null) {
+                    return;
+                }
+                mView.setHidden(mKeyguardStateController.isShowing());
+            }
+
+            @Override
+            public void onKeyguardFadingAwayChanged() {
+
+            }
+        });
+        // Don't initialize the divider or anything until we get the default display.
     }
 
     @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
+    public void onDisplayAdded(int displayId) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+                mDisplayController.getDisplayLayout(displayId), mSplits);
+        mImeController.addPositionProcessor(mImePositionProcessor);
+        mDisplayController.addDisplayChangingController(mRotationController);
+        try {
+            mSplits.init(ActivityTaskManager.getTaskOrganizerController(), mSurfaceSession);
+            // Set starting tile bounds based on middle target
+            final WindowContainerTransaction tct = new WindowContainerTransaction();
+            int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+            mSplitLayout.resizeSplits(midPos, tct);
+            ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct,
+                    null /* organizer */);
+        } catch (Exception e) {
+            Slog.e(TAG, "Failed to register docked stack listener", e);
+        }
+        update(mDisplayController.getDisplayContext(displayId).getResources().getConfiguration());
+    }
+
+    @Override
+    public void onDisplayConfigurationChanged(int displayId, Configuration newConfig) {
+        if (displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+        mSplitLayout = new SplitDisplayLayout(mDisplayController.getDisplayContext(displayId),
+                mDisplayController.getDisplayLayout(displayId), mSplits);
+        if (mRotateSplitLayout == null) {
+            int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+            final WindowContainerTransaction tct = new WindowContainerTransaction();
+            mSplitLayout.resizeSplits(midPos, tct);
+            try {
+                ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(tct,
+                        null /* organizer */);
+            } catch (RemoteException e) {
+            }
+        } else if (mRotateSplitLayout != null
+                && mSplitLayout.mDisplayLayout.rotation()
+                        == mRotateSplitLayout.mDisplayLayout.rotation()) {
+            mSplitLayout.mPrimary = new Rect(mRotateSplitLayout.mPrimary);
+            mSplitLayout.mSecondary = new Rect(mRotateSplitLayout.mSecondary);
+            mRotateSplitLayout = null;
+        }
         update(newConfig);
     }
 
+    Handler getHandler() {
+        return mHandler;
+    }
+
     public DividerView getView() {
         return mView;
     }
@@ -92,18 +307,25 @@
         return mHomeStackResizable;
     }
 
+    /** {@code true} if this is visible */
+    public boolean inSplitMode() {
+        return mView != null && mView.getVisibility() == View.VISIBLE;
+    }
+
     private void addDivider(Configuration configuration) {
+        Context dctx = mDisplayController.getDisplayContext(mContext.getDisplayId());
         mView = (DividerView)
-                LayoutInflater.from(mContext).inflate(R.layout.docked_stack_divider, null);
-        mView.injectDependencies(mWindowManager, mDividerState, this);
+                LayoutInflater.from(dctx).inflate(R.layout.docked_stack_divider, null);
+        DisplayLayout displayLayout = mDisplayController.getDisplayLayout(mContext.getDisplayId());
+        mView.injectDependencies(mWindowManager, mDividerState, this, mSplits, mSplitLayout);
         mView.setVisibility(mVisible ? View.VISIBLE : View.INVISIBLE);
         mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
-        final int size = mContext.getResources().getDimensionPixelSize(
+        final int size = dctx.getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
         final boolean landscape = configuration.orientation == ORIENTATION_LANDSCAPE;
-        final int width = landscape ? size : MATCH_PARENT;
-        final int height = landscape ? MATCH_PARENT : size;
-        mWindowManager.add(mView, width, height);
+        final int width = landscape ? size : displayLayout.width();
+        final int height = landscape ? displayLayout.height() : size;
+        mWindowManager.add(mView, width, height, mContext.getDisplayId());
     }
 
     private void removeDivider() {
@@ -116,65 +338,86 @@
     private void update(Configuration configuration) {
         removeDivider();
         addDivider(configuration);
-        if (mMinimized) {
+        if (mMinimized && mView != null) {
             mView.setMinimizedDockStack(true, mHomeStackResizable);
             updateTouchable();
         }
     }
 
-    private void updateVisibility(final boolean visible) {
-        mView.post(new Runnable() {
-            @Override
-            public void run() {
-                if (mVisible != visible) {
-                    mVisible = visible;
-                    mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
+    void updateVisibility(final boolean visible) {
+        if (mVisible != visible) {
+            mVisible = visible;
+            mView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
 
-                    // Update state because animations won't finish.
-                    mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
-                }
+            if (visible) {
+                mView.enterSplitMode(mHomeStackResizable);
+                // Update state because animations won't finish.
+                mView.setMinimizedDockStack(mMinimized, mHomeStackResizable);
+            } else {
+                mView.exitSplitMode();
+                // un-minimize so that next entry triggers minimize anim.
+                mView.setMinimizedDockStack(false /* minimized */, mHomeStackResizable);
             }
-        });
+            // Notify existence listeners
+            synchronized (mDockedStackExistsListeners) {
+                mDockedStackExistsListeners.removeIf(wf -> {
+                    Consumer<Boolean> l = wf.get();
+                    if (l != null) l.accept(visible);
+                    return l == null;
+                });
+            }
+        }
+    }
+
+    private void setHomeStackResizable(boolean resizable) {
+        if (mHomeStackResizable == resizable) {
+            return;
+        }
+        mHomeStackResizable = resizable;
+        if (!inSplitMode()) {
+            return;
+        }
+        WindowManagerProxy.applyHomeTasksMinimized(mSplitLayout, mSplits.mSecondary.token);
     }
 
     private void updateMinimizedDockedStack(final boolean minimized, final long animDuration,
             final boolean isHomeStackResizable) {
-        mView.post(new Runnable() {
-            @Override
-            public void run() {
-                mHomeStackResizable = isHomeStackResizable;
-                if (mMinimized != minimized) {
-                    mMinimized = minimized;
-                    updateTouchable();
-                    if (animDuration > 0) {
-                        mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable);
-                    } else {
-                        mView.setMinimizedDockStack(minimized, isHomeStackResizable);
-                    }
-                }
+        setHomeStackResizable(isHomeStackResizable);
+        if (animDuration > 0) {
+            mView.setMinimizedDockStack(minimized, animDuration, isHomeStackResizable);
+        } else {
+            mView.setMinimizedDockStack(minimized, isHomeStackResizable);
+        }
+        updateTouchable();
+    }
+
+    /** Switch to minimized state if appropriate */
+    public void setMinimized(final boolean minimized) {
+        mHandler.post(() -> {
+            if (!inSplitMode()) {
+                return;
             }
+            if (mMinimized == minimized) {
+                return;
+            }
+            mMinimized = minimized;
+            mView.setMinimizedDockStack(minimized, getAnimDuration(), mHomeStackResizable);
+            updateTouchable();
         });
     }
 
-    private void notifyDockedStackExistsChanged(final boolean exists) {
-        mView.post(new Runnable() {
-            @Override
-            public void run() {
-                mForcedResizableController.notifyDockedStackExistsChanged(exists);
-            }
-        });
+    void setAdjustedForIme(boolean adjustedForIme) {
+        if (mAdjustedForIme == adjustedForIme) {
+            return;
+        }
+        mAdjustedForIme = adjustedForIme;
+        updateTouchable();
     }
 
     private void updateTouchable() {
         mWindowManager.setTouchable((mHomeStackResizable || !mMinimized) && !mAdjustedForIme);
     }
 
-    public void onRecentsActivityStarting() {
-        if (mView != null) {
-            mView.onRecentsActivityStarting();
-        }
-    }
-
     /**
      * Workaround for b/62528361, at the time recents has drawn, it may happen before a
      * configuration change to the Divider, and internally, the event will be posted to the
@@ -206,6 +449,9 @@
     }
 
     public void onAppTransitionFinished() {
+        if (mView == null) {
+            return;
+        }
         mForcedResizableController.onAppTransitionFinished();
     }
 
@@ -231,46 +477,66 @@
         pw.print("  mAdjustedForIme="); pw.println(mAdjustedForIme);
     }
 
-    class DockDividerVisibilityListener extends IDockedStackListener.Stub {
+    long getAnimDuration() {
+        float transitionScale = Settings.Global.getFloat(mContext.getContentResolver(),
+                Settings.Global.TRANSITION_ANIMATION_SCALE,
+                mContext.getResources().getFloat(
+                        com.android.internal.R.dimen
+                                .config_appTransitionAnimationDurationScaleDefault));
+        final long transitionDuration = DEFAULT_APP_TRANSITION_DURATION;
+        return (long) (transitionDuration * transitionScale);
+    }
 
-        @Override
-        public void onDividerVisibilityChanged(boolean visible) throws RemoteException {
-            updateVisibility(visible);
+    /** Register a listener that gets called whenever the existence of the divider changes */
+    public void registerInSplitScreenListener(Consumer<Boolean> listener) {
+        listener.accept(inSplitMode());
+        synchronized (mDockedStackExistsListeners) {
+            mDockedStackExistsListeners.add(new WeakReference<>(listener));
         }
+    }
 
-        @Override
-        public void onDockedStackExistsChanged(boolean exists) throws RemoteException {
-            notifyDockedStackExistsChanged(exists);
+    void startEnterSplit() {
+        // Set resizable directly here because applyEnterSplit already resizes home stack.
+        mHomeStackResizable = WindowManagerProxy.applyEnterSplit(mSplits, mSplitLayout);
+    }
+
+    void ensureMinimizedSplit() {
+        final boolean wasMinimized = mMinimized;
+        mMinimized = true;
+        setHomeStackResizable(mSplits.mSecondary.isResizable());
+        if (!inSplitMode()) {
+            // Wasn't in split-mode yet, so enter now.
+            if (DEBUG) {
+                Log.d(TAG, " entering split mode with minimized=true");
+            }
+            updateVisibility(true /* visible */);
+        } else if (!wasMinimized) {
+            if (DEBUG) {
+                Log.d(TAG, " in split mode, but minimizing ");
+            }
+            // Was already in split-mode, update just minimized state.
+            updateMinimizedDockedStack(mMinimized, getAnimDuration(),
+                    mHomeStackResizable);
         }
+    }
 
-        @Override
-        public void onDockedStackMinimizedChanged(boolean minimized, long animDuration,
-                boolean isHomeStackResizable) throws RemoteException {
-            mHomeStackResizable = isHomeStackResizable;
-            updateMinimizedDockedStack(minimized, animDuration, isHomeStackResizable);
+    void ensureNormalSplit() {
+        if (!inSplitMode()) {
+            // Wasn't in split-mode, so enter now.
+            if (DEBUG) {
+                Log.d(TAG, " enter split mode unminimized ");
+            }
+            mMinimized = false;
+            updateVisibility(true /* visible */);
         }
-
-        @Override
-        public void onAdjustedForImeChanged(boolean adjustedForIme, long animDuration)
-                throws RemoteException {
-            mView.post(() -> {
-                if (mAdjustedForIme != adjustedForIme) {
-                    mAdjustedForIme = adjustedForIme;
-                    updateTouchable();
-                    if (!mMinimized) {
-                        if (animDuration > 0) {
-                            mView.setAdjustedForIme(adjustedForIme, animDuration);
-                        } else {
-                            mView.setAdjustedForIme(adjustedForIme);
-                        }
-                    }
-                }
-            });
-        }
-
-        @Override
-        public void onDockSideChanged(final int newDockSide) throws RemoteException {
-            mView.post(() -> mView.notifyDockSideChanged(newDockSide));
+        if (mMinimized) {
+            // Was in minimized state, so leave that.
+            if (DEBUG) {
+                Log.d(TAG, " in split mode already, but unminimizing ");
+            }
+            mMinimized = false;
+            updateMinimizedDockedStack(mMinimized, getAnimDuration(),
+                    mHomeStackResizable);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
index 49f4d5e..3b7f315 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerModule.java
@@ -17,8 +17,15 @@
 package com.android.systemui.stackdivider;
 
 import android.content.Context;
+import android.os.Handler;
 
+import com.android.systemui.TransactionPool;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.recents.Recents;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.wm.DisplayController;
+import com.android.systemui.wm.DisplayImeController;
+import com.android.systemui.wm.SystemWindows;
 
 import java.util.Optional;
 
@@ -35,7 +42,11 @@
 public class DividerModule {
     @Singleton
     @Provides
-    static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy) {
-        return new Divider(context, recentsOptionalLazy);
+    static Divider provideDivider(Context context, Optional<Lazy<Recents>> recentsOptionalLazy,
+            DisplayController displayController, SystemWindows systemWindows,
+            DisplayImeController imeController, @Main Handler handler,
+            KeyguardStateController keyguardStateController, TransactionPool transactionPool) {
+        return new Divider(context, recentsOptionalLazy, displayController, systemWindows,
+                imeController, handler, keyguardStateController, transactionPool);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 9fe6e84..375d9bb 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -16,12 +16,8 @@
 
 package com.android.systemui.stackdivider;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.PointerIcon.TYPE_HORIZONTAL_DOUBLE_ARROW;
 import static android.view.PointerIcon.TYPE_VERTICAL_DOUBLE_ARROW;
-import static android.view.WindowManager.DOCKED_LEFT;
 import static android.view.WindowManager.DOCKED_RIGHT;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 
@@ -40,10 +36,11 @@
 import android.util.AttributeSet;
 import android.view.Choreographer;
 import android.view.Display;
-import android.view.DisplayInfo;
 import android.view.InsetsState;
 import android.view.MotionEvent;
 import android.view.PointerIcon;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.Transaction;
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.View.OnTouchListener;
@@ -75,6 +72,7 @@
  */
 public class DividerView extends FrameLayout implements OnTouchListener,
         OnComputeInternalInsetsListener {
+    private static final String TAG = "DividerView";
 
     public interface DividerCallbacks {
         void onDraggingStart();
@@ -123,14 +121,11 @@
     private int mTouchSlop;
     private boolean mBackgroundLifted;
     private boolean mIsInMinimizeInteraction;
-    private SnapTarget mSnapTargetBeforeMinimized;
+    SnapTarget mSnapTargetBeforeMinimized;
 
     private int mDividerInsets;
     private final Display mDefaultDisplay;
-    private int mDisplayWidth;
-    private int mDisplayHeight;
-    private int mDisplayRotation;
-    private int mDividerWindowWidth;
+
     private int mDividerSize;
     private int mTouchElevation;
     private int mLongPressEntraceAnimDuration;
@@ -147,8 +142,7 @@
     private DividerWindowManager mWindowManager;
     private VelocityTracker mVelocityTracker;
     private FlingAnimationUtils mFlingAnimationUtils;
-    private DividerSnapAlgorithm mSnapAlgorithm;
-    private DividerSnapAlgorithm mMinimizedSnapAlgorithm;
+    private SplitDisplayLayout mSplitLayout;
     private DividerCallbacks mCallback;
     private final Rect mStableInsets = new Rect();
 
@@ -163,6 +157,10 @@
     private DividerState mState;
     private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
 
+    private SplitScreenTaskOrganizer mTiles;
+    boolean mFirstLayout = true;
+    int mDividerPositionX;
+    int mDividerPositionY;
 
     // The view is removed or in the process of been removed from the system.
     private boolean mRemoved;
@@ -172,7 +170,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_RESIZE_STACK:
-                    resizeStack(msg.arg1, msg.arg2, (SnapTarget) msg.obj);
+                    resizeStackSurfaces(msg.arg1, msg.arg2, (SnapTarget) msg.obj);
                     break;
                 default:
                     super.handleMessage(msg);
@@ -228,16 +226,17 @@
         public boolean performAccessibilityAction(View host, int action, Bundle args) {
             int currentPosition = getCurrentPosition();
             SnapTarget nextTarget = null;
+            DividerSnapAlgorithm snapAlgorithm = mSplitLayout.getSnapAlgorithm();
             if (action == R.id.action_move_tl_full) {
-                nextTarget = mSnapAlgorithm.getDismissEndTarget();
+                nextTarget = snapAlgorithm.getDismissEndTarget();
             } else if (action == R.id.action_move_tl_70) {
-                nextTarget = mSnapAlgorithm.getLastSplitTarget();
+                nextTarget = snapAlgorithm.getLastSplitTarget();
             } else if (action == R.id.action_move_tl_50) {
-                nextTarget = mSnapAlgorithm.getMiddleTarget();
+                nextTarget = snapAlgorithm.getMiddleTarget();
             } else if (action == R.id.action_move_tl_30) {
-                nextTarget = mSnapAlgorithm.getFirstSplitTarget();
+                nextTarget = snapAlgorithm.getFirstSplitTarget();
             } else if (action == R.id.action_move_rb_full) {
-                nextTarget = mSnapAlgorithm.getDismissStartTarget();
+                nextTarget = snapAlgorithm.getDismissStartTarget();
             }
             if (nextTarget != null) {
                 startDragging(true /* animate */, false /* touching */);
@@ -284,11 +283,11 @@
         mBackground = findViewById(R.id.docked_divider_background);
         mMinimizedShadow = findViewById(R.id.minimized_dock_shadow);
         mHandle.setOnTouchListener(this);
-        mDividerWindowWidth = getResources().getDimensionPixelSize(
+        final int dividerWindowWidth = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_thickness);
         mDividerInsets = getResources().getDimensionPixelSize(
                 com.android.internal.R.dimen.docked_stack_divider_insets);
-        mDividerSize = mDividerWindowWidth - 2 * mDividerInsets;
+        mDividerSize = dividerWindowWidth - 2 * mDividerInsets;
         mTouchElevation = getResources().getDimensionPixelSize(
                 R.dimen.docked_stack_divider_lift_elevation);
         mLongPressEntraceAnimDuration = getResources().getInteger(
@@ -296,7 +295,6 @@
         mGrowRecents = getResources().getBoolean(R.bool.recents_grow_in_multiwindow);
         mTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
         mFlingAnimationUtils = new FlingAnimationUtils(getResources().getDisplayMetrics(), 0.3f);
-        updateDisplayInfo();
         boolean landscape = getResources().getConfiguration().orientation
                 == Configuration.ORIENTATION_LANDSCAPE;
         mHandle.setPointerIcon(PointerIcon.getSystemIcon(getContext(),
@@ -314,6 +312,7 @@
                 && !mIsInMinimizeInteraction) {
             saveSnapTargetBeforeMinimized(mSnapTargetBeforeMinimized);
         }
+        mFirstLayout = true;
     }
 
     void onDividerRemoved() {
@@ -341,17 +340,17 @@
                 || mStableInsets.bottom != insets.getStableInsetBottom()) {
             mStableInsets.set(insets.getStableInsetLeft(), insets.getStableInsetTop(),
                     insets.getStableInsetRight(), insets.getStableInsetBottom());
-            if (mSnapAlgorithm != null || mMinimizedSnapAlgorithm != null) {
-                mSnapAlgorithm = null;
-                mMinimizedSnapAlgorithm = null;
-                initializeSnapAlgorithm();
-            }
         }
         return super.onApplyWindowInsets(insets);
     }
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mFirstLayout) {
+            // Wait for first layout so that the ViewRootImpl surface has been created.
+            initializeSurfaceState();
+            mFirstLayout = false;
+        }
         super.onLayout(changed, left, top, right, bottom);
         int minimizeLeft = 0;
         int minimizeTop = 0;
@@ -372,19 +371,16 @@
     }
 
     public void injectDependencies(DividerWindowManager windowManager, DividerState dividerState,
-            DividerCallbacks callback) {
+            DividerCallbacks callback, SplitScreenTaskOrganizer tiles, SplitDisplayLayout sdl) {
         mWindowManager = windowManager;
         mState = dividerState;
         mCallback = callback;
-
-        // Set the previous position ratio before minimized state after attaching this divider
-        if (mStableInsets.isEmpty()) {
-            WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
-        }
+        mTiles = tiles;
+        mSplitLayout = sdl;
 
         if (mState.mRatioPositionBeforeMinimized == 0) {
             // Set the middle target as the initial state
-            mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
+            mSnapTargetBeforeMinimized = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
         } else {
             repositionSnapTargetBeforeMinimized();
         }
@@ -411,18 +407,35 @@
         return mOtherTaskRect;
     }
 
+    private boolean inSplitMode() {
+        return getVisibility() == VISIBLE;
+    }
+
+    /** Unlike setVisible, this directly hides the surface without changing view visibility. */
+    void setHidden(boolean hidden) {
+        post(() -> {
+            final SurfaceControl sc = getWindowSurfaceControl();
+            if (sc == null) {
+                return;
+            }
+            Transaction t = mTiles.getTransaction();
+            if (hidden) {
+                t.hide(sc);
+            } else {
+                t.show(sc);
+            }
+            t.apply();
+            mTiles.releaseTransaction(t);
+        });
+    }
+
     public boolean startDragging(boolean animate, boolean touching) {
         cancelFlingAnimation();
         if (touching) {
             mHandle.setTouching(true, animate);
         }
-        mDockSide = mWindowManagerProxy.getDockSide();
+        mDockSide = mSplitLayout.getPrimarySplitSide();
 
-        // Update snap algorithm if rotation has occurred
-        if (mDisplayRotation != mDefaultDisplay.getRotation()) {
-            updateDisplayInfo();
-        }
-        initializeSnapAlgorithm();
         mWindowManagerProxy.setResizing(true);
         if (touching) {
             mWindowManager.setSlippery(false);
@@ -431,7 +444,7 @@
         if (mCallback != null) {
             mCallback.onDraggingStart();
         }
-        return mDockSide != WindowManager.DOCKED_INVALID;
+        return inSplitMode();
     }
 
     public void stopDragging(int position, float velocity, boolean avoidDismissStart,
@@ -467,38 +480,22 @@
     }
 
     private void updateDockSide() {
-        mDockSide = mWindowManagerProxy.getDockSide();
+        mDockSide = mSplitLayout.getPrimarySplitSide();
         mMinimizedShadow.setDockSide(mDockSide);
     }
 
-    private void initializeSnapAlgorithm() {
-        if (mSnapAlgorithm == null) {
-            mSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(), mDisplayWidth,
-                    mDisplayHeight, mDividerSize, isHorizontalDivision(), mStableInsets, mDockSide);
-            if (mSnapTargetBeforeMinimized != null && mSnapTargetBeforeMinimized.isMiddleTarget) {
-                mSnapTargetBeforeMinimized = mSnapAlgorithm.getMiddleTarget();
-            }
-        }
-        if (mMinimizedSnapAlgorithm == null) {
-            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(getContext().getResources(),
-                    mDisplayWidth, mDisplayHeight, mDividerSize, isHorizontalDivision(),
-                    mStableInsets, mDockSide, mDockedStackMinimized && mHomeStackResizable);
-        }
-    }
-
     public DividerSnapAlgorithm getSnapAlgorithm() {
-        initializeSnapAlgorithm();
-        return mDockedStackMinimized && mHomeStackResizable ? mMinimizedSnapAlgorithm :
-                mSnapAlgorithm;
+        return mDockedStackMinimized
+                && mHomeStackResizable ? mSplitLayout.getMinimizedSnapAlgorithm()
+                        : mSplitLayout.getSnapAlgorithm();
     }
 
     public int getCurrentPosition() {
-        getLocationOnScreen(mTempInt2);
-        if (isHorizontalDivision()) {
-            return mTempInt2[1] + mDividerInsets;
-        } else {
-            return mTempInt2[0] + mDividerInsets;
-        }
+        return isHorizontalDivision() ? mDividerPositionY : mDividerPositionX;
+    }
+
+    public boolean isMinimized() {
+        return mDockedStackMinimized;
     }
 
     @Override
@@ -557,25 +554,25 @@
     }
 
     private void logResizeEvent(SnapTarget snapTarget) {
-        if (snapTarget == mSnapAlgorithm.getDismissStartTarget()) {
+        if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissStartTarget()) {
             MetricsLogger.action(
                     mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideTopLeft(mDockSide)
                             ? LOG_VALUE_UNDOCK_MAX_OTHER
                             : LOG_VALUE_UNDOCK_MAX_DOCKED);
-        } else if (snapTarget == mSnapAlgorithm.getDismissEndTarget()) {
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getDismissEndTarget()) {
             MetricsLogger.action(
                     mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_MAX, dockSideBottomRight(mDockSide)
                             ? LOG_VALUE_UNDOCK_MAX_OTHER
                             : LOG_VALUE_UNDOCK_MAX_DOCKED);
-        } else if (snapTarget == mSnapAlgorithm.getMiddleTarget()) {
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getMiddleTarget()) {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
                     LOG_VALUE_RESIZE_50_50);
-        } else if (snapTarget == mSnapAlgorithm.getFirstSplitTarget()) {
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getFirstSplitTarget()) {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
                     dockSideTopLeft(mDockSide)
                             ? LOG_VALUE_RESIZE_DOCKED_SMALLER
                             : LOG_VALUE_RESIZE_DOCKED_LARGER);
-        } else if (snapTarget == mSnapAlgorithm.getLastSplitTarget()) {
+        } else if (snapTarget == mSplitLayout.getSnapAlgorithm().getLastSplitTarget()) {
             MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_RESIZE,
                     dockSideTopLeft(mDockSide)
                             ? LOG_VALUE_RESIZE_DOCKED_LARGER
@@ -625,12 +622,16 @@
                         : snapTarget.taskPosition,
                 snapTarget));
         Runnable endAction = () -> {
-            commitSnapFlags(snapTarget);
+            boolean dismissed = commitSnapFlags(snapTarget);
             mWindowManagerProxy.setResizing(false);
             updateDockSide();
             mCurrentAnimator = null;
             mEntranceAnimationRunning = false;
             mExitAnimationRunning = false;
+            if (!dismissed) {
+                WindowManagerProxy.applyResizeSplits((mIsInMinimizeInteraction
+                        ? mSnapTargetBeforeMinimized : snapTarget).position, mSplitLayout);
+            }
             if (mCallback != null) {
                 mCallback.onDraggingEnd();
             }
@@ -642,12 +643,13 @@
                 // position isn't negative.
                 final SnapTarget saveTarget;
                 if (snapTarget.position < 0) {
-                    saveTarget = mSnapAlgorithm.getMiddleTarget();
+                    saveTarget = mSplitLayout.getSnapAlgorithm().getMiddleTarget();
                 } else {
                     saveTarget = snapTarget;
                 }
-                if (saveTarget.position != mSnapAlgorithm.getDismissEndTarget().position
-                        && saveTarget.position != mSnapAlgorithm.getDismissStartTarget().position) {
+                final DividerSnapAlgorithm snapAlgo = mSplitLayout.getSnapAlgorithm();
+                if (saveTarget.position != snapAlgo.getDismissEndTarget().position
+                        && saveTarget.position != snapAlgo.getDismissStartTarget().position) {
                     saveSnapTargetBeforeMinimized(saveTarget);
                 }
             }
@@ -701,11 +703,11 @@
         }
     }
 
-    private void commitSnapFlags(SnapTarget target) {
+    private boolean commitSnapFlags(SnapTarget target) {
         if (target.flag == SnapTarget.FLAG_NONE) {
-            return;
+            return false;
         }
-        boolean dismissOrMaximize;
+        final boolean dismissOrMaximize;
         if (target.flag == SnapTarget.FLAG_DISMISS_START) {
             dismissOrMaximize = mDockSide == WindowManager.DOCKED_LEFT
                     || mDockSide == WindowManager.DOCKED_TOP;
@@ -713,12 +715,13 @@
             dismissOrMaximize = mDockSide == WindowManager.DOCKED_RIGHT
                     || mDockSide == WindowManager.DOCKED_BOTTOM;
         }
-        if (dismissOrMaximize) {
-            mWindowManagerProxy.dismissDockedStack();
-        } else {
-            mWindowManagerProxy.maximizeDockedStack();
-        }
-        mWindowManagerProxy.setResizeDimLayer(false, WINDOWING_MODE_UNDEFINED, 0f);
+        mWindowManagerProxy.dismissOrMaximizeDocked(mTiles, dismissOrMaximize);
+        Transaction t = mTiles.getTransaction();
+        setResizeDimLayer(t, true /* primary */, 0f);
+        setResizeDimLayer(t, false /* primary */, 0f);
+        t.apply();
+        mTiles.releaseTransaction(t);
+        return true;
     }
 
     private void liftBackground() {
@@ -765,6 +768,28 @@
         mBackgroundLifted = false;
     }
 
+    private void initializeSurfaceState() {
+        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+        // Recalculate the split-layout's internal tile bounds
+        mSplitLayout.resizeSplits(midPos);
+        Transaction t = mTiles.getTransaction();
+        if (mDockedStackMinimized) {
+            int position = mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget().position;
+            calculateBoundsForPosition(position, mDockSide, mDockedRect);
+            calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+                    mOtherRect);
+            mDividerPositionX = mDividerPositionY = position;
+            resizeSplitSurfaces(t, mDockedRect, mSplitLayout.mPrimary,
+                    mOtherRect, mSplitLayout.mSecondary);
+        } else {
+            resizeSplitSurfaces(t, mSplitLayout.mPrimary, null,
+                    mSplitLayout.mSecondary, null);
+        }
+        setResizeDimLayer(t, true /* primary */, 0.f /* alpha */);
+        setResizeDimLayer(t, false /* secondary */, 0.f /* alpha */);
+        t.apply();
+        mTiles.releaseTransaction(t);
+    }
 
     public void setMinimizedDockStack(boolean minimized, boolean isHomeStackResizable) {
         mHomeStackResizable = isHomeStackResizable;
@@ -789,15 +814,11 @@
             mDockedStackMinimized = minimized;
         } else if (mDockedStackMinimized != minimized) {
             mDockedStackMinimized = minimized;
-            if (mDisplayRotation != mDefaultDisplay.getRotation()) {
+            if (mSplitLayout.mDisplayLayout.rotation() != mDefaultDisplay.getRotation()) {
                 // Splitscreen to minimize is about to starts after rotating landscape to seascape,
                 // update insets, display info and snap algorithm targets
                 WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
                 repositionSnapTargetBeforeMinimized();
-                updateDisplayInfo();
-            } else {
-                mMinimizedSnapAlgorithm = null;
-                initializeSnapAlgorithm();
             }
             if (mIsInMinimizeInteraction != minimized || mCurrentAnimator != null) {
                 cancelFlingAnimation();
@@ -805,15 +826,64 @@
                     // Relayout to recalculate the divider shadow when minimizing
                     requestLayout();
                     mIsInMinimizeInteraction = true;
-                    resizeStack(mMinimizedSnapAlgorithm.getMiddleTarget());
+                    resizeStackSurfaces(mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget());
                 } else {
-                    resizeStack(mSnapTargetBeforeMinimized);
+                    resizeStackSurfaces(mSnapTargetBeforeMinimized);
                     mIsInMinimizeInteraction = false;
                 }
             }
         }
     }
 
+    void enterSplitMode(boolean isHomeStackResizable) {
+        post(() -> {
+            final SurfaceControl sc = getWindowSurfaceControl();
+            if (sc == null) {
+                return;
+            }
+            Transaction t = mTiles.getTransaction();
+            t.show(sc).apply();
+            mTiles.releaseTransaction(t);
+        });
+        if (isHomeStackResizable) {
+            SnapTarget miniMid = mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget();
+            if (mDockedStackMinimized) {
+                mDividerPositionY = mDividerPositionX = miniMid.position;
+            }
+        }
+    }
+
+    /**
+     * Tries to grab a surface control from ViewRootImpl. If this isn't available for some reason
+     * (ie. the window isn't ready yet), it will get the surfacecontrol that the WindowlessWM has
+     * assigned to it.
+     */
+    private SurfaceControl getWindowSurfaceControl() {
+        if (getViewRootImpl() == null) {
+            return null;
+        }
+        SurfaceControl out = getViewRootImpl().getSurfaceControl();
+        if (out != null && out.isValid()) {
+            return out;
+        }
+        return mWindowManager.mSystemWindows.getViewSurface(this);
+    }
+
+    void exitSplitMode() {
+        // Reset tile bounds
+        post(() -> {
+            final SurfaceControl sc = getWindowSurfaceControl();
+            if (sc == null) {
+                return;
+            }
+            Transaction t = mTiles.getTransaction();
+            t.hide(sc).apply();
+            mTiles.releaseTransaction(t);
+        });
+        int midPos = mSplitLayout.getSnapAlgorithm().getMiddleTarget().position;
+        WindowManagerProxy.applyResizeSplits(midPos, mSplitLayout);
+    }
+
     public void setMinimizedDockStack(boolean minimized, long animDuration,
             boolean isHomeStackResizable) {
         mHomeStackResizable = isHomeStackResizable;
@@ -844,14 +914,12 @@
             mDockedStackMinimized = minimized;
         } else if (mDockedStackMinimized != minimized) {
             mIsInMinimizeInteraction = true;
-            mMinimizedSnapAlgorithm = null;
             mDockedStackMinimized = minimized;
-            initializeSnapAlgorithm();
             stopDragging(minimized
                             ? mSnapTargetBeforeMinimized.position
                             : getCurrentPosition(),
                     minimized
-                            ? mMinimizedSnapAlgorithm.getMiddleTarget()
+                            ? mSplitLayout.getMinimizedSnapAlgorithm().getMiddleTarget()
                             : mSnapTargetBeforeMinimized,
                     animDuration, Interpolators.FAST_OUT_SLOW_IN, 0);
             setAdjustedForIme(false, animDuration);
@@ -865,18 +933,6 @@
                 .start();
     }
 
-    public void setAdjustedForIme(boolean adjustedForIme) {
-        updateDockSide();
-        mHandle.setAlpha(adjustedForIme ? 0f : 1f);
-        if (!adjustedForIme) {
-            resetBackground();
-        } else if (mDockSide == WindowManager.DOCKED_TOP) {
-            mBackground.setPivotY(0);
-            mBackground.setScaleY(ADJUSTED_FOR_IME_SCALE);
-        }
-        mAdjustedForIme = adjustedForIme;
-    }
-
     public void setAdjustedForIme(boolean adjustedForIme, long animDuration) {
         updateDockSide();
         mHandle.animate()
@@ -902,7 +958,8 @@
     private void saveSnapTargetBeforeMinimized(SnapTarget target) {
         mSnapTargetBeforeMinimized = target;
         mState.mRatioPositionBeforeMinimized = (float) target.position /
-                (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth);
+                (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+                        : mSplitLayout.mDisplayLayout.width());
     }
 
     private void resetBackground() {
@@ -916,51 +973,17 @@
     @Override
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        updateDisplayInfo();
-    }
-
-    public void notifyDockSideChanged(int newDockSide) {
-        int oldDockSide = mDockSide;
-        mDockSide = newDockSide;
-        mMinimizedShadow.setDockSide(mDockSide);
-        requestLayout();
-
-        // Update the snap position to the new docked side with correct insets
-        WindowManagerWrapper.getInstance().getStableInsets(mStableInsets);
-        mMinimizedSnapAlgorithm = null;
-        initializeSnapAlgorithm();
-
-        if (oldDockSide == DOCKED_LEFT && mDockSide == DOCKED_RIGHT
-                || oldDockSide == DOCKED_RIGHT && mDockSide == DOCKED_LEFT) {
-            repositionSnapTargetBeforeMinimized();
-        }
-
-        // Landscape to seascape rotation requires minimized to resize docked app correctly
-        if (mHomeStackResizable && mDockedStackMinimized) {
-            resizeStack(mMinimizedSnapAlgorithm.getMiddleTarget());
-        }
     }
 
     private void repositionSnapTargetBeforeMinimized() {
         int position = (int) (mState.mRatioPositionBeforeMinimized *
-                (isHorizontalDivision() ? mDisplayHeight : mDisplayWidth));
-        mSnapAlgorithm = null;
-        initializeSnapAlgorithm();
+                (isHorizontalDivision() ? mSplitLayout.mDisplayLayout.height()
+                        : mSplitLayout.mDisplayLayout.width()));
 
         // Set the snap target before minimized but do not save until divider is attached and not
         // minimized because it does not know its minimized state yet.
-        mSnapTargetBeforeMinimized = mSnapAlgorithm.calculateNonDismissingSnapTarget(position);
-    }
-
-    private void updateDisplayInfo() {
-        mDisplayRotation = mDefaultDisplay.getRotation();
-        final DisplayInfo info = new DisplayInfo();
-        mDefaultDisplay.getDisplayInfo(info);
-        mDisplayWidth = info.logicalWidth;
-        mDisplayHeight = info.logicalHeight;
-        mSnapAlgorithm = null;
-        mMinimizedSnapAlgorithm = null;
-        initializeSnapAlgorithm();
+        mSnapTargetBeforeMinimized =
+                mSplitLayout.getSnapAlgorithm().calculateNonDismissingSnapTarget(position);
     }
 
     private int calculatePosition(int touchX, int touchY) {
@@ -994,8 +1017,9 @@
     }
 
     public void calculateBoundsForPosition(int position, int dockSide, Rect outRect) {
-        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect, mDisplayWidth,
-                mDisplayHeight, mDividerSize);
+        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outRect,
+                mSplitLayout.mDisplayLayout.width(), mSplitLayout.mDisplayLayout.height(),
+                mDividerSize);
     }
 
     public void resizeStackDelayed(int position, int taskPosition, SnapTarget taskSnapTarget) {
@@ -1005,16 +1029,60 @@
         mSfChoreographer.scheduleAtSfVsync(mHandler, message);
     }
 
-    private void resizeStack(SnapTarget taskSnapTarget) {
-        resizeStack(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget);
+    private void resizeStackSurfaces(SnapTarget taskSnapTarget) {
+        resizeStackSurfaces(taskSnapTarget.position, taskSnapTarget.position, taskSnapTarget);
     }
 
-    public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
+    void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect otherRect) {
+        resizeSplitSurfaces(t, dockedRect, null, otherRect, null);
+    }
+
+    private void resizeSplitSurfaces(Transaction t, Rect dockedRect, Rect dockedTaskRect,
+            Rect otherRect, Rect otherTaskRect) {
+        dockedTaskRect = dockedTaskRect == null ? dockedRect : dockedTaskRect;
+        otherTaskRect = otherTaskRect == null ? otherRect : otherTaskRect;
+
+        mDividerPositionX = dockedRect.right;
+        mDividerPositionY = dockedRect.bottom;
+
+        t.setPosition(mTiles.mPrimarySurface, dockedTaskRect.left, dockedTaskRect.top);
+        Rect crop = new Rect(dockedRect);
+        crop.offsetTo(-Math.min(dockedTaskRect.left - dockedRect.left, 0),
+                -Math.min(dockedTaskRect.top - dockedRect.top, 0));
+        t.setWindowCrop(mTiles.mPrimarySurface, crop);
+        t.setPosition(mTiles.mSecondarySurface, otherTaskRect.left, otherTaskRect.top);
+        crop.set(otherRect);
+        crop.offsetTo(-(otherTaskRect.left - otherRect.left),
+                -(otherTaskRect.top - otherRect.top));
+        t.setWindowCrop(mTiles.mSecondarySurface, crop);
+        final SurfaceControl dividerCtrl = getWindowSurfaceControl();
+        if (dividerCtrl != null) {
+            if (isHorizontalDivision()) {
+                t.setPosition(dividerCtrl, 0, mDividerPositionY - mDividerInsets);
+            } else {
+                t.setPosition(dividerCtrl, mDividerPositionX - mDividerInsets, 0);
+            }
+        }
+    }
+
+    void setResizeDimLayer(Transaction t, boolean primary, float alpha) {
+        SurfaceControl dim = primary ? mTiles.mPrimaryDim : mTiles.mSecondaryDim;
+        if (alpha <= 0.f) {
+            t.hide(dim);
+        } else {
+            t.setAlpha(dim, alpha);
+            t.show(dim);
+        }
+    }
+
+    void resizeStackSurfaces(int position, int taskPosition, SnapTarget taskSnapTarget) {
         if (mRemoved) {
             // This divider view has been removed so shouldn't have any additional influence.
             return;
         }
         calculateBoundsForPosition(position, mDockSide, mDockedRect);
+        calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
+                mOtherRect);
 
         if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
             return;
@@ -1025,6 +1093,7 @@
             mBackground.invalidate();
         }
 
+        Transaction t = mTiles.getTransaction();
         mLastResizeRect.set(mDockedRect);
         if (mHomeStackResizable && mIsInMinimizeInteraction) {
             calculateBoundsForPosition(mSnapTargetBeforeMinimized.position, mDockSide,
@@ -1037,8 +1106,10 @@
                 mDockedTaskRect.offset(Math.max(position, mStableInsets.left - mDividerSize)
                         - mDockedTaskRect.left + mDividerSize, 0);
             }
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedTaskRect,
-                    mOtherTaskRect, null);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect,
+                    mOtherTaskRect);
+            t.apply();
+            mTiles.releaseTransaction(t);
             return;
         }
 
@@ -1052,8 +1123,7 @@
             }
             calculateBoundsForPosition(taskPosition, DockedDividerUtils.invertDockSide(mDockSide),
                     mOtherTaskRect);
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, null,
-                    mOtherTaskRect, null);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
         } else if (mExitAnimationRunning && taskPosition != TASK_POSITION_SAME) {
             calculateBoundsForPosition(taskPosition, mDockSide, mDockedTaskRect);
             mDockedInsetRect.set(mDockedTaskRect);
@@ -1066,8 +1136,7 @@
             if (mDockSide == DOCKED_RIGHT) {
                 mDockedTaskRect.offset(position - mStableInsets.left + mDividerSize, 0);
             }
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedInsetRect,
-                    mOtherTaskRect, mOtherInsetRect);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
         } else if (taskPosition != TASK_POSITION_SAME) {
             calculateBoundsForPosition(position, DockedDividerUtils.invertDockSide(mDockSide),
                     mOtherRect);
@@ -1078,7 +1147,8 @@
                     restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
             calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
             calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
-            mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
+            mTmpRect.set(0, 0, mSplitLayout.mDisplayLayout.width(),
+                    mSplitLayout.mDisplayLayout.height());
             alignTopLeft(mDockedRect, mDockedTaskRect);
             alignTopLeft(mOtherRect, mOtherTaskRect);
             mDockedInsetRect.set(mDockedTaskRect);
@@ -1094,15 +1164,15 @@
                     taskPositionDocked);
             applyDismissingParallax(mOtherTaskRect, dockSideInverted, taskSnapTarget, position,
                     taskPositionOther);
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, mDockedTaskRect, mDockedInsetRect,
-                    mOtherTaskRect, mOtherInsetRect);
+            resizeSplitSurfaces(t, mDockedRect, mDockedTaskRect, mOtherRect, mOtherTaskRect);
         } else {
-            mWindowManagerProxy.resizeDockedStack(mDockedRect, null, null, null, null);
+            resizeSplitSurfaces(t, mDockedRect, null, mOtherRect, null);
         }
         SnapTarget closestDismissTarget = getSnapAlgorithm().getClosestDismissTarget(position);
         float dimFraction = getDimFraction(position, closestDismissTarget);
-        mWindowManagerProxy.setResizeDimLayer(dimFraction != 0f,
-                getWindowingModeForDismissTarget(closestDismissTarget), dimFraction);
+        setResizeDimLayer(t, isDismissTargetPrimary(closestDismissTarget), dimFraction);
+        t.apply();
+        mTiles.releaseTransaction(t);
     }
 
     private void applyExitAnimationParallax(Rect taskRect, int position) {
@@ -1156,10 +1226,12 @@
     private int restrictDismissingTaskPosition(int taskPosition, int dockSide,
             SnapTarget snapTarget) {
         if (snapTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(dockSide)) {
-            return Math.max(mSnapAlgorithm.getFirstSplitTarget().position, mStartPosition);
+            return Math.max(mSplitLayout.getSnapAlgorithm().getFirstSplitTarget().position,
+                    mStartPosition);
         } else if (snapTarget.flag == SnapTarget.FLAG_DISMISS_END
                 && dockSideBottomRight(dockSide)) {
-            return Math.min(mSnapAlgorithm.getLastSplitTarget().position, mStartPosition);
+            return Math.min(mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position,
+                    mStartPosition);
         } else {
             return taskPosition;
         }
@@ -1171,19 +1243,19 @@
     private void applyDismissingParallax(Rect taskRect, int dockSide, SnapTarget snapTarget,
             int position, int taskPosition) {
         float fraction = Math.min(1, Math.max(0,
-                mSnapAlgorithm.calculateDismissingFraction(position)));
+                mSplitLayout.getSnapAlgorithm().calculateDismissingFraction(position)));
         SnapTarget dismissTarget = null;
         SnapTarget splitTarget = null;
         int start = 0;
-        if (position <= mSnapAlgorithm.getLastSplitTarget().position
+        if (position <= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
                 && dockSideTopLeft(dockSide)) {
-            dismissTarget = mSnapAlgorithm.getDismissStartTarget();
-            splitTarget = mSnapAlgorithm.getFirstSplitTarget();
+            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
+            splitTarget = mSplitLayout.getSnapAlgorithm().getFirstSplitTarget();
             start = taskPosition;
-        } else if (position >= mSnapAlgorithm.getLastSplitTarget().position
+        } else if (position >= mSplitLayout.getSnapAlgorithm().getLastSplitTarget().position
                 && dockSideBottomRight(dockSide)) {
-            dismissTarget = mSnapAlgorithm.getDismissEndTarget();
-            splitTarget = mSnapAlgorithm.getLastSplitTarget();
+            dismissTarget = mSplitLayout.getSnapAlgorithm().getDismissEndTarget();
+            splitTarget = mSplitLayout.getSnapAlgorithm().getLastSplitTarget();
             start = splitTarget.position;
         }
         if (dismissTarget != null && fraction > 0f
@@ -1236,14 +1308,10 @@
         }
     }
 
-    private int getWindowingModeForDismissTarget(SnapTarget dismissTarget) {
-        if ((dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
+    private boolean isDismissTargetPrimary(SnapTarget dismissTarget) {
+        return (dismissTarget.flag == SnapTarget.FLAG_DISMISS_START && dockSideTopLeft(mDockSide))
                 || (dismissTarget.flag == SnapTarget.FLAG_DISMISS_END
-                        && dockSideBottomRight(mDockSide))) {
-            return WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-        } else {
-            return WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
-        }
+                        && dockSideBottomRight(mDockSide));
     }
 
     /**
@@ -1297,7 +1365,7 @@
     }
 
     void onDockedFirstAnimationFrame() {
-        saveSnapTargetBeforeMinimized(mSnapAlgorithm.getMiddleTarget());
+        saveSnapTargetBeforeMinimized(mSplitLayout.getSnapAlgorithm().getMiddleTarget());
     }
 
     void onDockedTopTask() {
@@ -1307,8 +1375,9 @@
         updateDockSide();
         mEntranceAnimationRunning = true;
 
-        resizeStack(calculatePositionForInsetBounds(), mSnapAlgorithm.getMiddleTarget().position,
-                mSnapAlgorithm.getMiddleTarget());
+        resizeStackSurfaces(calculatePositionForInsetBounds(),
+                mSplitLayout.getSnapAlgorithm().getMiddleTarget().position,
+                mSplitLayout.getSnapAlgorithm().getMiddleTarget());
     }
 
     void onRecentsDrawn() {
@@ -1337,13 +1406,12 @@
     }
 
     void onUndockingTask() {
-        int dockSide = mWindowManagerProxy.getDockSide();
-        if (dockSide != WindowManager.DOCKED_INVALID && (mHomeStackResizable
-                || !mDockedStackMinimized)) {
+        int dockSide = mSplitLayout.getPrimarySplitSide();
+        if (inSplitMode() && (mHomeStackResizable || !mDockedStackMinimized)) {
             startDragging(false /* animate */, false /* touching */);
             SnapTarget target = dockSideTopLeft(dockSide)
-                    ? mSnapAlgorithm.getDismissEndTarget()
-                    : mSnapAlgorithm.getDismissStartTarget();
+                    ? mSplitLayout.getSnapAlgorithm().getDismissEndTarget()
+                    : mSplitLayout.getSnapAlgorithm().getDismissStartTarget();
 
             // Don't start immediately - give a little bit time to settle the drag resize change.
             mExitAnimationRunning = true;
@@ -1354,8 +1422,7 @@
     }
 
     private int calculatePositionForInsetBounds() {
-        mTmpRect.set(0, 0, mDisplayWidth, mDisplayHeight);
-        mTmpRect.inset(mStableInsets);
+        mSplitLayout.mDisplayLayout.getStableBounds(mTmpRect);
         return DockedDividerUtils.calculatePositionForBounds(mTmpRect, mDockSide, mDividerSize);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
index 2486d653..3020a25 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerWindowManager.java
@@ -26,12 +26,13 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
-import android.content.Context;
 import android.graphics.PixelFormat;
 import android.os.Binder;
 import android.view.View;
 import android.view.WindowManager;
 
+import com.android.systemui.wm.SystemWindows;
+
 /**
  * Manages the window parameters of the docked stack divider.
  */
@@ -39,15 +40,16 @@
 
     private static final String WINDOW_TITLE = "DockedStackDivider";
 
-    private final WindowManager mWindowManager;
+    final SystemWindows mSystemWindows;
     private WindowManager.LayoutParams mLp;
     private View mView;
 
-    public DividerWindowManager(Context ctx) {
-        mWindowManager = ctx.getSystemService(WindowManager.class);
+    public DividerWindowManager(SystemWindows systemWindows) {
+        mSystemWindows = systemWindows;
     }
 
-    public void add(View view, int width, int height) {
+    /** Add a divider view */
+    public void add(View view, int width, int height, int displayId) {
         mLp = new WindowManager.LayoutParams(
                 width, height, TYPE_DOCK_DIVIDER,
                 FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCH_MODAL
@@ -60,13 +62,13 @@
         view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                 | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
-        mWindowManager.addView(view, mLp);
+        mSystemWindows.addView(view, mLp, displayId, TYPE_DOCK_DIVIDER);
         mView = view;
     }
 
     public void remove() {
         if (mView != null) {
-            mWindowManager.removeView(mView);
+            mSystemWindows.removeView(mView);
         }
         mView = null;
     }
@@ -81,7 +83,7 @@
             changed = true;
         }
         if (changed) {
-            mWindowManager.updateViewLayout(mView, mLp);
+            mSystemWindows.updateViewLayout(mView, mLp);
         }
     }
 
@@ -95,7 +97,7 @@
             changed = true;
         }
         if (changed) {
-            mWindowManager.updateViewLayout(mView, mLp);
+            mSystemWindows.updateViewLayout(mView, mLp);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
index c6ac309..db7996e 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
@@ -31,6 +31,8 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.TaskStackChangeListener;
 
+import java.util.function.Consumer;
+
 /**
  * Controller that decides when to show the {@link ForcedResizableInfoActivity}.
  */
@@ -52,6 +54,12 @@
         }
     };
 
+    private final Consumer<Boolean> mDockedStackExistsListener = exists -> {
+        if (!exists) {
+            mPackagesShownInSession.clear();
+        }
+    };
+
     /** Record of force resized task that's pending to be handled. */
     private class PendingTaskRecord {
         int taskId;
@@ -67,7 +75,7 @@
         }
     }
 
-    public ForcedResizableInfoActivityController(Context context) {
+    public ForcedResizableInfoActivityController(Context context, Divider divider) {
         mContext = context;
         ActivityManagerWrapper.getInstance().registerTaskStackListener(
                 new TaskStackChangeListener() {
@@ -87,12 +95,7 @@
                         activityLaunchOnSecondaryDisplayFailed();
                     }
                 });
-    }
-
-    public void notifyDockedStackExistsChanged(boolean exists) {
-        if (!exists) {
-            mPackagesShownInSession.clear();
-        }
+        divider.registerInSplitScreenListener(mDockedStackExistsListener);
     }
 
     public void onAppTransitionFinished() {
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
new file mode 100644
index 0000000..b19f560
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitDisplayLayout.java
@@ -0,0 +1,310 @@
+/*
+ * 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.systemui.stackdivider;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
+import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.util.TypedValue;
+import android.view.WindowContainerTransaction;
+
+import com.android.internal.policy.DividerSnapAlgorithm;
+import com.android.internal.policy.DockedDividerUtils;
+import com.android.systemui.wm.DisplayLayout;
+
+/**
+ * Handles split-screen related internal display layout. In general, this represents the
+ * WM-facing understanding of the splits.
+ */
+public class SplitDisplayLayout {
+    /** Minimum size of an adjusted stack bounds relative to original stack bounds. Used to
+     * restrict IME adjustment so that a min portion of top stack remains visible.*/
+    private static final float ADJUSTED_STACK_FRACTION_MIN = 0.3f;
+
+    private static final int DIVIDER_WIDTH_INACTIVE_DP = 4;
+
+    SplitScreenTaskOrganizer mTiles;
+    DisplayLayout mDisplayLayout;
+    Context mContext;
+
+    // Lazy stuff
+    boolean mResourcesValid = false;
+    int mDividerSize;
+    int mDividerSizeInactive;
+    private DividerSnapAlgorithm mSnapAlgorithm = null;
+    private DividerSnapAlgorithm mMinimizedSnapAlgorithm = null;
+    Rect mPrimary = null;
+    Rect mSecondary = null;
+    Rect mAdjustedPrimary = null;
+    Rect mAdjustedSecondary = null;
+
+    public SplitDisplayLayout(Context ctx, DisplayLayout dl, SplitScreenTaskOrganizer taskTiles) {
+        mTiles = taskTiles;
+        mDisplayLayout = dl;
+        mContext = ctx;
+    }
+
+    void rotateTo(int newRotation) {
+        mDisplayLayout.rotateTo(mContext.getResources(), newRotation);
+        final Configuration config = new Configuration();
+        config.unset();
+        config.orientation = mDisplayLayout.getOrientation();
+        Rect tmpRect = new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+        tmpRect.inset(mDisplayLayout.nonDecorInsets());
+        config.windowConfiguration.setAppBounds(tmpRect);
+        tmpRect.set(0, 0, mDisplayLayout.width(), mDisplayLayout.height());
+        tmpRect.inset(mDisplayLayout.stableInsets());
+        config.screenWidthDp = (int) (tmpRect.width() / mDisplayLayout.density());
+        config.screenHeightDp = (int) (tmpRect.height() / mDisplayLayout.density());
+        mContext = mContext.createConfigurationContext(config);
+        mSnapAlgorithm = null;
+        mMinimizedSnapAlgorithm = null;
+        mResourcesValid = false;
+    }
+
+    private void updateResources() {
+        if (mResourcesValid) {
+            return;
+        }
+        mResourcesValid = true;
+        Resources res = mContext.getResources();
+        mDividerSize = DockedDividerUtils.getDividerSize(res,
+                DockedDividerUtils.getDividerInsets(res));
+        mDividerSizeInactive = (int) TypedValue.applyDimension(
+                TypedValue.COMPLEX_UNIT_DIP, DIVIDER_WIDTH_INACTIVE_DP, res.getDisplayMetrics());
+    }
+
+    int getPrimarySplitSide() {
+        return mDisplayLayout.isLandscape() ? DOCKED_LEFT : DOCKED_TOP;
+    }
+
+    boolean isMinimized() {
+        return mTiles.mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+                || mTiles.mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS;
+    }
+
+    DividerSnapAlgorithm getSnapAlgorithm() {
+        if (mSnapAlgorithm == null) {
+            updateResources();
+            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
+            mSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
+                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
+                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide());
+        }
+        return mSnapAlgorithm;
+    }
+
+    DividerSnapAlgorithm getMinimizedSnapAlgorithm() {
+        if (mMinimizedSnapAlgorithm == null) {
+            updateResources();
+            boolean isHorizontalDivision = !mDisplayLayout.isLandscape();
+            mMinimizedSnapAlgorithm = new DividerSnapAlgorithm(mContext.getResources(),
+                    mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize,
+                    isHorizontalDivision, mDisplayLayout.stableInsets(), getPrimarySplitSide(),
+                    true /* isMinimized */);
+        }
+        return mMinimizedSnapAlgorithm;
+    }
+
+    void resizeSplits(int position) {
+        mPrimary = mPrimary == null ? new Rect() : mPrimary;
+        mSecondary = mSecondary == null ? new Rect() : mSecondary;
+        calcSplitBounds(position, mPrimary, mSecondary);
+    }
+
+    void resizeSplits(int position, WindowContainerTransaction t) {
+        resizeSplits(position);
+        t.setBounds(mTiles.mPrimary.token, mPrimary);
+        t.setBounds(mTiles.mSecondary.token, mSecondary);
+
+        t.setSmallestScreenWidthDp(mTiles.mPrimary.token,
+                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mPrimary));
+        t.setSmallestScreenWidthDp(mTiles.mSecondary.token,
+                getSmallestWidthDpForBounds(mContext, mDisplayLayout, mSecondary));
+    }
+
+    void calcSplitBounds(int position, @NonNull Rect outPrimary, @NonNull Rect outSecondary) {
+        int dockSide = getPrimarySplitSide();
+        DockedDividerUtils.calculateBoundsForPosition(position, dockSide, outPrimary,
+                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
+
+        DockedDividerUtils.calculateBoundsForPosition(position,
+                DockedDividerUtils.invertDockSide(dockSide), outSecondary, mDisplayLayout.width(),
+                mDisplayLayout.height(), mDividerSize);
+    }
+
+    Rect calcMinimizedHomeStackBounds() {
+        DividerSnapAlgorithm.SnapTarget miniMid = getMinimizedSnapAlgorithm().getMiddleTarget();
+        Rect homeBounds = new Rect();
+        DockedDividerUtils.calculateBoundsForPosition(miniMid.position,
+                DockedDividerUtils.invertDockSide(getPrimarySplitSide()), homeBounds,
+                mDisplayLayout.width(), mDisplayLayout.height(), mDividerSize);
+        return homeBounds;
+    }
+
+    /**
+     * Updates the adjustment depending on it's current state.
+     */
+    void updateAdjustedBounds(int currImeTop, int startTop, int finalTop) {
+        updateAdjustedBounds(mDisplayLayout, currImeTop, startTop, finalTop, mDividerSize,
+                mDividerSizeInactive, mPrimary, mSecondary);
+    }
+
+    /**
+     * Updates the adjustment depending on it's current state.
+     */
+    private void updateAdjustedBounds(DisplayLayout dl, int currImeTop, int startTop, int finalTop,
+            int dividerWidth, int dividerWidthInactive, Rect primaryBounds, Rect secondaryBounds) {
+        adjustForIME(dl, currImeTop, startTop, finalTop, dividerWidth, dividerWidthInactive,
+                primaryBounds, secondaryBounds);
+    }
+
+    /** Assumes top/bottom split. Splits are not adjusted for left/right splits. */
+    private void adjustForIME(DisplayLayout dl, int currImeTop, int startTop, int finalTop,
+            int dividerWidth, int dividerWidthInactive, Rect primaryBounds, Rect secondaryBounds) {
+        if (mAdjustedPrimary == null) {
+            mAdjustedPrimary = new Rect();
+            mAdjustedSecondary = new Rect();
+        }
+
+        final Rect displayStableRect = new Rect();
+        dl.getStableBounds(displayStableRect);
+
+        final boolean showing = finalTop < startTop;
+        final float progress = ((float) (currImeTop - startTop)) / (finalTop - startTop);
+        final float dividerSquish = showing ? progress : 1.f - progress;
+        final int currDividerWidth =
+                (int) (dividerWidthInactive * dividerSquish + dividerWidth * (1.f - dividerSquish));
+
+        final int minTopStackBottom = displayStableRect.top
+                + (int) ((mPrimary.bottom - displayStableRect.top) * ADJUSTED_STACK_FRACTION_MIN);
+        final int minImeTop = minTopStackBottom + currDividerWidth;
+
+        // Calculate an offset which shifts the stacks up by the height of the IME, but still
+        // leaves at least 30% of the top stack visible.
+        final int yOffset = Math.max(0, dl.height() - Math.max(currImeTop, minImeTop));
+
+        // TOP
+        // Reduce the offset by an additional small amount to squish the divider bar.
+        mAdjustedPrimary.set(primaryBounds);
+        mAdjustedPrimary.offset(0, -yOffset + (dividerWidth - currDividerWidth));
+
+        // BOTTOM
+        mAdjustedSecondary.set(secondaryBounds);
+        mAdjustedSecondary.offset(0, -yOffset);
+    }
+
+    static int getSmallestWidthDpForBounds(@NonNull Context context, DisplayLayout dl,
+            Rect bounds) {
+        int dividerSize = DockedDividerUtils.getDividerSize(context.getResources(),
+                DockedDividerUtils.getDividerInsets(context.getResources()));
+
+        int minWidth = Integer.MAX_VALUE;
+
+        // Go through all screen orientations and find the orientation in which the task has the
+        // smallest width.
+        Rect tmpRect = new Rect();
+        Rect rotatedDisplayRect = new Rect();
+        Rect displayRect = new Rect(0, 0, dl.width(), dl.height());
+
+        DisplayLayout tmpDL = new DisplayLayout();
+        for (int rotation = 0; rotation < 4; rotation++) {
+            tmpDL.set(dl);
+            tmpDL.rotateTo(context.getResources(), rotation);
+            DividerSnapAlgorithm snap = initSnapAlgorithmForRotation(context, tmpDL, dividerSize);
+
+            tmpRect.set(bounds);
+            DisplayLayout.rotateBounds(tmpRect, displayRect, rotation - dl.rotation());
+            rotatedDisplayRect.set(0, 0, tmpDL.width(), tmpDL.height());
+            final int dockSide = getPrimarySplitSide(tmpRect, rotatedDisplayRect,
+                    tmpDL.getOrientation());
+            final int position = DockedDividerUtils.calculatePositionForBounds(tmpRect, dockSide,
+                    dividerSize);
+
+            final int snappedPosition =
+                    snap.calculateNonDismissingSnapTarget(position).position;
+            DockedDividerUtils.calculateBoundsForPosition(snappedPosition, dockSide, tmpRect,
+                    tmpDL.width(), tmpDL.height(), dividerSize);
+            Rect insettedDisplay = new Rect(rotatedDisplayRect);
+            insettedDisplay.inset(tmpDL.stableInsets());
+            tmpRect.intersect(insettedDisplay);
+            minWidth = Math.min(tmpRect.width(), minWidth);
+        }
+        return (int) (minWidth / dl.density());
+    }
+
+    static DividerSnapAlgorithm initSnapAlgorithmForRotation(Context context, DisplayLayout dl,
+            int dividerSize) {
+        final Configuration config = new Configuration();
+        config.unset();
+        config.orientation = dl.getOrientation();
+        Rect tmpRect = new Rect(0, 0, dl.width(), dl.height());
+        tmpRect.inset(dl.nonDecorInsets());
+        config.windowConfiguration.setAppBounds(tmpRect);
+        tmpRect.set(0, 0, dl.width(), dl.height());
+        tmpRect.inset(dl.stableInsets());
+        config.screenWidthDp = (int) (tmpRect.width() / dl.density());
+        config.screenHeightDp = (int) (tmpRect.height() / dl.density());
+        final Context rotationContext = context.createConfigurationContext(config);
+        return new DividerSnapAlgorithm(
+                rotationContext.getResources(), dl.width(), dl.height(), dividerSize,
+                config.orientation == ORIENTATION_PORTRAIT, dl.stableInsets());
+    }
+
+    /**
+     * Get the current primary-split side. Determined by its location of {@param bounds} within
+     * {@param displayRect} but if both are the same, it will try to dock to each side and determine
+     * if allowed in its respected {@param orientation}.
+     *
+     * @param bounds bounds of the primary split task to get which side is docked
+     * @param displayRect bounds of the display that contains the primary split task
+     * @param orientation the origination of device
+     * @return current primary-split side
+     */
+    static int getPrimarySplitSide(Rect bounds, Rect displayRect, int orientation) {
+        if (orientation == ORIENTATION_PORTRAIT) {
+            // Portrait mode, docked either at the top or the bottom.
+            final int diff = (displayRect.bottom - bounds.bottom) - (bounds.top - displayRect.top);
+            if (diff < 0) {
+                return DOCKED_BOTTOM;
+            } else {
+                // Top is default
+                return DOCKED_TOP;
+            }
+        } else if (orientation == ORIENTATION_LANDSCAPE) {
+            // Landscape mode, docked either on the left or on the right.
+            final int diff = (displayRect.right - bounds.right) - (bounds.left - displayRect.left);
+            if (diff < 0) {
+                return DOCKED_RIGHT;
+            }
+            return DOCKED_LEFT;
+        }
+        return DOCKED_INVALID;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
new file mode 100644
index 0000000..5cc8799
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/SplitScreenTaskOrganizer.java
@@ -0,0 +1,159 @@
+/*
+ * 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.systemui.stackdivider;
+
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
+import static android.view.Display.DEFAULT_DISPLAY;
+
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ITaskOrganizerController;
+import android.app.WindowConfiguration;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.Display;
+import android.view.ITaskOrganizer;
+import android.view.IWindowContainer;
+import android.view.SurfaceControl;
+import android.view.SurfaceSession;
+
+class SplitScreenTaskOrganizer extends ITaskOrganizer.Stub {
+    private static final String TAG = "SplitScreenTaskOrganizer";
+    private static final boolean DEBUG = Divider.DEBUG;
+
+    RunningTaskInfo mPrimary;
+    RunningTaskInfo mSecondary;
+    SurfaceControl mPrimarySurface;
+    SurfaceControl mSecondarySurface;
+    SurfaceControl mPrimaryDim;
+    SurfaceControl mSecondaryDim;
+    final Divider mDivider;
+
+    SplitScreenTaskOrganizer(Divider divider) {
+        mDivider = divider;
+    }
+
+    void init(ITaskOrganizerController organizerController, SurfaceSession session)
+            throws RemoteException {
+        organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        organizerController.registerTaskOrganizer(this, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        mPrimary = organizerController.createRootTask(Display.DEFAULT_DISPLAY,
+                WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        mSecondary = organizerController.createRootTask(Display.DEFAULT_DISPLAY,
+                WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+        mPrimarySurface = mPrimary.token.getLeash();
+        mSecondarySurface = mSecondary.token.getLeash();
+
+        // Initialize dim surfaces:
+        mPrimaryDim = new SurfaceControl.Builder(session).setParent(mPrimarySurface)
+                .setColorLayer().setName("Primary Divider Dim").build();
+        mSecondaryDim = new SurfaceControl.Builder(session).setParent(mSecondarySurface)
+                .setColorLayer().setName("Secondary Divider Dim").build();
+        SurfaceControl.Transaction t = getTransaction();
+        t.setLayer(mPrimaryDim, Integer.MAX_VALUE);
+        t.setColor(mPrimaryDim, new float[]{0f, 0f, 0f});
+        t.setLayer(mSecondaryDim, Integer.MAX_VALUE);
+        t.setColor(mSecondaryDim, new float[]{0f, 0f, 0f});
+        t.apply();
+        releaseTransaction(t);
+    }
+
+    SurfaceControl.Transaction getTransaction() {
+        return mDivider.mTransactionPool.acquire();
+    }
+
+    void releaseTransaction(SurfaceControl.Transaction t) {
+        mDivider.mTransactionPool.release(t);
+    }
+
+    @Override
+    public void taskAppeared(RunningTaskInfo taskInfo) {
+    }
+
+    @Override
+    public void taskVanished(IWindowContainer container) {
+    }
+
+    @Override
+    public void transactionReady(int id, SurfaceControl.Transaction t) {
+    }
+
+    @Override
+    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+        if (taskInfo.displayId != DEFAULT_DISPLAY) {
+            return;
+        }
+        mDivider.getHandler().post(() -> handleTaskInfoChanged(taskInfo));
+    }
+
+    /**
+     * This is effectively a finite state machine which moves between the various split-screen
+     * presentations based on the contents of the split regions.
+     */
+    private void handleTaskInfoChanged(RunningTaskInfo info) {
+        final boolean primaryWasEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean secondaryWasEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        if (info.token.asBinder() == mPrimary.token.asBinder()) {
+            mPrimary = info;
+        } else if (info.token.asBinder() == mSecondary.token.asBinder()) {
+            mSecondary = info;
+        }
+        final boolean primaryIsEmpty = mPrimary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        final boolean secondaryIsEmpty = mSecondary.topActivityType == ACTIVITY_TYPE_UNDEFINED;
+        if (DEBUG) {
+            Log.d(TAG, "onTaskInfoChanged " + mPrimary + "  " + mSecondary);
+        }
+        if (primaryIsEmpty || secondaryIsEmpty) {
+            // At-least one of the splits is empty which means we are currently transitioning
+            // into or out-of split-screen mode.
+            if (DEBUG) {
+                Log.d(TAG, " at-least one split empty " + mPrimary.topActivityType
+                        + "  " + mSecondary.topActivityType);
+            }
+            if (mDivider.inSplitMode()) {
+                // Was in split-mode, which means we are leaving split, so continue that.
+                // This happens when the stack in the primary-split is dismissed.
+                if (DEBUG) {
+                    Log.d(TAG, "    was in split, so this means leave it "
+                            + mPrimary.topActivityType + "  " + mSecondary.topActivityType);
+                }
+                WindowManagerProxy.applyDismissSplit(this, true /* dismissOrMaximize */);
+                mDivider.updateVisibility(false /* visible */);
+            } else if (!primaryIsEmpty && primaryWasEmpty && secondaryWasEmpty) {
+                // Wasn't in split-mode (both were empty), but now that the primary split is
+                // populated, we should fully enter split by moving everything else into secondary.
+                // This just tells window-manager to reparent things, the UI will respond
+                // when it gets new task info for the secondary split.
+                if (DEBUG) {
+                    Log.d(TAG, "   was not in split, but primary is populated, so enter it");
+                }
+                mDivider.startEnterSplit();
+            }
+        } else if (mSecondary.topActivityType == ACTIVITY_TYPE_HOME
+                || mSecondary.topActivityType == ACTIVITY_TYPE_RECENTS) {
+            // Both splits are populated but the secondary split has a home/recents stack on top,
+            // so enter minimized mode.
+            mDivider.ensureMinimizedSplit();
+        } else {
+            // Both splits are populated by normal activities, so make sure we aren't minimized.
+            mDivider.ensureNormalSplit();
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
index 228aab5..7685733 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/WindowManagerProxy.java
@@ -16,16 +16,25 @@
 
 package com.android.systemui.stackdivider;
 
-import static android.view.WindowManager.DOCKED_INVALID;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.view.Display.DEFAULT_DISPLAY;
 
+import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.graphics.Rect;
 import android.os.RemoteException;
 import android.util.Log;
+import android.view.Display;
+import android.view.IWindowContainer;
+import android.view.WindowContainerTransaction;
 import android.view.WindowManagerGlobal;
 
 import com.android.internal.annotations.GuardedBy;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
@@ -35,88 +44,20 @@
 public class WindowManagerProxy {
 
     private static final String TAG = "WindowManagerProxy";
+    private static final int[] HOME_AND_RECENTS = {ACTIVITY_TYPE_HOME, ACTIVITY_TYPE_RECENTS};
 
     private static final WindowManagerProxy sInstance = new WindowManagerProxy();
 
     @GuardedBy("mDockedRect")
     private final Rect mDockedRect = new Rect();
-    private final Rect mTempDockedTaskRect = new Rect();
-    private final Rect mTempDockedInsetRect = new Rect();
-    private final Rect mTempOtherTaskRect = new Rect();
-    private final Rect mTempOtherInsetRect = new Rect();
 
     private final Rect mTmpRect1 = new Rect();
-    private final Rect mTmpRect2 = new Rect();
-    private final Rect mTmpRect3 = new Rect();
-    private final Rect mTmpRect4 = new Rect();
-    private final Rect mTmpRect5 = new Rect();
 
     @GuardedBy("mDockedRect")
     private final Rect mTouchableRegion = new Rect();
 
-    private boolean mDimLayerVisible;
-    private int mDimLayerTargetWindowingMode;
-    private float mDimLayerAlpha;
-
     private final ExecutorService mExecutor = Executors.newSingleThreadExecutor();
 
-    private final Runnable mResizeRunnable = new Runnable() {
-        @Override
-        public void run() {
-            synchronized (mDockedRect) {
-                mTmpRect1.set(mDockedRect);
-                mTmpRect2.set(mTempDockedTaskRect);
-                mTmpRect3.set(mTempDockedInsetRect);
-                mTmpRect4.set(mTempOtherTaskRect);
-                mTmpRect5.set(mTempOtherInsetRect);
-            }
-            try {
-                ActivityTaskManager.getService()
-                        .resizeDockedStack(mTmpRect1,
-                                mTmpRect2.isEmpty() ? null : mTmpRect2,
-                                mTmpRect3.isEmpty() ? null : mTmpRect3,
-                                mTmpRect4.isEmpty() ? null : mTmpRect4,
-                                mTmpRect5.isEmpty() ? null : mTmpRect5);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to resize stack: " + e);
-            }
-        }
-    };
-
-    private final Runnable mDismissRunnable = new Runnable() {
-        @Override
-        public void run() {
-            try {
-                ActivityTaskManager.getService().dismissSplitScreenMode(false /* onTop */);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to remove stack: " + e);
-            }
-        }
-    };
-
-    private final Runnable mMaximizeRunnable = new Runnable() {
-        @Override
-        public void run() {
-            try {
-                ActivityTaskManager.getService().dismissSplitScreenMode(true /* onTop */);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to resize stack: " + e);
-            }
-        }
-    };
-
-    private final Runnable mDimLayerRunnable = new Runnable() {
-        @Override
-        public void run() {
-            try {
-                WindowManagerGlobal.getWindowManagerService().setResizeDimLayer(mDimLayerVisible,
-                        mDimLayerTargetWindowingMode, mDimLayerAlpha);
-            } catch (RemoteException e) {
-                Log.w(TAG, "Failed to resize stack: " + e);
-            }
-        }
-    };
-
     private final Runnable mSetTouchableRegionRunnable = new Runnable() {
         @Override
         public void run() {
@@ -139,40 +80,9 @@
         return sInstance;
     }
 
-    public void resizeDockedStack(Rect docked, Rect tempDockedTaskRect, Rect tempDockedInsetRect,
-            Rect tempOtherTaskRect, Rect tempOtherInsetRect) {
-        synchronized (mDockedRect) {
-            mDockedRect.set(docked);
-            if (tempDockedTaskRect != null) {
-                mTempDockedTaskRect.set(tempDockedTaskRect);
-            } else {
-                mTempDockedTaskRect.setEmpty();
-            }
-            if (tempDockedInsetRect != null) {
-                mTempDockedInsetRect.set(tempDockedInsetRect);
-            } else {
-                mTempDockedInsetRect.setEmpty();
-            }
-            if (tempOtherTaskRect != null) {
-                mTempOtherTaskRect.set(tempOtherTaskRect);
-            } else {
-                mTempOtherTaskRect.setEmpty();
-            }
-            if (tempOtherInsetRect != null) {
-                mTempOtherInsetRect.set(tempOtherInsetRect);
-            } else {
-                mTempOtherInsetRect.setEmpty();
-            }
-        }
-        mExecutor.execute(mResizeRunnable);
-    }
-
-    public void dismissDockedStack() {
-        mExecutor.execute(mDismissRunnable);
-    }
-
-    public void maximizeDockedStack() {
-        mExecutor.execute(mMaximizeRunnable);
+    void dismissOrMaximizeDocked(
+            final SplitScreenTaskOrganizer tiles, final boolean dismissOrMaximize) {
+        mExecutor.execute(() -> applyDismissSplit(tiles, dismissOrMaximize));
     }
 
     public void setResizing(final boolean resizing) {
@@ -188,26 +98,204 @@
         });
     }
 
-    public int getDockSide() {
-        try {
-            return WindowManagerGlobal.getWindowManagerService().getDockedStackSide();
-        } catch (RemoteException e) {
-            Log.w(TAG, "Failed to get dock side: " + e);
-        }
-        return DOCKED_INVALID;
-    }
-
-    public void setResizeDimLayer(boolean visible, int targetWindowingMode, float alpha) {
-        mDimLayerVisible = visible;
-        mDimLayerTargetWindowingMode = targetWindowingMode;
-        mDimLayerAlpha = alpha;
-        mExecutor.execute(mDimLayerRunnable);
-    }
-
+    /** Sets a touch region */
     public void setTouchRegion(Rect region) {
         synchronized (mDockedRect) {
             mTouchableRegion.set(region);
         }
         mExecutor.execute(mSetTouchableRegionRunnable);
     }
+
+    static void applyResizeSplits(int position, SplitDisplayLayout splitLayout) {
+        WindowContainerTransaction t = new WindowContainerTransaction();
+        splitLayout.resizeSplits(position, t);
+        try {
+            ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(t,
+                    null /* organizer */);
+        } catch (RemoteException e) {
+        }
+    }
+
+    private static boolean getHomeAndRecentsTasks(List<IWindowContainer> out,
+            IWindowContainer parent) {
+        boolean resizable = false;
+        try {
+            List<ActivityManager.RunningTaskInfo> rootTasks = parent == null
+                    ? ActivityTaskManager.getTaskOrganizerController().getRootTasks(
+                            Display.DEFAULT_DISPLAY, HOME_AND_RECENTS)
+                    : ActivityTaskManager.getTaskOrganizerController().getChildTasks(parent,
+                            HOME_AND_RECENTS);
+            for (int i = 0, n = rootTasks.size(); i < n; ++i) {
+                final ActivityManager.RunningTaskInfo ti = rootTasks.get(i);
+                out.add(ti.token);
+                if (ti.topActivityType == ACTIVITY_TYPE_HOME) {
+                    resizable = ti.isResizable();
+                }
+            }
+        } catch (RemoteException e) {
+        }
+        return resizable;
+    }
+
+    static void applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent) {
+        applyHomeTasksMinimized(layout, parent, null /* transaction */);
+    }
+
+    /**
+     * Assign a fixed override-bounds to home tasks that reflect their geometry while the primary
+     * split is minimized. This actually "sticks out" of the secondary split area, but when in
+     * minimized mode, the secondary split gets a 'negative' crop to expose it.
+     */
+    static boolean applyHomeTasksMinimized(SplitDisplayLayout layout, IWindowContainer parent,
+            WindowContainerTransaction t) {
+        // Resize the home/recents stacks to the larger minimized-state size
+        final Rect homeBounds;
+        final ArrayList<IWindowContainer> homeStacks = new ArrayList<>();
+        boolean isHomeResizable = getHomeAndRecentsTasks(homeStacks, parent);
+        if (isHomeResizable) {
+            homeBounds = layout.calcMinimizedHomeStackBounds();
+        } else {
+            homeBounds = new Rect(0, 0, layout.mDisplayLayout.width(),
+                    layout.mDisplayLayout.height());
+        }
+        WindowContainerTransaction wct = t != null ? t : new WindowContainerTransaction();
+        for (int i = homeStacks.size() - 1; i >= 0; --i) {
+            wct.setBounds(homeStacks.get(i), homeBounds);
+        }
+        if (t != null) {
+            return isHomeResizable;
+        }
+        try {
+            ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct,
+                    null /* organizer */);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to resize home stacks ", e);
+        }
+        return isHomeResizable;
+    }
+
+    /**
+     * Finishes entering split-screen by reparenting all FULLSCREEN tasks into the secondary split.
+     * This assumes there is already something in the primary split since that is usually what
+     * triggers a call to this. In the same transaction, this overrides the home task bounds via
+     * {@link #applyHomeTasksMinimized}.
+     *
+     * @return whether the home stack is resizable
+     */
+    static boolean applyEnterSplit(SplitScreenTaskOrganizer tiles, SplitDisplayLayout layout) {
+        try {
+            // Set launchtile first so that any stack created after
+            // getAllStackInfos and before reparent (even if unlikely) are placed
+            // correctly.
+            ActivityTaskManager.getTaskOrganizerController().setLaunchRoot(
+                    DEFAULT_DISPLAY, tiles.mSecondary.token);
+            List<ActivityManager.RunningTaskInfo> rootTasks =
+                    ActivityTaskManager.getTaskOrganizerController().getRootTasks(DEFAULT_DISPLAY,
+                            null /* activityTypes */);
+            WindowContainerTransaction wct = new WindowContainerTransaction();
+            if (rootTasks.isEmpty()) {
+                return false;
+            }
+            for (int i = rootTasks.size() - 1; i >= 0; --i) {
+                if (rootTasks.get(i).configuration.windowConfiguration.getWindowingMode()
+                        != WINDOWING_MODE_FULLSCREEN) {
+                    continue;
+                }
+                wct.reparent(rootTasks.get(i).token, tiles.mSecondary.token,
+                        true /* onTop */);
+            }
+            boolean isHomeResizable = applyHomeTasksMinimized(layout, null /* parent */, wct);
+            ActivityTaskManager.getTaskOrganizerController()
+                    .applyContainerTransaction(wct, null /* organizer */);
+            return isHomeResizable;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Error moving fullscreen tasks to secondary split: " + e);
+        }
+        return false;
+    }
+
+    private static boolean isHomeOrRecentTask(ActivityManager.RunningTaskInfo ti) {
+        final int atype = ti.configuration.windowConfiguration.getActivityType();
+        return atype == ACTIVITY_TYPE_HOME || atype == ACTIVITY_TYPE_RECENTS;
+    }
+
+    /**
+     * Reparents all tile members back to their display and resets home task override bounds.
+     * @param dismissOrMaximize When {@code true} this resolves the split by closing the primary
+     *                          split (thus resulting in the top of the secondary split becoming
+     *                          fullscreen. {@code false} resolves the other way.
+     */
+    static void applyDismissSplit(SplitScreenTaskOrganizer tiles, boolean dismissOrMaximize) {
+        try {
+            // Set launch root first so that any task created after getChildContainers and
+            // before reparent (pretty unlikely) are put into fullscreen.
+            ActivityTaskManager.getTaskOrganizerController().setLaunchRoot(Display.DEFAULT_DISPLAY,
+                    null);
+            // TODO(task-org): Once task-org is more complete, consider using Appeared/Vanished
+            //                 plus specific APIs to clean this up.
+            List<ActivityManager.RunningTaskInfo> primaryChildren =
+                    ActivityTaskManager.getTaskOrganizerController().getChildTasks(
+                            tiles.mPrimary.token, null /* activityTypes */);
+            List<ActivityManager.RunningTaskInfo> secondaryChildren =
+                    ActivityTaskManager.getTaskOrganizerController().getChildTasks(
+                            tiles.mSecondary.token, null /* activityTypes */);
+            // In some cases (eg. non-resizable is launched), system-server will leave split-screen.
+            // as a result, the above will not capture any tasks; yet, we need to clean-up the
+            // home task bounds.
+            List<ActivityManager.RunningTaskInfo> freeHomeAndRecents =
+                    ActivityTaskManager.getTaskOrganizerController().getRootTasks(
+                            Display.DEFAULT_DISPLAY, HOME_AND_RECENTS);
+            if (primaryChildren.isEmpty() && secondaryChildren.isEmpty()
+                    && freeHomeAndRecents.isEmpty()) {
+                return;
+            }
+            WindowContainerTransaction wct = new WindowContainerTransaction();
+            if (dismissOrMaximize) {
+                // Dismissing, so move all primary split tasks first
+                for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                    wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                            true /* onTop */);
+                }
+                // Don't need to worry about home tasks because they are already in the "proper"
+                // order within the secondary split.
+                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                    final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                    wct.reparent(ti.token, null /* parent */, true /* onTop */);
+                    if (isHomeOrRecentTask(ti)) {
+                        wct.setBounds(ti.token, null);
+                    }
+                }
+            } else {
+                // Maximize, so move non-home secondary split first
+                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                    if (isHomeOrRecentTask(secondaryChildren.get(i))) {
+                        continue;
+                    }
+                    wct.reparent(secondaryChildren.get(i).token, null /* parent */,
+                            true /* onTop */);
+                }
+                // Find and place home tasks in-between. This simulates the fact that there was
+                // nothing behind the primary split's tasks.
+                for (int i = secondaryChildren.size() - 1; i >= 0; --i) {
+                    final ActivityManager.RunningTaskInfo ti = secondaryChildren.get(i);
+                    if (isHomeOrRecentTask(ti)) {
+                        wct.reparent(ti.token, null /* parent */, true /* onTop */);
+                        // reset bounds too
+                        wct.setBounds(ti.token, null);
+                    }
+                }
+                for (int i = primaryChildren.size() - 1; i >= 0; --i) {
+                    wct.reparent(primaryChildren.get(i).token, null /* parent */,
+                            true /* onTop */);
+                }
+            }
+            for (int i = freeHomeAndRecents.size() - 1; i >= 0; --i) {
+                wct.setBounds(freeHomeAndRecents.get(i).token, null);
+            }
+            ActivityTaskManager.getTaskOrganizerController().applyContainerTransaction(wct,
+                    null /* organizer */);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Failed to remove stack: " + e);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
index ab69d47..4bb8621 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt
@@ -90,7 +90,7 @@
     }
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
-        IndentingPrintWriter(pw, "  ").use {
+        IndentingPrintWriter(pw, "  ").let {
             it.println("BlurUtils:")
             it.increaseIndent()
             it.println("minBlurRadius: $minBlurRadius")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 7d3d406..4f8e6cf 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -645,7 +645,13 @@
         @Override
         public void onBiometricHelp(int msgId, String helpString,
                 BiometricSourceType biometricSourceType) {
-            if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
+            // TODO(b/141025588): refactor to reduce repetition of code/comments
+            // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
+            // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
+            // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
+            // check of whether non-strong biometric is allowed
+            if (!mKeyguardUpdateMonitor
+                    .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)) {
                 return;
             }
             boolean showSwipeToUnlock =
@@ -705,13 +711,21 @@
 
         private boolean shouldSuppressFingerprintError(int msgId,
                 KeyguardUpdateMonitor updateMonitor) {
-            return ((!updateMonitor.isUnlockingWithBiometricAllowed()
+            // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
+            // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
+            // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
+            // check of whether non-strong biometric is allowed
+            return ((!updateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
                     && msgId != FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT)
                     || msgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED);
         }
 
         private boolean shouldSuppressFaceError(int msgId, KeyguardUpdateMonitor updateMonitor) {
-            return ((!updateMonitor.isUnlockingWithBiometricAllowed()
+            // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
+            // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
+            // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
+            // check of whether non-strong biometric is allowed
+            return ((!updateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */)
                     && msgId != FaceManager.FACE_ERROR_LOCKOUT_PERMANENT)
                     || msgId == FaceManager.FACE_ERROR_CANCELED);
         }
@@ -745,8 +759,9 @@
         }
 
         @Override
-        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
-            super.onBiometricAuthenticated(userId, biometricSourceType);
+        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
+                boolean isStrongBiometric) {
+            super.onBiometricAuthenticated(userId, biometricSourceType, isStrongBiometric);
             mHandler.sendEmptyMessage(MSG_HIDE_TRANSIENT);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
index aaf4849..711d6a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/MediaArtworkProcessor.kt
@@ -19,7 +19,6 @@
 import android.content.Context
 import android.graphics.Bitmap
 import android.graphics.Canvas
-import android.graphics.Point
 import android.graphics.Rect
 import android.renderscript.Allocation
 import android.renderscript.Element
@@ -27,9 +26,11 @@
 import android.renderscript.ScriptIntrinsicBlur
 import android.util.Log
 import android.util.MathUtils
+import android.util.Size
+import android.view.WindowManager
+import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.graphics.ColorUtils
 import com.android.systemui.statusbar.notification.MediaNotificationProcessor
-
 import javax.inject.Inject
 import javax.inject.Singleton
 
@@ -41,10 +42,9 @@
 @Singleton
 class MediaArtworkProcessor @Inject constructor() {
 
-    private val mTmpSize = Point()
     private var mArtworkCache: Bitmap? = null
 
-    fun processArtwork(context: Context, artwork: Bitmap): Bitmap? {
+    fun processArtwork(context: Context, artwork: Bitmap, windowType: Int): Bitmap? {
         if (mArtworkCache != null) {
             return mArtworkCache
         }
@@ -54,9 +54,9 @@
         var output: Allocation? = null
         var inBitmap: Bitmap? = null
         try {
-            context.display.getSize(mTmpSize)
+            val size = getWindowSize(context, windowType)
             val rect = Rect(0, 0, artwork.width, artwork.height)
-            MathUtils.fitRect(rect, Math.max(mTmpSize.x / DOWNSAMPLE, mTmpSize.y / DOWNSAMPLE))
+            MathUtils.fitRect(rect, Math.max(size.width / DOWNSAMPLE, size.height / DOWNSAMPLE))
             inBitmap = Bitmap.createScaledBitmap(artwork, rect.width(), rect.height(),
                     true /* filter */)
             // Render script blurs only support ARGB_8888, we need a conversion if we got a
@@ -98,4 +98,15 @@
         mArtworkCache?.recycle()
         mArtworkCache = null
     }
+
+    @VisibleForTesting
+    internal fun getWindowSize(context: Context, windowType: Int): Size {
+        val windowContext = context.display?.let {
+            context.createDisplayContext(it)
+                    .createWindowContext(windowType, null)
+        } ?: run { throw NullPointerException("Display is null") }
+        val windowManager = windowContext.getSystemService(WindowManager::class.java)
+                ?: run { throw NullPointerException("Null window manager") }
+        return windowManager.currentWindowMetrics.size
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index d0af106..f8db922 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -15,7 +15,6 @@
  */
 package com.android.systemui.statusbar;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER;
 import static com.android.systemui.statusbar.StatusBarState.KEYGUARD;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG_MEDIA_FAKE_ARTWORK;
 import static com.android.systemui.statusbar.phone.StatusBar.ENABLE_LOCKSCREEN_WALLPAPER;
@@ -36,7 +35,6 @@
 import android.media.session.MediaSessionManager;
 import android.media.session.PlaybackState;
 import android.os.AsyncTask;
-import android.os.Handler;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.provider.DeviceConfig;
@@ -44,6 +42,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.view.View;
+import android.view.WindowManager;
 import android.widget.ImageView;
 
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
@@ -52,6 +51,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.dagger.StatusBarModule;
 import com.android.systemui.statusbar.notification.NotificationEntryListener;
@@ -73,6 +73,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 
 import dagger.Lazy;
 
@@ -110,7 +111,7 @@
     @Nullable
     private LockscreenWallpaper mLockscreenWallpaper;
 
-    private final Handler mHandler = Dependency.get(MAIN_HANDLER);
+    private final Executor mMainExecutor;
 
     private final Context mContext;
     private final MediaSessionManager mMediaSessionManager;
@@ -181,7 +182,8 @@
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             NotificationEntryManager notificationEntryManager,
             MediaArtworkProcessor mediaArtworkProcessor,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController,
+            @Main Executor mainExecutor) {
         mContext = context;
         mMediaArtworkProcessor = mediaArtworkProcessor;
         mKeyguardBypassController = keyguardBypassController;
@@ -194,6 +196,7 @@
         mStatusBarLazy = statusBarLazy;
         mNotificationShadeWindowController = notificationShadeWindowController;
         mEntryManager = notificationEntryManager;
+        mMainExecutor = mainExecutor;
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
             public void onPendingEntryAdded(NotificationEntry entry) {
@@ -623,7 +626,7 @@
                                 mBackdrop.setVisibility(View.GONE);
                                 mBackdropFront.animate().cancel();
                                 mBackdropBack.setImageDrawable(null);
-                                mHandler.post(mHideBackdropFront);
+                                mMainExecutor.execute(mHideBackdropFront);
                             });
                     if (mKeyguardStateController.isKeyguardFadingAway()) {
                         mBackdrop.animate()
@@ -668,7 +671,8 @@
     };
 
     private Bitmap processArtwork(Bitmap artwork) {
-        return mMediaArtworkProcessor.processArtwork(mContext, artwork);
+        return mMediaArtworkProcessor.processArtwork(mContext, artwork,
+                WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE);
     }
 
     @MainThread
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 9c626f7..12add8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -159,6 +159,7 @@
     private boolean mDismissed;
     private Runnable mOnDismissListener;
     private boolean mIncreasedSize;
+    private boolean mTintIcons = true;
 
     public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
         this(context, slot, sbn, false);
@@ -612,6 +613,11 @@
     }
 
     private void updateIconColor() {
+        if (!mTintIcons) {
+            setColorFilter(null);
+            return;
+        }
+
         if (mCurrentSetColor != NO_COLOR) {
             if (mMatrixColorFilter == null) {
                 mMatrix = new float[4 * 5];
@@ -953,6 +959,19 @@
         maybeUpdateIconScaleDimens();
     }
 
+    /**
+     * Sets whether the icon should be tinted. If the state differs from the supplied setting, this
+     * will update the icon colors.
+     *
+     * @param shouldTint Whether the icon should be tinted.
+     */
+    public void setTintIcons(boolean shouldTint) {
+        if (mTintIcons != shouldTint) {
+            mTintIcons = shouldTint;
+            updateIconColor();
+        }
+    }
+
     public interface OnVisibilityChangedListener {
         void onVisibilityChanged(int newVisibility);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
index 0b37c22..cd5bb77 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StatusBarDependenciesModule.java
@@ -43,6 +43,8 @@
 import com.android.systemui.statusbar.policy.RemoteInputUriController;
 import com.android.systemui.tracing.ProtoTracer;
 
+import java.util.concurrent.Executor;
+
 import javax.inject.Singleton;
 
 import dagger.Lazy;
@@ -88,14 +90,16 @@
             Lazy<NotificationShadeWindowController> notificationShadeWindowController,
             NotificationEntryManager notificationEntryManager,
             MediaArtworkProcessor mediaArtworkProcessor,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController,
+            @Main Executor mainExecutor) {
         return new NotificationMediaManager(
                 context,
                 statusBarLazy,
                 notificationShadeWindowController,
                 notificationEntryManager,
                 mediaArtworkProcessor,
-                keyguardBypassController);
+                keyguardBypassController,
+                mainExecutor);
     }
 
     /** */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
index 93f5805..55a20fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/InstantAppNotifier.java
@@ -51,10 +51,10 @@
 import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
 import com.android.systemui.Dependency;
-import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.R;
 import com.android.systemui.SystemUI;
 import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.util.NotificationChannels;
@@ -80,11 +80,13 @@
     private final CommandQueue mCommandQueue;
     private boolean mDockedStackExists;
     private KeyguardStateController mKeyguardStateController;
+    private final Divider mDivider;
 
     @Inject
     public InstantAppNotifier(Context context, CommandQueue commandQueue,
-            @UiBackground Executor uiBgExecutor) {
+            @UiBackground Executor uiBgExecutor, Divider divider) {
         super(context);
+        mDivider = divider;
         mCommandQueue = commandQueue;
         mUiBgExecutor = uiBgExecutor;
     }
@@ -103,7 +105,7 @@
         mCommandQueue.addCallback(this);
         mKeyguardStateController.addCallback(this);
 
-        DockedStackExistsListener.register(
+        mDivider.registerInSplitScreenListener(
                 exists -> {
                     mDockedStackExists = exists;
                     updateForegroundInstantApps();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 72a7e11..07cf9d9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -53,12 +53,14 @@
             VisualStabilityManager visualStabilityManager,
             StatusBarStateController statusBarStateController,
             NotificationInterruptionStateProvider notificationInterruptionStateProvider,
-            NotificationListener notificationListener) {
+            NotificationListener notificationListener,
+            HeadsUpManager headsUpManager) {
         mRemoteInputManager = remoteInputManager;
         mVisualStabilityManager = visualStabilityManager;
         mStatusBarStateController = statusBarStateController;
         mNotificationInterruptionStateProvider = notificationInterruptionStateProvider;
         mNotificationListener = notificationListener;
+        mHeadsUpManager = headsUpManager;
 
         notificationEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
             @Override
@@ -81,10 +83,6 @@
         });
     }
 
-    public void setHeadsUpManager(HeadsUpManager headsUpManager) {
-        mHeadsUpManager = headsUpManager;
-    }
-
     /**
      * Adds the entry to the respective alerting manager if the content view was inflated and
      * the entry should still alert.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 4f55e02..5ebd368 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -49,9 +49,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener;
 import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.leak.LeakDetector;
 
@@ -230,9 +228,7 @@
         mRemoveInterceptors.remove(interceptor);
     }
 
-    public void setUpWithPresenter(NotificationPresenter presenter,
-            NotificationListContainer listContainer,
-            HeadsUpManager headsUpManager) {
+    public void setUpWithPresenter(NotificationPresenter presenter) {
         mPresenter = presenter;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
index 0095511..48386dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManager.kt
@@ -22,6 +22,7 @@
 import com.android.internal.annotations.VisibleForTesting
 import com.android.internal.config.sysui.SystemUiDeviceConfigFlags.NOTIFICATIONS_USE_PEOPLE_FILTERING
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
 import com.android.systemui.util.DeviceConfigProxy
@@ -45,7 +46,7 @@
     fun getNotificationBuckets(): IntArray {
         return when {
             isFilteringEnabled() ->
-                intArrayOf(BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
+                intArrayOf(BUCKET_HEADS_UP, BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT)
             NotificationUtils.useNewInterruptionModel(context) ->
                 intArrayOf(BUCKET_ALERTING, BUCKET_SILENT)
             else ->
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
index 616c110..fabe3a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
@@ -61,7 +61,8 @@
      * Injected constructor. See {@link NotificationsModule}.
      */
     public VisualStabilityManager(
-            NotificationEntryManager notificationEntryManager, @Main Handler handler) {
+            NotificationEntryManager notificationEntryManager,
+            @Main Handler handler) {
 
         mHandler = handler;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index f482d37..25a832d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -29,6 +29,8 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_NOTIFICATION_LIST;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
+import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC;
+import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED;
 
 import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED;
 import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING;
@@ -42,6 +44,9 @@
 import android.app.Person;
 import android.app.RemoteInputHistoryItem;
 import android.content.Context;
+import android.content.pm.LauncherApps;
+import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.ShortcutInfo;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
@@ -50,6 +55,7 @@
 import android.service.notification.SnoozeCriterion;
 import android.service.notification.StatusBarNotification;
 import android.util.ArraySet;
+import android.util.Log;
 import android.view.View;
 import android.widget.ImageView;
 
@@ -75,6 +81,8 @@
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
 
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -94,11 +102,15 @@
  * clean this up in the future.
  */
 public final class NotificationEntry extends ListEntry {
+    private static final String TAG = "NotificationEntry";
 
     private final String mKey;
     private StatusBarNotification mSbn;
     private Ranking mRanking;
 
+    private StatusBarIcon mSmallIcon;
+    private StatusBarIcon mPeopleAvatar;
+
     /*
      * Bookkeeping members
      */
@@ -459,12 +471,7 @@
      */
     public void createIcons(Context context, StatusBarNotification sbn)
             throws InflationException {
-        Notification n = sbn.getNotification();
-        final Icon smallIcon = n.getSmallIcon();
-        if (smallIcon == null) {
-            throw new InflationException("No small icon in notification from "
-                    + sbn.getPackageName());
-        }
+        StatusBarIcon ic = getIcon(context, sbn, false /* redact */);
 
         // Construct the icon.
         icon = new StatusBarIconView(context,
@@ -482,21 +489,20 @@
         aodIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
         aodIcon.setIncreasedSize(true);
 
-        final StatusBarIcon ic = new StatusBarIcon(
-                sbn.getUser(),
-                sbn.getPackageName(),
-                smallIcon,
-                n.iconLevel,
-                n.number,
-                StatusBarIconView.contentDescForNotification(context, n));
-
-        if (!icon.set(ic) || !expandedIcon.set(ic) || !aodIcon.set(ic)) {
+        try {
+            setIcons(ic, Collections.singletonList(icon));
+            if (isSensitive()) {
+                ic = getIcon(context, sbn, true /* redact */);
+            }
+            setIcons(ic, Arrays.asList(expandedIcon, aodIcon));
+        } catch (InflationException e) {
             icon = null;
             expandedIcon = null;
             centeredIcon = null;
             aodIcon = null;
-            throw new InflationException("Couldn't create icon: " + ic);
+            throw e;
         }
+
         expandedIcon.setVisibility(View.INVISIBLE);
         expandedIcon.setOnVisibilityChangedListener(
                 newVisibility -> {
@@ -510,10 +516,130 @@
             centeredIcon = new StatusBarIconView(context,
                     sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             centeredIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
-
-            if (!centeredIcon.set(ic)) {
+            try {
+                setIcons(ic, Collections.singletonList(centeredIcon));
+            } catch (InflationException e) {
                 centeredIcon = null;
-                throw new InflationException("Couldn't update centered icon: " + ic);
+                throw e;
+            }
+        }
+    }
+
+    /**
+     * Determines if this icon should be tinted based on the sensitivity of the icon, its context
+     * and the user's indicated sensitivity preference.
+     *
+     * @param ic The icon that should/should not be tinted.
+     * @return
+     */
+    private boolean shouldTintIcon(StatusBarIconView ic) {
+        boolean usedInSensitiveContext = (ic == expandedIcon || ic == aodIcon);
+        return !isImportantConversation() || (usedInSensitiveContext && isSensitive());
+    }
+
+
+    private void setIcons(StatusBarIcon ic, List<StatusBarIconView> icons)
+            throws InflationException {
+        for (StatusBarIconView icon: icons) {
+            if (icon == null) {
+              continue;
+            }
+            icon.setTintIcons(shouldTintIcon(icon));
+            if (!icon.set(ic)) {
+                throw new InflationException("Couldn't create icon" + ic);
+            }
+        }
+    }
+
+    private StatusBarIcon getIcon(Context context, StatusBarNotification sbn, boolean redact)
+            throws InflationException {
+        Notification n = sbn.getNotification();
+        final boolean showPeopleAvatar = isImportantConversation() && !redact;
+
+        // If cached, return corresponding cached values
+        if (showPeopleAvatar && mPeopleAvatar != null) {
+            return mPeopleAvatar;
+        } else if (!showPeopleAvatar && mSmallIcon != null) {
+            return mSmallIcon;
+        }
+
+        Icon icon = showPeopleAvatar ? createPeopleAvatar(context) : n.getSmallIcon();
+        if (icon == null) {
+            throw new InflationException("No icon in notification from " + sbn.getPackageName());
+        }
+
+        StatusBarIcon ic = new StatusBarIcon(
+                    sbn.getUser(),
+                    sbn.getPackageName(),
+                    icon,
+                    n.iconLevel,
+                    n.number,
+                    StatusBarIconView.contentDescForNotification(context, n));
+
+        // Cache if important conversation.
+        if (isImportantConversation()) {
+            if (showPeopleAvatar) {
+                mPeopleAvatar = ic;
+            } else {
+                mSmallIcon = ic;
+            }
+        }
+        return ic;
+    }
+
+    private Icon createPeopleAvatar(Context context) throws InflationException {
+        // Attempt to extract form shortcut.
+        String conversationId = getChannel().getConversationId();
+        ShortcutQuery query = new ShortcutQuery()
+                .setPackage(mSbn.getPackageName())
+                .setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED)
+                .setShortcutIds(Collections.singletonList(conversationId));
+        List<ShortcutInfo> shortcuts = context.getSystemService(LauncherApps.class)
+                .getShortcuts(query, mSbn.getUser());
+        Icon ic = null;
+        if (shortcuts != null && !shortcuts.isEmpty()) {
+            ic = shortcuts.get(0).getIcon();
+        }
+
+        // Fall back to notification large icon if available
+        if (ic == null) {
+            ic = mSbn.getNotification().getLargeIcon();
+        }
+
+        // Fall back to extract from message
+        if (ic == null) {
+            Bundle extras = mSbn.getNotification().extras;
+            List<Message> messages = Message.getMessagesFromBundleArray(
+                    extras.getParcelableArray(Notification.EXTRA_MESSAGES));
+            Person user = extras.getParcelable(Notification.EXTRA_MESSAGING_PERSON);
+
+            for (int i = messages.size() - 1; i >= 0; i--) {
+                Message message = messages.get(i);
+                Person sender = message.getSenderPerson();
+                if (sender != null && sender != user) {
+                    ic = message.getSenderPerson().getIcon();
+                    break;
+                }
+            }
+        }
+
+        // Revert to small icon if still not available
+        if (ic == null) {
+            ic = mSbn.getNotification().getSmallIcon();
+        }
+        if (ic == null) {
+            throw new InflationException("No icon in notification from " + mSbn.getPackageName());
+        }
+        return ic;
+    }
+
+    private void updateSensitiveIconState() {
+        try {
+            StatusBarIcon ic = getIcon(getRow().getContext(), mSbn, isSensitive());
+            setIcons(ic, Arrays.asList(expandedIcon, aodIcon));
+        } catch (InflationException e) {
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "Unable to update icon", e);
             }
         }
     }
@@ -544,30 +670,32 @@
             throws InflationException {
         if (icon != null) {
             // Update the icon
-            Notification n = sbn.getNotification();
-            final StatusBarIcon ic = new StatusBarIcon(
-                    mSbn.getUser(),
-                    mSbn.getPackageName(),
-                    n.getSmallIcon(),
-                    n.iconLevel,
-                    n.number,
-                    StatusBarIconView.contentDescForNotification(context, n));
+            mSmallIcon = null;
+            mPeopleAvatar = null;
+
+            StatusBarIcon ic = getIcon(context, sbn, false /* redact */);
+
             icon.setNotification(sbn);
             expandedIcon.setNotification(sbn);
             aodIcon.setNotification(sbn);
-            if (!icon.set(ic) || !expandedIcon.set(ic) || !aodIcon.set(ic)) {
-                throw new InflationException("Couldn't update icon: " + ic);
+            setIcons(ic, Arrays.asList(icon, expandedIcon));
+
+            if (isSensitive()) {
+                ic = getIcon(context, sbn, true /* redact */);
             }
+            setIcons(ic, Collections.singletonList(aodIcon));
 
             if (centeredIcon != null) {
                 centeredIcon.setNotification(sbn);
-                if (!centeredIcon.set(ic)) {
-                    throw new InflationException("Couldn't update centered icon: " + ic);
-                }
+                setIcons(ic, Collections.singletonList(centeredIcon));
             }
         }
     }
 
+    private boolean isImportantConversation() {
+        return getChannel() != null && getChannel().isImportantConversation();
+    }
+
     public int getContrastedColor(Context context, boolean isLowPriority,
             int backgroundColor) {
         int rawColor = isLowPriority ? Notification.COLOR_DEFAULT :
@@ -996,6 +1124,7 @@
         getRow().setSensitive(sensitive, deviceSensitive);
         if (sensitive != mSensitive) {
             mSensitive = sensitive;
+            updateSensitiveIconState();
             if (mOnSensitiveChangedListener != null) {
                 mOnSensitiveChangedListener.run();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
index 2981252..9c942a5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManager.kt
@@ -28,11 +28,13 @@
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_HEADS_UP
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_PEOPLE
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationGroupManager
 import com.android.systemui.statusbar.policy.HeadsUpManager
 import dagger.Lazy
+import java.util.Comparator
 import java.util.Objects
 import javax.inject.Inject
 
@@ -73,6 +75,9 @@
         val aIsPeople = a.isPeopleNotification()
         val bIsPeople = b.isPeopleNotification()
 
+        val aIsImportantPeople = a.isImportantPeopleNotification()
+        val bIsImportantPeople = b.isImportantPeopleNotification()
+
         val aMedia = isImportantMedia(a)
         val bMedia = isImportantMedia(b)
 
@@ -86,10 +91,12 @@
         val bIsHighPriority = b.isHighPriority()
 
         when {
-            usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1
             aHeadsUp != bHeadsUp -> if (aHeadsUp) -1 else 1
             // Provide consistent ranking with headsUpManager
             aHeadsUp -> headsUpManager.compare(a, b)
+            usePeopleFiltering && aIsPeople != bIsPeople -> if (aIsPeople) -1 else 1
+            usePeopleFiltering && aIsImportantPeople != bIsImportantPeople ->
+                if (aIsImportantPeople) -1 else 1
             // Upsort current media notification.
             aMedia != bMedia -> if (aMedia) -1 else 1
             // Upsort PRIORITY_MAX system notifications
@@ -156,7 +163,9 @@
         isMedia: Boolean,
         isSystemMax: Boolean
     ) {
-        if (usePeopleFiltering && entry.isPeopleNotification()) {
+        if (usePeopleFiltering && isHeadsUp) {
+            entry.bucket = BUCKET_HEADS_UP
+        } else if (usePeopleFiltering && entry.isPeopleNotification()) {
             entry.bucket = BUCKET_PEOPLE
         } else if (isHeadsUp || isMedia || isSystemMax || entry.isHighPriority()) {
             entry.bucket = BUCKET_ALERTING
@@ -192,6 +201,9 @@
     private fun NotificationEntry.isPeopleNotification() =
             peopleNotificationIdentifier.isPeopleNotification(sbn, ranking)
 
+    private fun NotificationEntry.isImportantPeopleNotification() =
+            peopleNotificationIdentifier.isImportantPeopleNotification(sbn, ranking)
+
     private fun NotificationEntry.isHighPriority() =
             highPriorityProvider.isHighPriority(this)
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 8f8f742..d0b553d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -47,6 +47,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.util.leak.LeakDetector;
 
 import java.util.concurrent.Executor;
@@ -123,14 +124,16 @@
             VisualStabilityManager visualStabilityManager,
             StatusBarStateController statusBarStateController,
             NotificationInterruptionStateProvider notificationInterruptionStateProvider,
-            NotificationListener notificationListener) {
+            NotificationListener notificationListener,
+            HeadsUpManager headsUpManager) {
         return new NotificationAlertingManager(
                 notificationEntryManager,
                 remoteInputManager,
                 visualStabilityManager,
                 statusBarStateController,
                 notificationInterruptionStateProvider,
-                notificationListener);
+                notificationListener,
+                headsUpManager);
     }
 
     /** Provides an instance of {@link NotificationLogger} */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
index efcef71..16574ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubModule.kt
@@ -24,8 +24,8 @@
 
     @Binds
     abstract fun peopleHubSectionFooterViewAdapter(
-        impl: PeopleHubSectionFooterViewAdapterImpl
-    ): PeopleHubSectionFooterViewAdapter
+        impl: PeopleHubViewAdapterImpl
+    ): PeopleHubViewAdapter
 
     @Binds
     abstract fun peopleHubDataSource(impl: PeopleHubDataSourceImpl): DataSource<PeopleHubModel>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
index ec1d6de..e28d03f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleHubViewController.kt
@@ -25,17 +25,16 @@
 import android.view.View
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.ActivityStarter
-import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager
 import javax.inject.Inject
 import javax.inject.Singleton
 
 /** Boundary between the View and PeopleHub, as seen by the View. */
-interface PeopleHubSectionFooterViewAdapter {
-    fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary)
+interface PeopleHubViewAdapter {
+    fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription
 }
 
-/** Abstract `View` representation of PeopleHub footer in [NotificationSectionsManager]. */
-interface PeopleHubSectionFooterViewBoundary {
+/** Abstract `View` representation of PeopleHub. */
+interface PeopleHubViewBoundary {
     /** View used for animating the activity launch caused by clicking a person in the hub. */
     val associatedViewForClickAnimation: View
 
@@ -57,23 +56,22 @@
 }
 
 /**
- * Wraps a [PeopleHubSectionFooterViewBoundary] in a [DataListener], and connects it to the data
+ * Wraps a [PeopleHubViewBoundary] in a [DataListener], and connects it to the data
  * pipeline.
  *
  * @param dataSource PeopleHub data pipeline.
  */
 @Singleton
-class PeopleHubSectionFooterViewAdapterImpl @Inject constructor(
+class PeopleHubViewAdapterImpl @Inject constructor(
     private val dataSource: DataSource<@JvmSuppressWildcards PeopleHubViewModelFactory>
-) : PeopleHubSectionFooterViewAdapter {
+) : PeopleHubViewAdapter {
 
-    override fun bindView(viewBoundary: PeopleHubSectionFooterViewBoundary) {
-        dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary))
-    }
+    override fun bindView(viewBoundary: PeopleHubViewBoundary): Subscription =
+            dataSource.registerListener(PeopleHubDataListenerImpl(viewBoundary))
 }
 
 private class PeopleHubDataListenerImpl(
-    private val viewBoundary: PeopleHubSectionFooterViewBoundary
+    private val viewBoundary: PeopleHubViewBoundary
 ) : DataListener<PeopleHubViewModelFactory> {
 
     override fun onDataChanged(data: PeopleHubViewModelFactory) {
@@ -92,7 +90,7 @@
  * Converts [PeopleHubModel]s into [PeopleHubViewModelFactory]s.
  *
  * This class serves as the glue between the View layer (which depends on
- * [PeopleHubSectionFooterViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
+ * [PeopleHubViewBoundary]) and the Data layer (which produces [PeopleHubModel]s).
  */
 @Singleton
 class PeopleHubViewModelFactoryDataSourceImpl @Inject constructor(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
index 4672de0..e15fa2e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/people/PeopleNotificationIdentifier.kt
@@ -23,6 +23,7 @@
 
 interface PeopleNotificationIdentifier {
     fun isPeopleNotification(sbn: StatusBarNotification, ranking: Ranking): Boolean
+    fun isImportantPeopleNotification(sbn: StatusBarNotification, ranking: Ranking): Boolean
 }
 
 @Singleton
@@ -32,4 +33,7 @@
 
     override fun isPeopleNotification(sbn: StatusBarNotification, ranking: Ranking) =
             ranking.isConversation || personExtractor.isPersonNotification(sbn)
+
+    override fun isImportantPeopleNotification(sbn: StatusBarNotification, ranking: Ranking) =
+            isPeopleNotification(sbn, ranking) && ranking.channel.isImportantConversation
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index 3eac229..b03ba3c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -336,6 +336,10 @@
         return false;
     }
 
+    boolean superPerformClick() {
+        return super.performClick();
+    }
+
     /**
      * Cancels the hotspot and makes the notification inactive.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
index 8465658..2643ec9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationViewController.java
@@ -72,7 +72,8 @@
             } else {
                 mView.makeInactive(true /* animate */);
             }
-        }, mView::performClick, mView::handleSlideBack, mFalsingManager::onNotificationDoubleTap);
+        }, mView::superPerformClick, mView::handleSlideBack,
+                mFalsingManager::onNotificationDoubleTap);
         mView.setOnTouchListener(mTouchHandler);
         mView.setTouchHandler(mTouchHandler);
         mView.setOnDimmedListener(dimmed -> {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 55173182..5008133 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -482,6 +482,7 @@
      * once per notification as the packageInfo can't technically change for a notification row.
      */
     private void cacheIsSystemNotification() {
+        //TODO: This probably shouldn't be in ExpandableNotificationRow
         if (mEntry != null && mEntry.mIsSystemNotification == null) {
             if (mSystemNotificationAsyncTask.getStatus() == AsyncTask.Status.PENDING) {
                 // Run async task once, only if it hasn't already been executed. Note this is
@@ -1197,6 +1198,9 @@
         if (mMenuRow != null && mMenuRow.getMenuView() != null) {
             mMenuRow.onConfigurationChanged();
         }
+        if (mImageResolver != null) {
+            mImageResolver.updateMaxImageSizes();
+        }
     }
 
     public void onUiModeChanged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
index a0fef00..e79d89f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableView.java
@@ -67,29 +67,34 @@
 
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        final int givenSize = MeasureSpec.getSize(heightMeasureSpec);
+        final int givenHeight = MeasureSpec.getSize(heightMeasureSpec);
         final int viewHorizontalPadding = getPaddingStart() + getPaddingEnd();
+
+        // Max height is as large as possible, unless otherwise requested
         int ownMaxHeight = Integer.MAX_VALUE;
         int heightMode = MeasureSpec.getMode(heightMeasureSpec);
-        if (heightMode != MeasureSpec.UNSPECIFIED && givenSize != 0) {
-            ownMaxHeight = Math.min(givenSize, ownMaxHeight);
+        if (heightMode != MeasureSpec.UNSPECIFIED && givenHeight != 0) {
+            // Set our max height to what was requested from the parent
+            ownMaxHeight = Math.min(givenHeight, ownMaxHeight);
         }
-        int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
+
+        // height of the largest child
         int maxChildHeight = 0;
+        int atMostOwnMaxHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child.getVisibility() == GONE) {
                 continue;
             }
-            int childHeightSpec = newHeightSpec;
+            int childHeightSpec = atMostOwnMaxHeightSpec;
             ViewGroup.LayoutParams layoutParams = child.getLayoutParams();
             if (layoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
                 if (layoutParams.height >= 0) {
-                    // An actual height is set
-                    childHeightSpec = layoutParams.height > ownMaxHeight
-                        ? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
-                        : MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
+                    // If an actual height is set, cap it to the max height
+                    childHeightSpec = MeasureSpec.makeMeasureSpec(
+                            Math.min(layoutParams.height, ownMaxHeight),
+                            MeasureSpec.EXACTLY);
                 }
                 child.measure(getChildMeasureSpec(
                         widthMeasureSpec, viewHorizontalPadding, layoutParams.width),
@@ -100,15 +105,22 @@
                 mMatchParentViews.add(child);
             }
         }
+
+        // Set our own height to the given height, or the height of the largest child
         int ownHeight = heightMode == MeasureSpec.EXACTLY
-                ? givenSize : Math.min(ownMaxHeight, maxChildHeight);
-        newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
+                ? givenHeight
+                : Math.min(ownMaxHeight, maxChildHeight);
+        int exactlyOwnHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
+
+        // Now that we know our own height, measure the children that are MATCH_PARENT
         for (View child : mMatchParentViews) {
             child.measure(getChildMeasureSpec(
                     widthMeasureSpec, viewHorizontalPadding, child.getLayoutParams().width),
-                    newHeightSpec);
+                    exactlyOwnHeightSpec);
         }
         mMatchParentViews.clear();
+
+        // Finish up
         int width = MeasureSpec.getSize(widthMeasureSpec);
         setMeasuredDimension(width, ownHeight);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
index 248e5fe..60eda06 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfo.java
@@ -22,6 +22,7 @@
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_DYNAMIC;
 import static android.content.pm.LauncherApps.ShortcutQuery.FLAG_MATCH_PINNED;
+import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -112,7 +113,8 @@
     boolean mSkipPost = false;
 
     @Retention(SOURCE)
-    @IntDef({ACTION_BUBBLE, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE})
+    @IntDef({ACTION_BUBBLE, ACTION_HOME, ACTION_FAVORITE, ACTION_SNOOZE, ACTION_MUTE,
+            ACTION_UNBUBBLE, ACTION_SETTINGS})
     private @interface Action {}
     static final int ACTION_BUBBLE = 0;
     static final int ACTION_HOME = 1;
@@ -128,8 +130,6 @@
             mBubbleController.onUserDemotedBubbleFromNotification(mEntry);
         } else {
             mBubbleController.onUserCreatedBubbleFromNotification(mEntry);
-            Settings.Global.putInt(
-                    mContext.getContentResolver(), Settings.Global.NOTIFICATION_BUBBLES, 1);
         }
         closeControls(v, true);
     };
@@ -225,7 +225,9 @@
             mShortcutInfo = shortcuts.get(0);
         }
 
-        mIsBubbleable = mEntry.getBubbleMetadata() != null;
+        mIsBubbleable = mEntry.getBubbleMetadata() != null
+            && Settings.Global.getInt(mContext.getContentResolver(),
+                Settings.Global.NOTIFICATION_BUBBLES, 0) == 1;
         mStartedAsBubble = mEntry.isBubble();
 
         createConversationChannelIfNeeded();
@@ -382,6 +384,11 @@
         ((TextView) findViewById(R.id.pkg_name)).setText(mAppName);
     }
 
+    private boolean bubbleImportantConversations() {
+        return Settings.Secure.getInt(mContext.getContentResolver(),
+                BUBBLE_IMPORTANT_CONVERSATIONS, 1) == 1;
+    }
+
     private void bindDelegate() {
         TextView delegateView = findViewById(R.id.delegate_name);
 
@@ -579,6 +586,10 @@
                     case ACTION_FAVORITE:
                         mChannelToUpdate.setImportantConversation(
                                 !mChannelToUpdate.isImportantConversation());
+                        if (mChannelToUpdate.isImportantConversation()
+                                && bubbleImportantConversations()) {
+                            mChannelToUpdate.setAllowBubbles(true);
+                        }
                         break;
                     case ACTION_MUTE:
                         if (mChannelToUpdate.getImportance() == IMPORTANCE_UNSPECIFIED
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
index fa4bc2a..52f7c2c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolver.java
@@ -19,12 +19,17 @@
 import android.app.ActivityManager;
 import android.app.Notification;
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
 
+import com.android.internal.R;
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.widget.ImageResolver;
 import com.android.internal.widget.LocalImageResolver;
 import com.android.internal.widget.MessagingMessage;
@@ -36,6 +41,10 @@
 
 /**
  * Custom resolver with built-in image cache for image messages.
+ *
+ * If the URL points to a bitmap that's larger than the maximum width or height, the bitmap
+ * will be resized down to that maximum size before being cached. See {@link #getMaxImageWidth()},
+ * {@link #getMaxImageHeight()}, and {@link #resolveImage(Uri)} for the downscaling implementation.
  */
 public class NotificationInlineImageResolver implements ImageResolver {
     private static final String TAG = NotificationInlineImageResolver.class.getSimpleName();
@@ -44,6 +53,13 @@
     private final ImageCache mImageCache;
     private Set<Uri> mWantedUriSet;
 
+    // max allowed bitmap width, in pixels
+    @VisibleForTesting
+    protected int mMaxImageWidth;
+    // max allowed bitmap height, in pixels
+    @VisibleForTesting
+    protected int mMaxImageHeight;
+
     /**
      * Constructor.
      * @param context    Context.
@@ -56,6 +72,8 @@
         if (mImageCache != null) {
             mImageCache.setImageResolver(this);
         }
+
+        updateMaxImageSizes();
     }
 
     /**
@@ -66,14 +84,49 @@
         return mImageCache != null && !ActivityManager.isLowRamDeviceStatic();
     }
 
+    private boolean isLowRam() {
+        return ActivityManager.isLowRamDeviceStatic();
+    }
+
     /**
-     * To resolve image from specified uri directly.
+     * Update the maximum width and height allowed for bitmaps, ex. after a configuration change.
+     */
+    public void updateMaxImageSizes() {
+        mMaxImageWidth = getMaxImageWidth();
+        mMaxImageHeight = getMaxImageHeight();
+    }
+
+    @VisibleForTesting
+    protected int getMaxImageWidth() {
+        return mContext.getResources().getDimensionPixelSize(isLowRam()
+                ? R.dimen.notification_custom_view_max_image_width_low_ram
+                : R.dimen.notification_custom_view_max_image_width);
+    }
+
+    @VisibleForTesting
+    protected int getMaxImageHeight() {
+        return mContext.getResources().getDimensionPixelSize(isLowRam()
+                ? R.dimen.notification_custom_view_max_image_height_low_ram
+                : R.dimen.notification_custom_view_max_image_height);
+    }
+
+    @VisibleForTesting
+    protected BitmapDrawable resolveImageInternal(Uri uri) throws IOException {
+        return (BitmapDrawable) LocalImageResolver.resolveImage(uri, mContext);
+    }
+
+    /**
+     * To resolve image from specified uri directly. If the resulting image is larger than the
+     * maximum allowed size, scale it down.
      * @param uri Uri of the image.
      * @return Drawable of the image.
      * @throws IOException Throws if failed at resolving the image.
      */
     Drawable resolveImage(Uri uri) throws IOException {
-        return LocalImageResolver.resolveImage(uri, mContext);
+        BitmapDrawable image = resolveImageInternal(uri);
+        Bitmap bitmap = image.getBitmap();
+        image.setBitmap(Icon.scaleDownIfNecessary(bitmap, mMaxImageWidth, mMaxImageHeight));
+        return image;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
index 23433cb..b3561c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.java
@@ -16,11 +16,10 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout.ROWS_GENTLE;
-
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
+import android.annotation.LayoutRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Intent;
@@ -35,18 +34,21 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
 import com.android.systemui.statusbar.notification.people.DataListener;
-import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
-import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewBoundary;
+import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter;
+import com.android.systemui.statusbar.notification.people.PeopleHubViewBoundary;
 import com.android.systemui.statusbar.notification.people.PersonViewModel;
+import com.android.systemui.statusbar.notification.people.Subscription;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.ExpandableView;
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
 
 import java.lang.annotation.Retention;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 import javax.inject.Inject;
 
@@ -63,63 +65,65 @@
     private static final String TAG = "NotifSectionsManager";
     private static final boolean DEBUG = false;
 
-    private NotificationStackScrollLayout mParent;
     private final ActivityStarter mActivityStarter;
     private final StatusBarStateController mStatusBarStateController;
     private final ConfigurationController mConfigurationController;
-    private final int mNumberOfSections;
+    private final PeopleHubViewAdapter mPeopleHubViewAdapter;
     private final NotificationSectionsFeatureManager mSectionsFeatureManager;
-    private final NotificationRowComponent.Builder mNotificationRowComponentBuilder;
+    private final int mNumberOfSections;
+
+    private final PeopleHubViewBoundary mPeopleHubViewBoundary = new PeopleHubViewBoundary() {
+        @Override
+        public void setVisible(boolean isVisible) {
+            if (mPeopleHubVisible != isVisible) {
+                mPeopleHubVisible = isVisible;
+                if (mInitialized) {
+                    updateSectionBoundaries();
+                }
+            }
+        }
+
+        @NonNull
+        @Override
+        public View getAssociatedViewForClickAnimation() {
+            return mPeopleHubView;
+        }
+
+        @NonNull
+        @Override
+        public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
+            return mPeopleHubView.getPersonViewAdapters();
+        }
+    };
+
+    private NotificationStackScrollLayout mParent;
     private boolean mInitialized = false;
 
     private SectionHeaderView mGentleHeader;
-    private boolean mGentleHeaderVisible = false;
-
-    private boolean mPeopleHubVisible = false;
-    private PeopleHubView mPeopleHubView;
-    private final PeopleHubSectionFooterViewAdapter mPeopleHubViewAdapter;
-    private final PeopleHubSectionFooterViewBoundary mPeopleHubViewBoundary =
-            new PeopleHubSectionFooterViewBoundary() {
-                @Override
-                public void setVisible(boolean isVisible) {
-                    if (mPeopleHubVisible != isVisible) {
-                        mPeopleHubVisible = isVisible;
-                        if (mInitialized) {
-                            updateSectionBoundaries();
-                        }
-                    }
-                }
-
-                @NonNull
-                @Override
-                public View getAssociatedViewForClickAnimation() {
-                    return mPeopleHubView;
-                }
-
-                @NonNull
-                @Override
-                public Sequence<DataListener<PersonViewModel>> getPersonViewAdapters() {
-                    return mPeopleHubView.getPersonViewAdapters();
-                }
-            };
-
+    private boolean mGentleHeaderVisible;
     @Nullable private View.OnClickListener mOnClearGentleNotifsClickListener;
 
+    private SectionHeaderView mAlertingHeader;
+    private boolean mAlertingHeaderVisible;
+
+    private PeopleHubView mPeopleHubView;
+    private boolean mPeopleHeaderVisible;
+    private boolean mPeopleHubVisible = false;
+    @Nullable private Subscription mPeopleHubSubscription;
+
     @Inject
     NotificationSectionsManager(
             ActivityStarter activityStarter,
             StatusBarStateController statusBarStateController,
             ConfigurationController configurationController,
-            PeopleHubSectionFooterViewAdapter peopleHubViewAdapter,
-            NotificationSectionsFeatureManager sectionsFeatureManager,
-            NotificationRowComponent.Builder notificationRowComponentBuilder) {
+            PeopleHubViewAdapter peopleHubViewAdapter,
+            NotificationSectionsFeatureManager sectionsFeatureManager) {
         mActivityStarter = activityStarter;
         mStatusBarStateController = statusBarStateController;
         mConfigurationController = configurationController;
         mPeopleHubViewAdapter = peopleHubViewAdapter;
         mSectionsFeatureManager = sectionsFeatureManager;
         mNumberOfSections = mSectionsFeatureManager.getNumberOfBuckets();
-        mNotificationRowComponentBuilder = notificationRowComponentBuilder;
     }
 
     NotificationSection[] createSectionsForBuckets() {
@@ -141,105 +145,81 @@
         mInitialized = true;
         mParent = parent;
         reinflateViews(layoutInflater);
-        mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary);
         mConfigurationController.addCallback(mConfigurationListener);
     }
 
+    private <T extends ExpandableView> T reinflateView(
+            T view, LayoutInflater layoutInflater, @LayoutRes int layoutResId) {
+        int oldPos = -1;
+        if (view != null) {
+            if (view.getTransientContainer() != null) {
+                view.getTransientContainer().removeView(mGentleHeader);
+            } else if (view.getParent() != null) {
+                oldPos = mParent.indexOfChild(view);
+                mParent.removeView(view);
+            }
+        }
+
+        view = (T) layoutInflater.inflate(layoutResId, mParent, false);
+
+        if (oldPos != -1) {
+            mParent.addView(view, oldPos);
+        }
+
+        return view;
+    }
+
     /**
      * Reinflates the entire notification header, including all decoration views.
      */
     void reinflateViews(LayoutInflater layoutInflater) {
-        int oldGentleHeaderPos = -1;
-        int oldPeopleHubPos = -1;
-        if (mGentleHeader != null) {
-            if (mGentleHeader.getTransientContainer() != null) {
-                mGentleHeader.getTransientContainer().removeView(mGentleHeader);
-            } else if (mGentleHeader.getParent() != null) {
-                oldGentleHeaderPos = mParent.indexOfChild(mGentleHeader);
-                mParent.removeView(mGentleHeader);
-            }
-        }
-        if (mPeopleHubView != null) {
-            if (mPeopleHubView.getTransientContainer() != null) {
-                mPeopleHubView.getTransientContainer().removeView(mPeopleHubView);
-            } else if (mPeopleHubView.getParent() != null) {
-                oldPeopleHubPos = mParent.indexOfChild(mPeopleHubView);
-                mParent.removeView(mPeopleHubView);
-            }
-        }
-
-        mGentleHeader = (SectionHeaderView) layoutInflater.inflate(
-                R.layout.status_bar_notification_section_header, mParent, false);
-        NotificationRowComponent sectionHeaderComponent = mNotificationRowComponentBuilder
-                .activatableNotificationView(mGentleHeader)
-                .build();
-        sectionHeaderComponent.getActivatableNotificationViewController().init();
-
+        mGentleHeader = reinflateView(
+                mGentleHeader, layoutInflater, R.layout.status_bar_notification_section_header);
+        mGentleHeader.setHeaderText(R.string.notification_section_header_gentle);
         mGentleHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
         mGentleHeader.setOnClearAllClickListener(this::onClearGentleNotifsClick);
 
-        if (oldGentleHeaderPos != -1) {
-            mParent.addView(mGentleHeader, oldGentleHeaderPos);
+        mAlertingHeader = reinflateView(
+                mAlertingHeader, layoutInflater, R.layout.status_bar_notification_section_header);
+        mAlertingHeader.setHeaderText(R.string.notification_section_header_alerting);
+        mAlertingHeader.setOnHeaderClickListener(this::onGentleHeaderClick);
+
+        if (mPeopleHubSubscription != null) {
+            mPeopleHubSubscription.unsubscribe();
         }
-
-        mPeopleHubView = (PeopleHubView) layoutInflater.inflate(
-                R.layout.people_strip, mParent, false);
-
-        NotificationRowComponent notificationRowComponent = mNotificationRowComponentBuilder
-                .activatableNotificationView(mPeopleHubView)
-                .build();
-        notificationRowComponent.getActivatableNotificationViewController().init();
-
-        if (oldPeopleHubPos != -1) {
-            mParent.addView(mPeopleHubView, oldPeopleHubPos);
-        }
+        mPeopleHubView = reinflateView(mPeopleHubView, layoutInflater, R.layout.people_strip);
+        mPeopleHubSubscription = mPeopleHubViewAdapter.bindView(mPeopleHubViewBoundary);
     }
 
-    /** Listener for when the "clear all" buttton is clciked on the gentle notification header. */
+    /** Listener for when the "clear all" button is clicked on the gentle notification header. */
     void setOnClearGentleNotifsClickListener(View.OnClickListener listener) {
         mOnClearGentleNotifsClickListener = listener;
     }
 
-    /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
-    void onUiModeChanged() {
-        mGentleHeader.onUiModeChanged();
-    }
-
     @Override
     public boolean beginsSection(@NonNull View view, @Nullable View previous) {
-        boolean begin = false;
-        if (view instanceof ActivatableNotificationView) {
-            if (previous instanceof ActivatableNotificationView) {
-                // If we're drawing the first non-person notification, break out a section
-                ActivatableNotificationView curr = (ActivatableNotificationView) view;
-                ActivatableNotificationView prev = (ActivatableNotificationView) previous;
-
-                begin = getBucket(curr) != getBucket(prev);
-            }
-        }
-
-        if (!begin) {
-            begin = view == mGentleHeader || view == mPeopleHubView;
-        }
-
-        return begin;
+        return view == mGentleHeader
+                || view == mPeopleHubView
+                || view == mAlertingHeader
+                || !Objects.equals(getBucket(view), getBucket(previous));
     }
 
     private boolean isUsingMultipleSections() {
         return mNumberOfSections > 1;
     }
 
-    private @PriorityBucket int getBucket(ActivatableNotificationView view)
-            throws IllegalArgumentException {
-        if (view instanceof ExpandableNotificationRow) {
-            return ((ExpandableNotificationRow) view).getEntry().getBucket();
-        } else if (view == mGentleHeader) {
+    @Nullable
+    private Integer getBucket(View view) {
+        if (view == mGentleHeader) {
             return BUCKET_SILENT;
         } else if (view == mPeopleHubView) {
             return BUCKET_PEOPLE;
+        } else if (view == mAlertingHeader) {
+            return BUCKET_ALERTING;
+        } else if (view instanceof ExpandableNotificationRow) {
+            return ((ExpandableNotificationRow) view).getEntry().getBucket();
         }
-
-        throw new IllegalArgumentException("I don't know how to find a bucket for this view :(");
+        return null;
     }
 
     /**
@@ -251,118 +231,104 @@
             return;
         }
 
-        boolean peopleNotificationsPresent = false;
-        int firstNonHeadsUpIndex = -1;
-        int firstGentleIndex = -1;
-        int notifCount = 0;
+        final boolean showHeaders = mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
+        final boolean usingPeopleFiltering = mSectionsFeatureManager.isFilteringEnabled();
 
-        final int n = mParent.getChildCount();
-        for (int i = 0; i < n; i++) {
-            View child = mParent.getChildAt(i);
-            if (child instanceof ExpandableNotificationRow && child.getVisibility() != View.GONE) {
-                notifCount++;
+        boolean peopleNotifsPresent = false;
+        int peopleHeaderTarget = -1;
+        int alertingHeaderTarget = -1;
+        int gentleHeaderTarget = -1;
+
+        int viewCount = 0;
+
+        if (showHeaders) {
+            final int childCount = mParent.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                View child = mParent.getChildAt(i);
+                if (child.getVisibility() == View.GONE
+                        || !(child instanceof ExpandableNotificationRow)) {
+                    continue;
+                }
                 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-                if (firstNonHeadsUpIndex == -1 && !row.isHeadsUp()) {
-                    firstNonHeadsUpIndex = i;
+                switch (row.getEntry().getBucket()) {
+                    case BUCKET_PEOPLE:
+                        if (peopleHeaderTarget == -1) {
+                            peopleNotifsPresent = true;
+                            peopleHeaderTarget = viewCount;
+                            viewCount++;
+                        }
+                        break;
+                    case BUCKET_ALERTING:
+                        if (usingPeopleFiltering && alertingHeaderTarget == -1) {
+                            alertingHeaderTarget = viewCount;
+                            viewCount++;
+                        }
+                        break;
+                    case BUCKET_SILENT:
+                        if (gentleHeaderTarget == -1) {
+                            gentleHeaderTarget = viewCount;
+                            viewCount++;
+                        }
+                        break;
                 }
-                if (row.getEntry().getBucket() == BUCKET_PEOPLE) {
-                    peopleNotificationsPresent = true;
-                }
-                if (row.getEntry().getBucket() == BUCKET_SILENT) {
-                    firstGentleIndex = i;
-                    break;
+                viewCount++;
+            }
+            if (usingPeopleFiltering && mPeopleHubVisible && peopleHeaderTarget == -1) {
+                // Insert the people header even if there are no people visible, in order to show
+                // the hub. Put it directly above the next header.
+                if (alertingHeaderTarget != -1) {
+                    peopleHeaderTarget = alertingHeaderTarget;
+                    alertingHeaderTarget++;
+                    gentleHeaderTarget++;
+                } else if (gentleHeaderTarget != -1) {
+                    peopleHeaderTarget = gentleHeaderTarget;
+                    gentleHeaderTarget++;
+                } else {
+                    // Put it at the end of the list.
+                    peopleHeaderTarget = viewCount;
                 }
             }
         }
 
-        if (firstNonHeadsUpIndex == -1) {
-            firstNonHeadsUpIndex = firstGentleIndex != -1 ? firstGentleIndex : notifCount;
-        }
+        // Allow swiping the people header if the section is empty
+        mPeopleHubView.setCanSwipe(mPeopleHubVisible && !peopleNotifsPresent);
 
-        // make room for peopleHub
-        int offset = adjustPeopleHubVisibilityAndPosition(
-                firstNonHeadsUpIndex, peopleNotificationsPresent);
-        if (firstGentleIndex != -1) {
-            firstGentleIndex += offset;
-        }
-
-        adjustGentleHeaderVisibilityAndPosition(firstGentleIndex);
-
-        mGentleHeader.setAreThereDismissableGentleNotifs(
-                mParent.hasActiveClearableNotifications(ROWS_GENTLE));
+        mPeopleHeaderVisible = adjustHeaderVisibilityAndPosition(
+                peopleHeaderTarget, mPeopleHubView, mPeopleHeaderVisible);
+        mAlertingHeaderVisible = adjustHeaderVisibilityAndPosition(
+                alertingHeaderTarget, mAlertingHeader, mAlertingHeaderVisible);
+        mGentleHeaderVisible = adjustHeaderVisibilityAndPosition(
+                gentleHeaderTarget, mGentleHeader, mGentleHeaderVisible);
     }
 
-    private void adjustGentleHeaderVisibilityAndPosition(int firstGentleNotifIndex) {
-        final boolean showGentleHeader =
-                firstGentleNotifIndex != -1
-                        && mStatusBarStateController.getState() != StatusBarState.KEYGUARD;
-        final int currentHeaderIndex = mParent.indexOfChild(mGentleHeader);
-
-        if (!showGentleHeader) {
-            if (mGentleHeaderVisible) {
-                mGentleHeaderVisible = false;
-                mParent.removeView(mGentleHeader);
+    private boolean adjustHeaderVisibilityAndPosition(
+            int targetIndex, StackScrollerDecorView header, boolean isCurrentlyVisible) {
+        if (targetIndex == -1) {
+            if (isCurrentlyVisible) {
+                mParent.removeView(header);
             }
+            return false;
         } else {
-            if (!mGentleHeaderVisible) {
-                mGentleHeaderVisible = true;
+            if (header instanceof SwipeableView) {
+                ((SwipeableView) header).resetTranslation();
+            }
+            if (!isCurrentlyVisible) {
                 // If the header is animating away, it will still have a parent, so detach it first
                 // TODO: We should really cancel the active animations here. This will happen
                 // automatically when the view's intro animation starts, but it's a fragile link.
-                if (mGentleHeader.getTransientContainer() != null) {
-                    mGentleHeader.getTransientContainer().removeTransientView(mGentleHeader);
-                    mGentleHeader.setTransientContainer(null);
+                if (header.getTransientContainer() != null) {
+                    header.getTransientContainer().removeTransientView(header);
+                    header.setTransientContainer(null);
                 }
-                mParent.addView(mGentleHeader, firstGentleNotifIndex);
-            } else if (currentHeaderIndex != firstGentleNotifIndex - 1) {
-                // Relocate the header to be immediately before the first child in the section
-                int targetIndex = firstGentleNotifIndex;
-                if (currentHeaderIndex < firstGentleNotifIndex) {
-                    // Adjust the target index to account for the header itself being temporarily
-                    // removed during the position change.
-                    targetIndex--;
-                }
-
-                mParent.changeViewPosition(mGentleHeader, targetIndex);
+                header.setContentVisible(true);
+                mParent.addView(header, targetIndex);
+            } else if (mParent.indexOfChild(header) != targetIndex) {
+                mParent.changeViewPosition(header, targetIndex);
             }
+            return true;
         }
     }
 
-    private int adjustPeopleHubVisibilityAndPosition(
-            int targetIndex, boolean peopleNotificationsPresent) {
-        final boolean showPeopleHeader = mNumberOfSections > 2
-                && mStatusBarStateController.getState() != StatusBarState.KEYGUARD
-                && (peopleNotificationsPresent || mPeopleHubVisible);
-        final int currentHubIndex = mParent.indexOfChild(mPeopleHubView);
-        final boolean currentlyVisible = currentHubIndex >= 0;
-
-        mPeopleHubView.setCanSwipe(showPeopleHeader && !peopleNotificationsPresent);
-
-        if (!showPeopleHeader) {
-            if (currentlyVisible) {
-                mParent.removeView(mPeopleHubView);
-                return -1;
-            }
-        } else {
-            mPeopleHubView.unDismiss();
-            mPeopleHubView.resetTranslation();
-            if (!currentlyVisible) {
-                if (mPeopleHubView.getTransientContainer() != null) {
-                    mPeopleHubView.getTransientContainer().removeTransientView(mPeopleHubView);
-                    mPeopleHubView.setTransientContainer(null);
-                }
-                mParent.addView(mPeopleHubView, targetIndex);
-                return 1;
-            } else if (currentHubIndex != targetIndex) {
-                if (currentHubIndex < targetIndex) {
-                    targetIndex--;
-                }
-                mParent.changeViewPosition(mPeopleHubView, targetIndex);
-            }
-        }
-        return 0;
-    }
-
     /**
      * Updates the boundaries (as tracked by their first and last views) of the priority sections.
      *
@@ -388,7 +354,12 @@
 
             //TODO: do this in a single pass, and more better
             for (ActivatableNotificationView v : children)  {
-                if (getBucket(v) == filter) {
+                Integer bucket = getBucket(v);
+                if (bucket == null) {
+                    throw new IllegalArgumentException("Cannot find section bucket for view");
+                }
+
+                if (bucket == filter) {
                     viewsInBucket.add(v);
                 }
 
@@ -463,16 +434,17 @@
     /**
      * For now, declare the available notification buckets (sections) here so that other
      * presentation code can decide what to do based on an entry's buckets
-     *
      */
     @Retention(SOURCE)
     @IntDef(prefix = { "BUCKET_" }, value = {
+            BUCKET_HEADS_UP,
             BUCKET_PEOPLE,
             BUCKET_ALERTING,
             BUCKET_SILENT
     })
     public @interface PriorityBucket {}
-    public static final int BUCKET_PEOPLE = 0;
-    public static final int BUCKET_ALERTING = 1;
-    public static final int BUCKET_SILENT = 2;
+    public static final int BUCKET_HEADS_UP = 0;
+    public static final int BUCKET_PEOPLE = 1;
+    public static final int BUCKET_ALERTING = 2;
+    public static final int BUCKET_SILENT = 3;
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 2eeda1f..1bd9bbe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -815,7 +815,6 @@
         mBgColor = mContext.getColor(R.color.notification_shade_background_color);
         updateBackgroundDimming();
         mShelf.onUiModeChanged();
-        mSectionsManager.onUiModeChanged();
     }
 
     @ShadeViewRefactor(RefactorComponent.DECORATOR)
@@ -1632,8 +1631,8 @@
 
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ExpandableView getChildAtPosition(float touchX, float touchY) {
-        return getChildAtPosition(touchX, touchY, true /* requireMinHeight */);
-
+        return getChildAtPosition(
+                touchX, touchY, true /* requireMinHeight */, true /* ignoreDecors */);
     }
 
     /**
@@ -1642,17 +1641,18 @@
      * @param touchX           the x coordinate
      * @param touchY           the y coordinate
      * @param requireMinHeight Whether a minimum height is required for a child to be returned.
+     * @param ignoreDecors     Whether decors can be returned
      * @return the child at the given location.
      */
     @ShadeViewRefactor(RefactorComponent.COORDINATOR)
     private ExpandableView getChildAtPosition(float touchX, float touchY,
-            boolean requireMinHeight) {
+            boolean requireMinHeight, boolean ignoreDecors) {
         // find the view under the pointer, accounting for GONE views
         final int count = getChildCount();
         for (int childIdx = 0; childIdx < count; childIdx++) {
             ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
             if (slidingChild.getVisibility() != VISIBLE
-                    || slidingChild instanceof StackScrollerDecorView) {
+                    || (ignoreDecors && slidingChild instanceof StackScrollerDecorView)) {
                 continue;
             }
             float childTop = slidingChild.getTranslationY();
@@ -4166,7 +4166,9 @@
             case MotionEvent.ACTION_DOWN: {
                 final int y = (int) ev.getY();
                 mScrolledToTopOnFirstDown = isScrolledToTop();
-                if (getChildAtPosition(ev.getX(), y, false /* requireMinHeight */) == null) {
+                final ExpandableView childAtTouchPos = getChildAtPosition(
+                        ev.getX(), y, false /* requireMinHeight */, false /* ignoreDecors */);
+                if (childAtTouchPos == null) {
                     setIsBeingDragged(false);
                     recycleVelocityTracker();
                     break;
@@ -6299,8 +6301,6 @@
             }
 
             if (view instanceof PeopleHubView) {
-                PeopleHubView row = (PeopleHubView) view;
-                row.dismiss(false);
                 mSectionsManager.hidePeopleRow();
             }
 
@@ -6325,8 +6325,11 @@
 
         @Override
         public View getChildAtPosition(MotionEvent ev) {
-            View child = NotificationStackScrollLayout.this.getChildAtPosition(ev.getX(),
-                    ev.getY());
+            View child = NotificationStackScrollLayout.this.getChildAtPosition(
+                    ev.getX(),
+                    ev.getY(),
+                    true /* requireMinHeight */,
+                    false /* ignoreDecors */);
             if (child instanceof ExpandableNotificationRow) {
                 ExpandableNotificationRow row = (ExpandableNotificationRow) child;
                 ExpandableNotificationRow parent = row.getNotificationParent();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
index e5717ae..151c6b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/PeopleHubView.kt
@@ -25,30 +25,32 @@
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin
 import com.android.systemui.statusbar.notification.people.DataListener
 import com.android.systemui.statusbar.notification.people.PersonViewModel
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView
 
 class PeopleHubView(context: Context, attrs: AttributeSet) :
-        ActivatableNotificationView(context, attrs), SwipeableView {
+        StackScrollerDecorView(context, attrs), SwipeableView {
 
     private lateinit var contents: ViewGroup
-    private lateinit var personControllers: List<PersonDataListenerImpl>
 
-    val personViewAdapters: Sequence<DataListener<PersonViewModel?>>
-        get() = personControllers.asSequence()
+    lateinit var personViewAdapters: Sequence<DataListener<PersonViewModel?>>
+        private set
 
     override fun onFinishInflate() {
-        super.onFinishInflate()
         contents = requireViewById(R.id.people_list)
-        personControllers = (0 until contents.childCount)
+        personViewAdapters = (0 until contents.childCount)
                 .reversed()
                 .asSequence()
                 .mapNotNull { idx ->
                     (contents.getChildAt(idx) as? ImageView)?.let(::PersonDataListenerImpl)
                 }
                 .toList()
+                .asSequence()
+        super.onFinishInflate()
+        setVisible(true /* nowVisible */, false /* animate */)
     }
 
-    override fun getContentView(): View = contents
+    override fun findContentView(): View = contents
+    override fun findSecondaryView(): View? = null
 
     override fun hasFinishedInitialization(): Boolean = true
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index add982d..ad3ff69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -17,8 +17,8 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import android.annotation.Nullable;
+import android.annotation.StringRes;
 import android.content.Context;
-import android.graphics.RectF;
 import android.util.AttributeSet;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
@@ -28,7 +28,7 @@
 import android.widget.TextView;
 
 import com.android.systemui.R;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.row.StackScrollerDecorView;
 
 import java.util.Objects;
 
@@ -36,23 +36,22 @@
  * Similar in size and appearance to the NotificationShelf, appears at the beginning of some
  * notification sections. Currently only used for gentle notifications.
  */
-public class SectionHeaderView extends ActivatableNotificationView {
+public class SectionHeaderView extends StackScrollerDecorView {
     private ViewGroup mContents;
     private TextView mLabelView;
     private ImageView mClearAllButton;
     @Nullable private View.OnClickListener mOnClearClickListener = null;
 
-    private final RectF mTmpRect = new RectF();
-
     public SectionHeaderView(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
     @Override
     protected void onFinishInflate() {
-        super.onFinishInflate();
         mContents = Objects.requireNonNull(findViewById(R.id.content));
         bindContents();
+        super.onFinishInflate();
+        setVisible(true /* nowVisible */, false /* animate */);
     }
 
     private void bindContents() {
@@ -64,15 +63,20 @@
     }
 
     @Override
-    protected View getContentView() {
+    protected View findContentView() {
         return mContents;
     }
 
+    @Override
+    protected View findSecondaryView() {
+        return null;
+    }
+
     /**
      * Destroys and reinflates the visible contents of the section header. For use on configuration
      * changes or any other time that layout values might need to be re-evaluated.
      *
-     * Does not reinflate the base content view itself ({@link #getContentView()} or any of the
+     * Does not reinflate the base content view itself ({@link #findContentView()} or any of the
      * decorator views, such as the background view or shadow view.
      */
     void reinflateContents() {
@@ -88,35 +92,20 @@
         return true;
     }
 
-    /** Must be called whenever the UI mode changes (i.e. when we enter night mode). */
-    void onUiModeChanged() {
-        updateBackgroundColors();
-        mLabelView.setTextColor(
-                getContext().getColor(R.color.notification_section_header_label_color));
-        mClearAllButton.setImageResource(
-                R.drawable.status_bar_notification_section_header_clear_btn);
-    }
-
     void setAreThereDismissableGentleNotifs(boolean areThereDismissableGentleNotifs) {
         mClearAllButton.setVisibility(areThereDismissableGentleNotifs ? View.VISIBLE : View.GONE);
     }
 
     @Override
-    protected boolean disallowSingleClick(MotionEvent event) {
-        // Disallow single click on lockscreen if user is tapping on clear all button
-        mTmpRect.set(
-                mClearAllButton.getLeft(),
-                mClearAllButton.getTop(),
-                mClearAllButton.getLeft() + mClearAllButton.getWidth(),
-                mClearAllButton.getTop() + mClearAllButton.getHeight());
-        return mTmpRect.contains(event.getX(), event.getY());
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        return super.onInterceptTouchEvent(ev);
     }
 
     /**
      * Fired whenever the user clicks on the body of the header (e.g. no sub-buttons or anything).
      */
     void setOnHeaderClickListener(View.OnClickListener listener) {
-        mContents.setOnClickListener(listener);
+        mLabelView.setOnClickListener(listener);
     }
 
     /** Fired when the user clicks on the "X" button on the far right of the header. */
@@ -124,4 +113,8 @@
         mOnClearClickListener = listener;
         mClearAllButton.setOnClickListener(listener);
     }
+
+    void setHeaderText(@StringRes int resId) {
+        mLabelView.setText(resId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 691e1c4..1dde5c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -150,14 +150,26 @@
     private KeyguardViewMediator mKeyguardViewMediator;
     private ScrimController mScrimController;
     private StatusBar mStatusBar;
-    private int mPendingAuthenticatedUserId = -1;
-    private BiometricSourceType mPendingAuthenticatedBioSourceType = null;
+    private PendingAuthenticated mPendingAuthenticated = null;
     private boolean mPendingShowBouncer;
     private boolean mHasScreenTurnedOnSinceAuthenticating;
     private boolean mFadedAwayAfterWakeAndUnlock;
 
     private final MetricsLogger mMetricsLogger;
 
+    private static final class PendingAuthenticated {
+        public final int userId;
+        public final BiometricSourceType biometricSourceType;
+        public final boolean isStrongBiometric;
+
+        PendingAuthenticated(int userId, BiometricSourceType biometricSourceType,
+                boolean isStrongBiometric) {
+            this.userId = userId;
+            this.biometricSourceType = biometricSourceType;
+            this.isStrongBiometric = isStrongBiometric;
+        }
+    }
+
     @Inject
     public BiometricUnlockController(Context context, DozeScrimController dozeScrimController,
             KeyguardViewMediator keyguardViewMediator, ScrimController scrimController,
@@ -251,28 +263,30 @@
     }
 
     @Override
-    public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
+    public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
         Trace.beginSection("BiometricUnlockController#onBiometricAuthenticated");
         if (mUpdateMonitor.isGoingToSleep()) {
-            mPendingAuthenticatedUserId = userId;
-            mPendingAuthenticatedBioSourceType = biometricSourceType;
+            mPendingAuthenticated = new PendingAuthenticated(userId, biometricSourceType,
+                    isStrongBiometric);
             Trace.endSection();
             return;
         }
         mMetricsLogger.write(new LogMaker(MetricsEvent.BIOMETRIC_AUTH)
                 .setType(MetricsEvent.TYPE_SUCCESS).setSubtype(toSubtype(biometricSourceType)));
         boolean unlockAllowed = mKeyguardBypassController.onBiometricAuthenticated(
-                biometricSourceType);
+                biometricSourceType, isStrongBiometric);
         if (unlockAllowed) {
             mKeyguardViewMediator.userActivity();
-            startWakeAndUnlock(biometricSourceType);
+            startWakeAndUnlock(biometricSourceType, isStrongBiometric);
         } else {
             Log.d(TAG, "onBiometricAuthenticated aborted by bypass controller");
         }
     }
 
-    public void startWakeAndUnlock(BiometricSourceType biometricSourceType) {
-        startWakeAndUnlock(calculateMode(biometricSourceType));
+    public void startWakeAndUnlock(BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
+        startWakeAndUnlock(calculateMode(biometricSourceType, isStrongBiometric));
     }
 
     public void startWakeAndUnlock(@WakeAndUnlockMode int mode) {
@@ -373,45 +387,46 @@
     public void onStartedGoingToSleep(int why) {
         resetMode();
         mFadedAwayAfterWakeAndUnlock = false;
-        mPendingAuthenticatedUserId = -1;
-        mPendingAuthenticatedBioSourceType = null;
+        mPendingAuthenticated = null;
     }
 
     @Override
     public void onFinishedGoingToSleep(int why) {
         Trace.beginSection("BiometricUnlockController#onFinishedGoingToSleep");
-        BiometricSourceType pendingType = mPendingAuthenticatedBioSourceType;
-        int pendingUserId = mPendingAuthenticatedUserId;
-        if (pendingUserId != -1 && pendingType != null) {
+        if (mPendingAuthenticated != null) {
             // Post this to make sure it's executed after the device is fully locked.
-            mHandler.post(() -> onBiometricAuthenticated(pendingUserId, pendingType));
+            mHandler.post(() -> onBiometricAuthenticated(mPendingAuthenticated.userId,
+                    mPendingAuthenticated.biometricSourceType,
+                    mPendingAuthenticated.isStrongBiometric));
+            mPendingAuthenticated = null;
         }
-        mPendingAuthenticatedUserId = -1;
-        mPendingAuthenticatedBioSourceType = null;
         Trace.endSection();
     }
 
     public boolean hasPendingAuthentication() {
-        return mPendingAuthenticatedUserId != -1
-                && mUpdateMonitor.isUnlockingWithBiometricAllowed()
-                && mPendingAuthenticatedUserId == KeyguardUpdateMonitor.getCurrentUser();
+        return mPendingAuthenticated != null
+                && mUpdateMonitor
+                    .isUnlockingWithBiometricAllowed(mPendingAuthenticated.isStrongBiometric)
+                && mPendingAuthenticated.userId == KeyguardUpdateMonitor.getCurrentUser();
     }
 
     public int getMode() {
         return mMode;
     }
 
-    private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType) {
+    private @WakeAndUnlockMode int calculateMode(BiometricSourceType biometricSourceType,
+            boolean isStrongBiometric) {
         if (biometricSourceType == BiometricSourceType.FACE
                 || biometricSourceType == BiometricSourceType.IRIS) {
-            return calculateModeForPassiveAuth();
+            return calculateModeForPassiveAuth(isStrongBiometric);
         } else {
-            return calculateModeForFingerprint();
+            return calculateModeForFingerprint(isStrongBiometric);
         }
     }
 
-    private @WakeAndUnlockMode int calculateModeForFingerprint() {
-        boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
+    private @WakeAndUnlockMode int calculateModeForFingerprint(boolean isStrongBiometric) {
+        boolean unlockingAllowed =
+                mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
         boolean deviceDreaming = mUpdateMonitor.isDreaming();
 
         if (!mUpdateMonitor.isDeviceInteractive()) {
@@ -440,8 +455,9 @@
         return MODE_NONE;
     }
 
-    private @WakeAndUnlockMode int calculateModeForPassiveAuth() {
-        boolean unlockingAllowed = mUpdateMonitor.isUnlockingWithBiometricAllowed();
+    private @WakeAndUnlockMode int calculateModeForPassiveAuth(boolean isStrongBiometric) {
+        boolean unlockingAllowed =
+                mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric);
         boolean deviceDreaming = mUpdateMonitor.isDreaming();
         boolean bypass = mKeyguardBypassController.getBypassEnabled();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index c6e3fde..63fe700 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -19,24 +19,15 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.content.res.Resources;
-import android.graphics.Rect;
 import android.graphics.Region;
-import android.util.Log;
 import android.util.Pools;
-import android.view.DisplayCutout;
-import android.view.Gravity;
-import android.view.View;
-import android.view.ViewTreeObserver;
-import android.view.WindowInsets;
 
 import androidx.collection.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
-import com.android.systemui.ScreenDecorations;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
 import com.android.systemui.statusbar.StatusBarState;
@@ -49,31 +40,27 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Stack;
 
 /**
  * A implementation of HeadsUpManager for phone and car.
  */
 public class HeadsUpManagerPhone extends HeadsUpManager implements Dumpable,
-        VisualStabilityManager.Callback, OnHeadsUpChangedListener,
-        ConfigurationController.ConfigurationListener, StateListener {
+        VisualStabilityManager.Callback, OnHeadsUpChangedListener {
     private static final String TAG = "HeadsUpManagerPhone";
 
     @VisibleForTesting
     final int mExtensionTime;
-    private final StatusBarStateController mStatusBarStateController;
     private final KeyguardBypassController mBypassController;
+    private final NotificationGroupManager mGroupManager;
+    private final List<OnHeadsUpPhoneListenerChange> mHeadsUpPhoneListeners = new ArrayList<>();
     private final int mAutoHeadsUpNotificationDecay;
-    private View mNotificationShadeWindowView;
-    private NotificationGroupManager mGroupManager;
     private VisualStabilityManager mVisualStabilityManager;
-    private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     private boolean mReleaseOnExpandFinish;
 
-    private int mStatusBarHeight;
-    private int mHeadsUpInset;
-    private int mDisplayCutoutTouchableRegionSize;
     private boolean mTrackingHeadsUp;
     private HashSet<String> mSwipedOutKeys = new HashSet<>();
     private HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
@@ -81,12 +68,13 @@
     private ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
             = new ArraySet<>();
     private boolean mIsExpanded;
-    private int[] mTmpTwoArray = new int[2];
     private boolean mHeadsUpGoingAway;
     private int mStatusBarState;
-    private Region mTouchableRegion = new Region();
-
     private AnimationStateHandler mAnimationStateHandler;
+    private int mHeadsUpInset;
+
+    // Used for determining the region for touch interaction
+    private final Region mTouchableRegion = new Region();
 
     private final Pools.Pool<HeadsUpEntryPhone> mEntryPool = new Pools.Pool<HeadsUpEntryPhone>() {
         private Stack<HeadsUpEntryPhone> mPoolObjects = new Stack<>();
@@ -111,76 +99,96 @@
 
     public HeadsUpManagerPhone(@NonNull final Context context,
             StatusBarStateController statusBarStateController,
-            KeyguardBypassController bypassController) {
+            KeyguardBypassController bypassController,
+            NotificationGroupManager groupManager,
+            ConfigurationController configurationController) {
         super(context);
         Resources resources = mContext.getResources();
         mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
         mAutoHeadsUpNotificationDecay = resources.getInteger(
                 R.integer.auto_heads_up_notification_decay);
-        mStatusBarStateController = statusBarStateController;
-        mStatusBarStateController.addCallback(this);
+        statusBarStateController.addCallback(mStatusBarStateListener);
         mBypassController = bypassController;
-
-        initResources();
-    }
-
-    public void setUp(@NonNull View notificationShadeWindowView,
-            @NonNull NotificationGroupManager groupManager,
-            @NonNull StatusBar bar,
-            @NonNull VisualStabilityManager visualStabilityManager) {
-        mNotificationShadeWindowView = notificationShadeWindowView;
-        mStatusBarTouchableRegionManager = new StatusBarTouchableRegionManager(this, bar,
-                notificationShadeWindowView);
         mGroupManager = groupManager;
-        mVisualStabilityManager = visualStabilityManager;
 
-        addListener(new OnHeadsUpChangedListener() {
+        updateResources();
+        configurationController.addCallback(new ConfigurationController.ConfigurationListener() {
             @Override
-            public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
-                if (Log.isLoggable(TAG, Log.WARN)) {
-                    Log.w(TAG, "onHeadsUpPinnedModeChanged");
-                }
-                mStatusBarTouchableRegionManager.updateTouchableRegion();
+            public void onDensityOrFontScaleChanged() {
+                updateResources();
+            }
+
+            @Override
+            public void onOverlayChanged() {
+                updateResources();
             }
         });
     }
 
+    void setup(VisualStabilityManager visualStabilityManager) {
+        mVisualStabilityManager = visualStabilityManager;
+    }
+
     public void setAnimationStateHandler(AnimationStateHandler handler) {
         mAnimationStateHandler = handler;
     }
 
-    private void initResources() {
+    private void updateResources() {
         Resources resources = mContext.getResources();
-        mStatusBarHeight = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
-        mHeadsUpInset = mStatusBarHeight + resources.getDimensionPixelSize(
-                R.dimen.heads_up_status_bar_padding);
-        mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.display_cutout_touchable_region_size);
-    }
-
-    @Override
-    public void onDensityOrFontScaleChanged() {
-        super.onDensityOrFontScaleChanged();
-        initResources();
-    }
-
-    @Override
-    public void onOverlayChanged() {
-        initResources();
+        mHeadsUpInset =
+                resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height)
+                        + resources.getDimensionPixelSize(R.dimen.heads_up_status_bar_padding);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  Public methods:
 
     /**
+     * Add a listener to receive callbacks onHeadsUpGoingAway
+     */
+    void addHeadsUpPhoneListener(OnHeadsUpPhoneListenerChange listener) {
+        mHeadsUpPhoneListeners.add(listener);
+    }
+
+    /**
+     * Gets the touchable region needed for heads up notifications. Returns null if no touchable
+     * region is required (ie: no heads up notification currently exists).
+     */
+    @Nullable Region getTouchableRegion() {
+        NotificationEntry topEntry = getTopEntry();
+
+        // This call could be made in an inconsistent state while the pinnedMode hasn't been
+        // updated yet, but callbacks leading out of the headsUp manager, querying it. Let's
+        // therefore also check if the topEntry is null.
+        if (!hasPinnedHeadsUp() || topEntry == null) {
+            return null;
+        } else {
+            if (topEntry.isChildInGroup()) {
+                final NotificationEntry groupSummary =
+                        mGroupManager.getGroupSummary(topEntry.getSbn());
+                if (groupSummary != null) {
+                    topEntry = groupSummary;
+                }
+            }
+            ExpandableNotificationRow topRow = topEntry.getRow();
+            int[] tmpArray = new int[2];
+            topRow.getLocationOnScreen(tmpArray);
+            int minX = tmpArray[0];
+            int maxX = tmpArray[0] + topRow.getWidth();
+            int height = topRow.getIntrinsicHeight();
+            mTouchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
+            return mTouchableRegion;
+        }
+    }
+
+    /**
      * Decides whether a click is invalid for a notification, i.e it has not been shown long enough
      * that a user might have consciously clicked on it.
      *
      * @param key the key of the touched notification
      * @return whether the touch is invalid and should be discarded
      */
-    public boolean shouldSwallowClick(@NonNull String key) {
+    boolean shouldSwallowClick(@NonNull String key) {
         HeadsUpManager.HeadsUpEntry entry = getHeadsUpEntry(key);
         return entry != null && mClock.currentTimeMillis() < entry.mPostTime;
     }
@@ -213,39 +221,12 @@
      *
      * @param isExpanded True to notify expanded, false to notify collapsed.
      */
-    public void setIsPanelExpanded(boolean isExpanded) {
+    void setIsPanelExpanded(boolean isExpanded) {
         if (isExpanded != mIsExpanded) {
             mIsExpanded = isExpanded;
             if (isExpanded) {
                 mHeadsUpGoingAway = false;
             }
-            mStatusBarTouchableRegionManager.setIsStatusBarExpanded(isExpanded);
-            mStatusBarTouchableRegionManager.updateTouchableRegion();
-        }
-    }
-
-    @Override
-    public void onStateChanged(int newState) {
-        boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
-        boolean isKeyguard = newState == StatusBarState.KEYGUARD;
-        mStatusBarState = newState;
-        if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
-            String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
-            for (String key : keys) {
-                removeAlertEntry(key);
-            }
-            mKeysToRemoveWhenLeavingKeyguard.clear();
-        }
-    }
-
-    @Override
-    public void onDozingChanged(boolean isDozing) {
-        if (!isDozing) {
-            // Let's make sure all huns we got while dozing time out within the normal timeout
-            // duration. Otherwise they could get stuck for a very long time
-            for (AlertEntry entry : mAlertEntries.values()) {
-                entry.updateEntry(true /* updatePostTime */);
-            }
         }
     }
 
@@ -262,18 +243,16 @@
      * Set that we are exiting the headsUp pinned mode, but some notifications might still be
      * animating out. This is used to keep the touchable regions in a sane state.
      */
-    public void setHeadsUpGoingAway(boolean headsUpGoingAway) {
+    void setHeadsUpGoingAway(boolean headsUpGoingAway) {
         if (headsUpGoingAway != mHeadsUpGoingAway) {
             mHeadsUpGoingAway = headsUpGoingAway;
-            if (!headsUpGoingAway) {
-                mStatusBarTouchableRegionManager.updateTouchableRegionAfterLayout();
-            } else {
-                mStatusBarTouchableRegionManager.updateTouchableRegion();
+            for (OnHeadsUpPhoneListenerChange listener : mHeadsUpPhoneListeners) {
+                listener.onHeadsUpGoingAwayStateChanged(headsUpGoingAway);
             }
         }
     }
 
-    public boolean isHeadsUpGoingAway() {
+    boolean isHeadsUpGoingAway() {
         return mHeadsUpGoingAway;
     }
 
@@ -346,63 +325,6 @@
         dumpInternal(fd, pw, args);
     }
 
-    /**
-     * Update touch insets to include any area needed for touching a heads up notification.
-     *
-     * @param info Insets that will include heads up notification touch area after execution.
-     */
-    @Nullable
-    public void updateTouchableRegion(ViewTreeObserver.InternalInsetsInfo info) {
-        info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
-        info.touchableRegion.set(calculateTouchableRegion());
-    }
-
-    public Region calculateTouchableRegion() {
-        NotificationEntry topEntry = getTopEntry();
-        // This call could be made in an inconsistent state while the pinnedMode hasn't been
-        // updated yet, but callbacks leading out of the headsUp manager, querying it. Let's
-        // therefore also check if the topEntry is null.
-        if (!hasPinnedHeadsUp() || topEntry == null) {
-            mTouchableRegion.set(0, 0, mNotificationShadeWindowView.getWidth(), mStatusBarHeight);
-            updateRegionForNotch(mTouchableRegion);
-
-        } else {
-            if (topEntry.isChildInGroup()) {
-                final NotificationEntry groupSummary =
-                        mGroupManager.getGroupSummary(topEntry.getSbn());
-                if (groupSummary != null) {
-                    topEntry = groupSummary;
-                }
-            }
-            ExpandableNotificationRow topRow = topEntry.getRow();
-            topRow.getLocationOnScreen(mTmpTwoArray);
-            int minX = mTmpTwoArray[0];
-            int maxX = mTmpTwoArray[0] + topRow.getWidth();
-            int height = topRow.getIntrinsicHeight();
-            mTouchableRegion.set(minX, 0, maxX, mHeadsUpInset + height);
-        }
-        return mTouchableRegion;
-    }
-
-    private void updateRegionForNotch(Region region) {
-        WindowInsets windowInsets = mNotificationShadeWindowView.getRootWindowInsets();
-        if (windowInsets == null) {
-            Log.w(TAG, "StatusBarWindowView is not attached.");
-            return;
-        }
-        DisplayCutout cutout = windowInsets.getDisplayCutout();
-        if (cutout == null) {
-            return;
-        }
-
-        // Expand touchable region such that we also catch touches that just start below the notch
-        // area.
-        Rect bounds = new Rect();
-        ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds);
-        bounds.offset(0, mDisplayCutoutTouchableRegionSize);
-        region.union(bounds);
-    }
-
     @Override
     public boolean shouldExtendLifetime(NotificationEntry entry) {
         // We should not defer the removal if reordering isn't allowed since otherwise
@@ -411,11 +333,6 @@
         return mVisualStabilityManager.isReorderingAllowed() && super.shouldExtendLifetime(entry);
     }
 
-    @Override
-    public void onConfigChanged(Configuration newConfig) {
-        initResources();
-    }
-
     ///////////////////////////////////////////////////////////////////////////////////////////////
     //  VisualStabilityManager.Callback overrides:
 
@@ -522,8 +439,7 @@
                         // time out anyway
                         && !entry.showingPulsing()) {
                     mEntriesToRemoveWhenReorderingAllowed.add(entry);
-                    mVisualStabilityManager.addReorderingAllowedCallback(
-                            HeadsUpManagerPhone.this);
+                    mVisualStabilityManager.addReorderingAllowedCallback(HeadsUpManagerPhone.this);
                 } else if (mTrackingHeadsUp) {
                     mEntriesToRemoveAfterExpand.add(entry);
                 } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
@@ -626,4 +542,42 @@
     public interface AnimationStateHandler {
         void setHeadsUpGoingAwayAnimationsAllowed(boolean allowed);
     }
+
+    /**
+     * Listener to register for HeadsUpNotification Phone changes.
+     */
+    public interface OnHeadsUpPhoneListenerChange {
+        /**
+         * Called when a heads up notification is 'going away' or no longer 'going away'.
+         * See {@link HeadsUpManagerPhone#setHeadsUpGoingAway}.
+         */
+        void onHeadsUpGoingAwayStateChanged(boolean headsUpGoingAway);
+    }
+
+    private final StateListener mStatusBarStateListener = new StateListener() {
+        @Override
+        public void onStateChanged(int newState) {
+            boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
+            boolean isKeyguard = newState == StatusBarState.KEYGUARD;
+            mStatusBarState = newState;
+            if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
+                String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
+                for (String key : keys) {
+                    removeAlertEntry(key);
+                }
+                mKeysToRemoveWhenLeavingKeyguard.clear();
+            }
+        }
+
+        @Override
+        public void onDozingChanged(boolean isDozing) {
+            if (!isDozing) {
+                // Let's make sure all huns we got while dozing time out within the normal timeout
+                // duration. Otherwise they could get stuck for a very long time
+                for (AlertEntry entry : mAlertEntries.values()) {
+                    entry.updateEntry(true /* updatePostTime */);
+                }
+            }
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
index b4d0d47..03918e0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBypassController.kt
@@ -38,11 +38,20 @@
     private val mKeyguardStateController: KeyguardStateController
     private val statusBarStateController: StatusBarStateController
     private var hasFaceFeature: Boolean
+    private var pendingUnlock: PendingUnlock? = null
 
     /**
+     * Pending unlock info:
+     *
      * The pending unlock type which is set if the bypass was blocked when it happened.
+     *
+     * Whether the pending unlock type is strong biometric or non-strong biometric
+     * (i.e. weak or convenience).
      */
-    private var pendingUnlockType: BiometricSourceType? = null
+    private data class PendingUnlock(
+        val pendingUnlockType: BiometricSourceType,
+        val isStrongBiometric: Boolean
+    )
 
     lateinit var unlockController: BiometricUnlockController
     var isPulseExpanding = false
@@ -86,7 +95,7 @@
         statusBarStateController.addCallback(object : StatusBarStateController.StateListener {
             override fun onStateChanged(newState: Int) {
                 if (newState != StatusBarState.KEYGUARD) {
-                    pendingUnlockType = null
+                    pendingUnlock = null
                 }
             }
         })
@@ -101,7 +110,7 @@
         lockscreenUserManager.addUserChangedListener(
                 object : NotificationLockscreenUserManager.UserChangedListener {
                     override fun onUserChanged(userId: Int) {
-                        pendingUnlockType = null
+                        pendingUnlock = null
                     }
                 })
     }
@@ -111,11 +120,14 @@
      *
      * @return false if we can not wake and unlock right now
      */
-    fun onBiometricAuthenticated(biometricSourceType: BiometricSourceType): Boolean {
+    fun onBiometricAuthenticated(
+        biometricSourceType: BiometricSourceType,
+        isStrongBiometric: Boolean
+    ): Boolean {
         if (bypassEnabled) {
             val can = canBypass()
             if (!can && (isPulseExpanding || qSExpanded)) {
-                pendingUnlockType = biometricSourceType
+                pendingUnlock = PendingUnlock(biometricSourceType, isStrongBiometric)
             }
             return can
         }
@@ -123,10 +135,12 @@
     }
 
     fun maybePerformPendingUnlock() {
-        if (pendingUnlockType != null) {
-            if (onBiometricAuthenticated(pendingUnlockType!!)) {
-                unlockController.startWakeAndUnlock(pendingUnlockType)
-                pendingUnlockType = null
+        if (pendingUnlock != null) {
+            if (onBiometricAuthenticated(pendingUnlock!!.pendingUnlockType,
+                            pendingUnlock!!.isStrongBiometric)) {
+                unlockController.startWakeAndUnlock(pendingUnlock!!.pendingUnlockType,
+                        pendingUnlock!!.isStrongBiometric)
+                pendingUnlock = null
             }
         }
     }
@@ -162,12 +176,17 @@
     }
 
     fun onStartedGoingToSleep() {
-        pendingUnlockType = null
+        pendingUnlock = null
     }
 
     override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
         pw.println("KeyguardBypassController:")
-        pw.println("  pendingUnlockType: $pendingUnlockType")
+        if (pendingUnlock != null) {
+            pw.println("  mPendingUnlock.pendingUnlockType: ${pendingUnlock!!.pendingUnlockType}")
+            pw.println("  mPendingUnlock.isStrongBiometric: ${pendingUnlock!!.isStrongBiometric}")
+        } else {
+            pw.println("  mPendingUnlock: $pendingUnlock")
+        }
         pw.println("  bypassEnabled: $bypassEnabled")
         pw.println("  canBypass: ${canBypass()}")
         pw.println("  bouncerShowing: $bouncerShowing")
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 60589843..61cef68 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -387,7 +387,12 @@
     public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(info);
         boolean fingerprintRunning = mKeyguardUpdateMonitor.isFingerprintDetectionRunning();
-        boolean unlockingAllowed = mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed();
+        // Only checking if unlocking with Biometric is allowed (no matter strong or non-strong
+        // as long as primary auth, i.e. PIN/pattern/password, is not required), so it's ok to
+        // pass true for isStrongBiometric to isUnlockingWithBiometricAllowed() to bypass the
+        // check of whether non-strong biometric is allowed
+        boolean unlockingAllowed = mKeyguardUpdateMonitor
+                        .isUnlockingWithBiometricAllowed(true /* isStrongBiometric */);
         if (fingerprintRunning && unlockingAllowed) {
             AccessibilityNodeInfo.AccessibilityAction unlock
                     = new AccessibilityNodeInfo.AccessibilityAction(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d790cbc..84aecd4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -63,7 +63,6 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
-import com.android.systemui.DockedStackExistsListener;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.assist.AssistHandleViewController;
@@ -75,6 +74,7 @@
 import com.android.systemui.shared.system.ActivityManagerWrapper;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
+import com.android.systemui.stackdivider.Divider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.NavigationBarController;
 import com.android.systemui.statusbar.policy.DeadZone;
@@ -869,7 +869,8 @@
 
         getImeSwitchButton().setOnClickListener(mImeSwitcherClickListener);
 
-        DockedStackExistsListener.register(mDockedListener);
+        Divider divider = Dependency.get(Divider.class);
+        divider.registerInSplitScreenListener(mDockedListener);
         updateOrientationViews();
         reloadNavIcons();
     }
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 d2186f9..c61d7bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -202,8 +202,10 @@
 
                 @Override
                 public void onBiometricAuthenticated(int userId,
-                        BiometricSourceType biometricSourceType) {
-                    if (mFirstBypassAttempt && mUpdateMonitor.isUnlockingWithBiometricAllowed()) {
+                        BiometricSourceType biometricSourceType,
+                        boolean isStrongBiometric) {
+                    if (mFirstBypassAttempt
+                            && mUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric)) {
                         mDelayShowingKeyguardStatusBar = true;
                     }
                 }
@@ -453,10 +455,11 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor, MetricsLogger metricsLogger,
             ActivityManager activityManager, ZenModeController zenModeController,
             ConfigurationController configurationController,
-            FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
+            FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         super(view, falsingManager, dozeLog, keyguardStateController,
                 (SysuiStatusBarStateController) statusBarStateController, vibratorHelper,
-                latencyTracker, flingAnimationUtilsBuilder);
+                latencyTracker, flingAnimationUtilsBuilder, statusBarTouchableRegionManager);
         mView = view;
         mMetricsLogger = metricsLogger;
         mActivityManager = activityManager;
@@ -704,9 +707,9 @@
 
     private Rect calculateGestureExclusionRect() {
         Rect exclusionRect = null;
-        Region touchableRegion = mHeadsUpManager.calculateTouchableRegion();
+        Region touchableRegion = mStatusBarTouchableRegionManager.calculateTouchableRegion();
         if (isFullyCollapsed() && touchableRegion != null) {
-            // Note: The heads up manager also calculates the non-pinned touchable region
+            // Note: The manager also calculates the non-pinned touchable region
             exclusionRect = touchableRegion.getBounds();
         }
         return exclusionRect != null ? exclusionRect : EMPTY_RECT;
@@ -1914,6 +1917,7 @@
         boolean isExpanded = !isFullyCollapsed() || mExpectingSynthesizedDown;
         if (mPanelExpanded != isExpanded) {
             mHeadsUpManager.setIsPanelExpanded(isExpanded);
+            mStatusBarTouchableRegionManager.setPanelExpanded(isExpanded);
             mStatusBar.setPanelExpanded(isExpanded);
             mPanelExpanded = isExpanded;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
index d016217..2dd42c2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowController.java
@@ -40,6 +40,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
+import com.android.systemui.DumpController;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
@@ -101,7 +102,8 @@
             IActivityManager activityManager, DozeParameters dozeParameters,
             StatusBarStateController statusBarStateController,
             ConfigurationController configurationController,
-            KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor) {
+            KeyguardBypassController keyguardBypassController, SysuiColorExtractor colorExtractor,
+            DumpController dumpController) {
         mContext = context;
         mWindowManager = windowManager;
         mActivityManager = activityManager;
@@ -111,6 +113,7 @@
         mLpChanged = new LayoutParams();
         mKeyguardBypassController = keyguardBypassController;
         mColorExtractor = colorExtractor;
+        dumpController.registerDumpable(this);
 
         mLockScreenDisplayTimeout = context.getResources()
                 .getInteger(R.integer.config_lockScreenDisplayTimeout);
@@ -594,7 +597,7 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("StatusBarWindowController:");
+        pw.println(TAG + ":");
         pw.println("  mKeyguardDisplayMode=" + mKeyguardDisplayMode);
         pw.println(mCurrentState);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index af46f7b..30367ed 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -73,6 +73,7 @@
 
     protected StatusBar mStatusBar;
     protected HeadsUpManagerPhone mHeadsUpManager;
+    protected final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
 
     private float mPeekHeight;
     private float mHintDistance;
@@ -206,7 +207,9 @@
             FalsingManager falsingManager, DozeLog dozeLog,
             KeyguardStateController keyguardStateController,
             SysuiStatusBarStateController statusBarStateController, VibratorHelper vibratorHelper,
-            LatencyTracker latencyTracker, FlingAnimationUtils.Builder flingAnimationUtilsBuilder) {
+            LatencyTracker latencyTracker,
+            FlingAnimationUtils.Builder flingAnimationUtilsBuilder,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         mView = view;
         mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
             @Override
@@ -251,6 +254,7 @@
                 R.bool.config_enableNotificationShadeDrag);
         mVibratorHelper = vibratorHelper;
         mVibrateOnOpening = mResources.getBoolean(R.bool.config_vibrateOnIconAnimation);
+        mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
     }
 
     protected void loadDimens() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 260f94c..1ab36c5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -678,6 +678,12 @@
     }
 
     @Override
+    public void onCountdownEnd() {
+        if (DEBUG) Log.d(TAG, "screenrecord: hiding icon during countdown");
+        mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
+    }
+
+    @Override
     public void onRecordingStart() {
         if (DEBUG) Log.d(TAG, "screenrecord: showing icon");
         mIconController.setIcon(mSlotScreenRecord,
@@ -687,7 +693,7 @@
 
     @Override
     public void onRecordingEnd() {
-        // Ensure this is on the main thread, since it could be called during countdown
+        // Ensure this is on the main thread
         if (DEBUG) Log.d(TAG, "screenrecord: hiding icon");
         mHandler.post(() -> mIconController.setIconVisibility(mSlotScreenRecord, false));
     }
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 10821d6..945a9db 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -21,7 +21,6 @@
 import android.animation.ValueAnimator;
 import android.annotation.IntDef;
 import android.app.AlarmManager;
-import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
@@ -45,7 +44,6 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.statusbar.ScrimView;
 import com.android.systemui.statusbar.notification.stack.ViewState;
@@ -116,7 +114,7 @@
      * A scrim varies its opacity based on a busyness factor, for example
      * how many notifications are currently visible.
      */
-    public static final float BUSY_SCRIM_ALPHA = 0.54f;
+    public static final float BUSY_SCRIM_ALPHA = 0.75f;
 
     /**
      * The most common scrim, the one under the keyguard.
@@ -146,8 +144,6 @@
     private GradientColors mColors;
     private boolean mNeedsDrawableColorUpdate;
 
-    private float mScrimBehindAlpha;
-    private float mScrimBehindAlphaResValue;
     private float mScrimBehindAlphaKeyguard = SCRIM_BEHIND_ALPHA_KEYGUARD;
 
     // Assuming the shade is expanded during initialization
@@ -192,7 +188,6 @@
     @Inject
     public ScrimController(LightBarController lightBarController, DozeParameters dozeParameters,
             AlarmManager alarmManager, KeyguardStateController keyguardStateController,
-            @Main Resources resources,
             DelayedWakeLock.Builder delayedWakeLockBuilder, Handler handler,
             KeyguardUpdateMonitor keyguardUpdateMonitor, SysuiColorExtractor sysuiColorExtractor,
             DockManager dockManager) {
@@ -203,14 +198,12 @@
         mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
-        mScrimBehindAlphaResValue = resources.getFloat(R.dimen.scrim_behind_alpha);
         mHandler = handler;
         mTimeTicker = new AlarmTimeout(alarmManager, this::onHideWallpaperTimeout,
                 "hide_aod_wallpaper", mHandler);
         mWakeLock = delayedWakeLockBuilder.setHandler(mHandler).setTag("Scrims").build();
         // Scrim alpha is initially set to the value on the resource but might be changed
         // to make sure that text on top of it is legible.
-        mScrimBehindAlpha = mScrimBehindAlphaResValue;
         mDozeParameters = dozeParameters;
         mDockManager = dockManager;
         keyguardStateController.addCallback(new KeyguardStateController.Callback() {
@@ -587,7 +580,6 @@
             int mainColor = mColors.getMainColor();
             float minOpacity = ColorUtils.calculateMinimumBackgroundAlpha(textColor, mainColor,
                     4.5f /* minimumContrast */) / 255f;
-            mScrimBehindAlpha = Math.max(mScrimBehindAlphaResValue, minOpacity);
             dispatchScrimState(mScrimBehind.getViewAlpha());
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 301eac2..0d3b09a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -163,7 +163,6 @@
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.stackdivider.Divider;
-import com.android.systemui.stackdivider.WindowManagerProxy;
 import com.android.systemui.statusbar.BackDropView;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.CrossFadeHelper;
@@ -356,6 +355,7 @@
     private final KeyguardBypassController mKeyguardBypassController;
     private final KeyguardStateController mKeyguardStateController;
     private final HeadsUpManagerPhone mHeadsUpManager;
+    private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     private final DynamicPrivacyController mDynamicPrivacyController;
     private final BypassHeadsUpNotifier mBypassHeadsUpNotifier;
     private final FalsingManager mFalsingManager;
@@ -676,7 +676,8 @@
             KeyguardDismissUtil keyguardDismissUtil,
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
-            DismissCallbackRegistry dismissCallbackRegistry) {
+            DismissCallbackRegistry dismissCallbackRegistry,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         super(context);
         mNotificationsController = notificationsController;
         mLightBarController = lightBarController;
@@ -688,6 +689,7 @@
         mKeyguardBypassController = keyguardBypassController;
         mKeyguardStateController = keyguardStateController;
         mHeadsUpManager = headsUpManagerPhone;
+        mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
         mDynamicPrivacyController = dynamicPrivacyController;
         mBypassHeadsUpNotifier = bypassHeadsUpNotifier;
         mFalsingManager = falsingManager;
@@ -1031,9 +1033,8 @@
                         CollapsedStatusBarFragment.TAG)
                 .commit();
 
-        mHeadsUpManager.setUp(mNotificationShadeWindowView, mGroupManager, this,
-                mVisualStabilityManager);
-        mConfigurationController.addCallback(mHeadsUpManager);
+        mHeadsUpManager.setup(mVisualStabilityManager);
+        mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
         mHeadsUpManager.addListener(this);
         mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
         mHeadsUpManager.addListener(mVisualStabilityManager);
@@ -1410,8 +1411,11 @@
         if (!mRecentsOptional.isPresent()) {
             return false;
         }
-        int dockSide = WindowManagerProxy.getInstance().getDockSide();
-        if (dockSide == WindowManager.DOCKED_INVALID) {
+        Divider divider = null;
+        if (mDividerOptional.isPresent()) {
+            divider = mDividerOptional.get();
+        }
+        if (divider == null || !divider.inSplitMode()) {
             final int navbarPos = WindowManagerWrapper.getInstance().getNavBarPosition(mDisplayId);
             if (navbarPos == NAV_BAR_POS_INVALID) {
                 return false;
@@ -1421,16 +1425,13 @@
                     : SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
             return mRecentsOptional.get().splitPrimaryTask(createMode, null, metricsDockAction);
         } else {
-            if (mDividerOptional.isPresent()) {
-                Divider divider = mDividerOptional.get();
-                if (divider.isMinimized() && !divider.isHomeStackResizable()) {
-                    // Undocking from the minimized state is not supported
-                    return false;
-                } else {
-                    divider.onUndockingTask();
-                    if (metricsUndockAction != -1) {
-                        mMetricsLogger.action(metricsUndockAction);
-                    }
+            if (divider.isMinimized() && !divider.isHomeStackResizable()) {
+                // Undocking from the minimized state is not supported
+                return false;
+            } else {
+                divider.onUndockingTask();
+                if (metricsUndockAction != -1) {
+                    mMetricsLogger.action(metricsUndockAction);
                 }
             }
         }
@@ -2468,6 +2469,12 @@
             pw.println("  mHeadsUpManager: null");
         }
 
+        if (mStatusBarTouchableRegionManager != null) {
+            mStatusBarTouchableRegionManager.dump(fd, pw, args);
+        } else {
+            pw.println("  mStatusBarTouchableRegionManager: null");
+        }
+
         if (mLightBarController != null) {
             mLightBarController.dump(fd, pw, args);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index 2485513..693cdd2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -209,7 +209,7 @@
             };
 
             mViewHierarchyManager.setUpWithPresenter(this, notifListContainer);
-            mEntryManager.setUpWithPresenter(this, notifListContainer, mHeadsUpManager);
+            mEntryManager.setUpWithPresenter(this);
             mEntryManager.addNotificationEntryListener(notificationEntryListener);
             mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
             mEntryManager.addNotificationLifetimeExtender(mGutsManager);
@@ -230,8 +230,6 @@
             onUserSwitched(mLockscreenUserManager.getCurrentUserId());
         });
         Dependency.get(ConfigurationController.class).addCallback(this);
-
-        notificationAlertingManager.setHeadsUpManager(mHeadsUpManager);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index b8fb6d3..5bab867 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -17,66 +17,187 @@
 package com.android.systemui.statusbar.phone;
 
 import android.annotation.NonNull;
+import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Rect;
+import android.graphics.Region;
+import android.util.Log;
+import android.view.DisplayCutout;
+import android.view.Gravity;
 import android.view.View;
 import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
+import android.view.WindowInsets;
 
-import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
 import com.android.systemui.R;
+import com.android.systemui.ScreenDecorations;
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
 
 /**
- * Manages what parts of the status bar are touchable. Clients are primarily UI that displays in the
- * status bar even though the UI doesn't look like part of the status bar.
+ * Manages what parts of the status bar are touchable. Clients are primarily UI that display in the
+ * status bar even though the UI doesn't look like part of the status bar. Currently this
+ * includes HeadsUpNotifications and Bubbles.
  */
-public final class StatusBarTouchableRegionManager implements
-        OnComputeInternalInsetsListener, ConfigurationListener {
+@Singleton
+public final class StatusBarTouchableRegionManager implements Dumpable {
+    private static final String TAG = "TouchableRegionManager";
 
-    private final BubbleController mBubbleController = Dependency.get(BubbleController.class);
+    private final Context mContext;
     private final HeadsUpManagerPhone mHeadsUpManager;
+    private final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final BubbleController mBubbleController;
+
     private boolean mIsStatusBarExpanded = false;
     private boolean mShouldAdjustInsets = false;
-    private final StatusBar mStatusBar;
-    private final View mNotificationShadeWindowView;
+    private StatusBar mStatusBar;
+    private View mNotificationShadeWindowView;
     private View mNotificationPanelView;
     private boolean mForceCollapsedUntilLayout = false;
-    private final NotificationShadeWindowController mNotificationShadeWindowController;
 
-    public StatusBarTouchableRegionManager(HeadsUpManagerPhone headsUpManager,
-                                           @NonNull StatusBar statusBar,
-                                           @NonNull View notificationShadeWindowView) {
-        mHeadsUpManager = headsUpManager;
-        mStatusBar = statusBar;
-        mNotificationShadeWindowView = notificationShadeWindowView;
-        mNotificationShadeWindowController =
-                Dependency.get(NotificationShadeWindowController.class);
+    private Region mTouchableRegion = new Region();
+    private int mDisplayCutoutTouchableRegionSize;
+    private int mStatusBarHeight;
 
-        mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
-            updateTouchableRegion();
+    @Inject
+    public StatusBarTouchableRegionManager(
+            Context context,
+            NotificationShadeWindowController notificationShadeWindowController,
+            ConfigurationController configurationController,
+            HeadsUpManagerPhone headsUpManager,
+            BubbleController bubbleController
+    ) {
+        mContext = context;
+        initResources();
+        configurationController.addCallback(new ConfigurationListener() {
+            @Override
+            public void onDensityOrFontScaleChanged() {
+                initResources();
+            }
+
+            @Override
+            public void onOverlayChanged() {
+                initResources();
+            }
         });
 
+        mHeadsUpManager = headsUpManager;
+        mHeadsUpManager.addListener(
+                new OnHeadsUpChangedListener() {
+                    @Override
+                    public void onHeadsUpPinnedModeChanged(boolean hasPinnedNotification) {
+                        if (Log.isLoggable(TAG, Log.WARN)) {
+                            Log.w(TAG, "onHeadsUpPinnedModeChanged");
+                        }
+                        updateTouchableRegion();
+                    }
+                });
+        mHeadsUpManager.addHeadsUpPhoneListener(
+                new HeadsUpManagerPhone.OnHeadsUpPhoneListenerChange() {
+                    @Override
+                    public void onHeadsUpGoingAwayStateChanged(boolean headsUpGoingAway) {
+                        if (!headsUpGoingAway) {
+                            updateTouchableRegionAfterLayout();
+                        } else {
+                            updateTouchableRegion();
+                        }
+                    }
+                });
+
+        mNotificationShadeWindowController = notificationShadeWindowController;
         mNotificationShadeWindowController.setForcePluginOpenListener((forceOpen) -> {
             updateTouchableRegion();
         });
-        Dependency.get(ConfigurationController.class).addCallback(this);
-        if (mNotificationShadeWindowView != null) {
-            mNotificationPanelView = mNotificationShadeWindowView.findViewById(
-                    R.id.notification_panel);
+
+        mBubbleController = bubbleController;
+        mBubbleController.setBubbleStateChangeListener((hasBubbles) -> {
+            updateTouchableRegion();
+        });
+    }
+
+    protected void setup(
+            @NonNull StatusBar statusBar,
+            @NonNull View notificationShadeWindowView) {
+        mStatusBar = statusBar;
+        mNotificationShadeWindowView = notificationShadeWindowView;
+        mNotificationPanelView = mNotificationShadeWindowView.findViewById(R.id.notification_panel);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("StatusBarTouchableRegionManager state:");
+        pw.print("  mTouchableRegion=");
+        pw.println(mTouchableRegion);
+    }
+
+    /**
+     * Notify that the status bar panel gets expanded or collapsed.
+     *
+     * @param isExpanded True to notify expanded, false to notify collapsed.
+     */
+    void setPanelExpanded(boolean isExpanded) {
+        if (isExpanded != mIsStatusBarExpanded) {
+            mIsStatusBarExpanded = isExpanded;
+            if (isExpanded) {
+                // make sure our state is sane
+                mForceCollapsedUntilLayout = false;
+            }
+            updateTouchableRegion();
         }
     }
 
     /**
+     * Calculates the touch region needed for heads up notifications, taking into consideration
+     * any existing display cutouts (notch)
+     * @return the heads up notification touch area
+     */
+    Region calculateTouchableRegion() {
+        // Update touchable region for HeadsUp notifications
+        final Region headsUpTouchableRegion = mHeadsUpManager.getTouchableRegion();
+        if (headsUpTouchableRegion != null) {
+            mTouchableRegion.set(headsUpTouchableRegion);
+        } else {
+            // If there aren't any HUNs, update the touch region to the status bar
+            // width/height, potentially adjusting for a display cutout (notch)
+            mTouchableRegion.set(0, 0, mNotificationShadeWindowView.getWidth(),
+                    mStatusBarHeight);
+            updateRegionForNotch(mTouchableRegion);
+        }
+
+        // Update touchable region for bubbles
+        Rect bubbleRect = mBubbleController.getTouchableRegion();
+        if (bubbleRect != null) {
+            mTouchableRegion.union(bubbleRect);
+        }
+        return mTouchableRegion;
+    }
+
+    private void initResources() {
+        Resources resources = mContext.getResources();
+        mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
+                com.android.internal.R.dimen.display_cutout_touchable_region_size);
+        mStatusBarHeight =
+                resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+    }
+
+    /**
      * Set the touchable portion of the status bar based on what elements are visible.
      */
-    public void updateTouchableRegion() {
+    private void updateTouchableRegion() {
         boolean hasCutoutInset = (mNotificationShadeWindowView != null)
                 && (mNotificationShadeWindowView.getRootWindowInsets() != null)
                 && (mNotificationShadeWindowView.getRootWindowInsets().getDisplayCutout() != null);
-        boolean shouldObserve =
-                mHeadsUpManager.hasPinnedHeadsUp() || mHeadsUpManager.isHeadsUpGoingAway()
+        boolean shouldObserve = mHeadsUpManager.hasPinnedHeadsUp()
+                        || mHeadsUpManager.isHeadsUpGoingAway()
                         || mBubbleController.hasBubbles()
                         || mForceCollapsedUntilLayout
                         || hasCutoutInset
@@ -87,11 +208,11 @@
 
         if (shouldObserve) {
             mNotificationShadeWindowView.getViewTreeObserver()
-                    .addOnComputeInternalInsetsListener(this);
+                    .addOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
             mNotificationShadeWindowView.requestLayout();
         } else {
             mNotificationShadeWindowView.getViewTreeObserver()
-                    .removeOnComputeInternalInsetsListener(this);
+                    .removeOnComputeInternalInsetsListener(mOnComputeInternalInsetsListener);
         }
         mShouldAdjustInsets = shouldObserve;
     }
@@ -99,7 +220,7 @@
     /**
      * Calls {@code updateTouchableRegion()} after a layout pass completes.
      */
-    public void updateTouchableRegionAfterLayout() {
+    private void updateTouchableRegionAfterLayout() {
         if (mNotificationPanelView != null) {
             mForceCollapsedUntilLayout = true;
             mNotificationPanelView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
@@ -116,34 +237,38 @@
         }
     }
 
-    /**
-     * Notify that the status bar panel gets expanded or collapsed.
-     *
-     * @param isExpanded True to notify expanded, false to notify collapsed.
-     */
-    public void setIsStatusBarExpanded(boolean isExpanded) {
-        if (isExpanded != mIsStatusBarExpanded) {
-            mIsStatusBarExpanded = isExpanded;
-            if (isExpanded) {
-                // make sure our state is sane
-                mForceCollapsedUntilLayout = false;
-            }
-            updateTouchableRegion();
+    private void updateRegionForNotch(Region touchableRegion) {
+        WindowInsets windowInsets = mNotificationShadeWindowView.getRootWindowInsets();
+        if (windowInsets == null) {
+            Log.w(TAG, "StatusBarWindowView is not attached.");
+            return;
         }
-    }
-
-    @Override
-    public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-        if (mIsStatusBarExpanded || mStatusBar.isBouncerShowing()) {
-            // The touchable region is always the full area when expanded
+        DisplayCutout cutout = windowInsets.getDisplayCutout();
+        if (cutout == null) {
             return;
         }
 
-        mHeadsUpManager.updateTouchableRegion(info);
-
-        Rect bubbleRect = mBubbleController.getTouchableRegion();
-        if (bubbleRect != null) {
-            info.touchableRegion.union(bubbleRect);
-        }
+        // Expand touchable region such that we also catch touches that just start below the notch
+        // area.
+        Rect bounds = new Rect();
+        ScreenDecorations.DisplayCutoutView.boundsFromDirection(cutout, Gravity.TOP, bounds);
+        bounds.offset(0, mDisplayCutoutTouchableRegionSize);
+        touchableRegion.union(bounds);
     }
+
+    private final OnComputeInternalInsetsListener mOnComputeInternalInsetsListener =
+            new OnComputeInternalInsetsListener() {
+        @Override
+        public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
+            if (mIsStatusBarExpanded || mStatusBar.isBouncerShowing()) {
+                // The touchable region is always the full area when expanded
+                return;
+            }
+
+            // Update touch insets to include any area needed for touching features that live in
+            // the status bar (ie: heads up notifications or bubbles)
+            info.setTouchableInsets(ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_REGION);
+            info.touchableRegion.set(calculateTouchableRegion());
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 26459a9..e64f821 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -85,6 +85,7 @@
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.StatusBarNotificationActivityStarter;
+import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
@@ -192,7 +193,8 @@
             KeyguardDismissUtil keyguardDismissUtil,
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
-            DismissCallbackRegistry dismissCallbackRegistry) {
+            DismissCallbackRegistry dismissCallbackRegistry,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager) {
         return new StatusBar(
                 context,
                 notificationsController,
@@ -267,6 +269,7 @@
                 keyguardDismissUtil,
                 extensionController,
                 userInfoControllerImpl,
-                dismissCallbackRegistry);
+                dismissCallbackRegistry,
+                statusBarTouchableRegionManager);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
index 0ab08a8..a7f60d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardStateControllerImpl.java
@@ -293,13 +293,12 @@
         }
 
         @Override
-        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType) {
+        public void onBiometricAuthenticated(int userId, BiometricSourceType biometricSourceType,
+                boolean isStrongBiometric) {
             Trace.beginSection("KeyguardUpdateMonitorCallback#onBiometricAuthenticated");
-            if (!mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()) {
-                Trace.endSection();
-                return;
+            if (mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(isStrongBiometric)) {
+                update(false /* updateAlways */);
             }
-            update(false /* updateAlways */);
             Trace.endSection();
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index f6e1681..cebcf76 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -15,24 +15,18 @@
  */
 package com.android.systemui.statusbar.policy;
 
-import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
-import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
-
 import android.content.Context;
 import android.content.Intent;
 import android.database.ContentObserver;
 import android.net.NetworkCapabilities;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.Message;
 import android.provider.Settings.Global;
-import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation;
 import android.telephony.CdmaEriInformation;
 import android.telephony.CellSignalStrength;
 import android.telephony.CellSignalStrengthCdma;
-import android.telephony.DataSpecificRegistrationInfo;
-import android.telephony.NetworkRegistrationInfo;
+import android.telephony.DisplayInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -60,16 +54,10 @@
 import java.util.Map;
 import java.util.Objects;
 import java.util.concurrent.Executor;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
 
 public class MobileSignalController extends SignalController<
         MobileSignalController.MobileState, MobileSignalController.MobileIconGroup> {
-
-    // The message to display Nr5G icon gracfully by CarrierConfig timeout
-    private static final int MSG_DISPLAY_GRACE = 1;
-
     private final TelephonyManager mPhone;
     private final SubscriptionDefaults mDefaults;
     private final String mNetworkNameDefault;
@@ -86,19 +74,15 @@
     // Since some pieces of the phone state are interdependent we store it locally,
     // this could potentially become part of MobileState for simplification/complication
     // of code.
-    private int mDataNetType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
-    private boolean mCA = false;
-    private boolean mCAPlus = false;
     private int mDataState = TelephonyManager.DATA_DISCONNECTED;
+    private DisplayInfo mDisplayInfo = new DisplayInfo(TelephonyManager.NETWORK_TYPE_UNKNOWN,
+            DisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
     private ServiceState mServiceState;
     private SignalStrength mSignalStrength;
     private MobileIconGroup mDefaultIcons;
     private Config mConfig;
-    private final Handler mDisplayGraceHandler;
     @VisibleForTesting
     boolean mInflateSignalStrengths = false;
-    @VisibleForTesting
-    boolean mIsShowingIconGracefully = false;
 
     // TODO: Reduce number of vars passed in, if we have the NetworkController, probably don't
     // need listener lists anymore.
@@ -136,16 +120,6 @@
                 updateTelephony();
             }
         };
-
-        mDisplayGraceHandler = new Handler(receiverLooper) {
-            @Override
-            public void handleMessage(Message msg) {
-                if (msg.what == MSG_DISPLAY_GRACE) {
-                    mIsShowingIconGracefully = false;
-                    updateTelephony();
-                }
-            }
-        };
     }
 
     public void setConfiguration(Config config) {
@@ -190,7 +164,8 @@
                         | PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
                         | PhoneStateListener.LISTEN_DATA_ACTIVITY
                         | PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE
-                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+                        | PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE
+                        | PhoneStateListener.LISTEN_DISPLAY_INFO_CHANGED);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(Global.MOBILE_DATA),
                 true, mObserver);
         mContext.getContentResolver().registerContentObserver(Global.getUriFor(
@@ -268,52 +243,60 @@
             mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_LTE),
                     TelephonyIcons.FOUR_G);
             if (mConfig.hideLtePlus) {
-                mNetworkToIconLookup.put(toIconKeyCA(TelephonyManager.NETWORK_TYPE_LTE),
-                        TelephonyIcons.FOUR_G);
+                mNetworkToIconLookup.put(toDisplayIconKey(
+                        DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), TelephonyIcons.FOUR_G);
             } else {
-                mNetworkToIconLookup.put(toIconKeyCA(TelephonyManager.NETWORK_TYPE_LTE),
-                        TelephonyIcons.FOUR_G_PLUS);
+                mNetworkToIconLookup.put(toDisplayIconKey(
+                        DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), TelephonyIcons.FOUR_G_PLUS);
             }
         } else {
             mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_LTE),
                     TelephonyIcons.LTE);
             if (mConfig.hideLtePlus) {
-                mNetworkToIconLookup.put(toIconKeyCA(TelephonyManager.NETWORK_TYPE_LTE),
-                        TelephonyIcons.LTE);
+                mNetworkToIconLookup.put(toDisplayIconKey(
+                        DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), TelephonyIcons.LTE);
             } else {
-                mNetworkToIconLookup.put(toIconKeyCA(TelephonyManager.NETWORK_TYPE_LTE),
-                        TelephonyIcons.LTE_PLUS);
+                mNetworkToIconLookup.put(toDisplayIconKey(
+                        DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA), TelephonyIcons.LTE_PLUS);
             }
         }
-        mNetworkToIconLookup.put(toIconKeyCAPlus(TelephonyManager.NETWORK_TYPE_LTE),
-                TelephonyIcons.LTE_CA_5G_E);
         mNetworkToIconLookup.put(toIconKey(TelephonyManager.NETWORK_TYPE_IWLAN),
                 TelephonyIcons.WFC);
+        mNetworkToIconLookup.put(toDisplayIconKey(
+                DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO), TelephonyIcons.LTE_CA_5G_E);
+        mNetworkToIconLookup.put(toDisplayIconKey(
+                DisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA), TelephonyIcons.NR_5G);
+        mNetworkToIconLookup.put(toDisplayIconKey(
+                DisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE), TelephonyIcons.NR_5G_PLUS);
     }
 
     private String getIconKey() {
-        if (mCA) {
-            return toIconKeyCA(mDataNetType);
-        } else if (mCAPlus) {
-            return toIconKeyCAPlus(mDataNetType);
+        if (mDisplayInfo.getOverrideNetworkType() == DisplayInfo.OVERRIDE_NETWORK_TYPE_NONE) {
+            return toIconKey(mDisplayInfo.getNetworkType());
         } else {
-            return toIconKey(mDataNetType);
+            return toDisplayIconKey(mDisplayInfo.getOverrideNetworkType());
         }
     }
 
-    // Some specific carriers have 5GE network which is special CA network.
-    private String toIconKeyCAPlus(@Annotation.NetworkType int networkType) {
-        return toIconKeyCA(networkType) + "_Plus";
-    }
-
-    private String toIconKeyCA(@Annotation.NetworkType int networkType) {
-        return toIconKey(networkType) + "_CA";
-    }
-
     private String toIconKey(@Annotation.NetworkType int networkType) {
         return Integer.toString(networkType);
     }
 
+    private String toDisplayIconKey(@Annotation.OverrideNetworkType int displayNetworkType) {
+        switch (displayNetworkType) {
+            case DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_CA:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA";
+            case DisplayInfo.OVERRIDE_NETWORK_TYPE_LTE_ADVANCED_PRO:
+                return toIconKey(TelephonyManager.NETWORK_TYPE_LTE) + "_CA_Plus";
+            case DisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA:
+                return "5G";
+            case DisplayInfo.OVERRIDE_NETWORK_TYPE_NR_NSA_MMWAVE:
+                return "5G_Plus";
+            default:
+                return "unsupported";
+        }
+    }
+
     private void updateInflateSignalStrength() {
         mInflateSignalStrengths = SignalStrengthUtil.shouldInflateSignalStrength(mContext,
                 mSubscriptionInfo.getSubscriptionId());
@@ -465,26 +448,6 @@
         }
     }
 
-    private boolean isCarrierSpecificDataIcon() {
-        if (mConfig.patternOfCarrierSpecificDataIcon == null
-                || mConfig.patternOfCarrierSpecificDataIcon.length() == 0) {
-            return false;
-        }
-
-        Pattern stringPattern = Pattern.compile(mConfig.patternOfCarrierSpecificDataIcon);
-        String[] operatorNames = new String[]{mServiceState.getOperatorAlphaLongRaw(),
-                mServiceState.getOperatorAlphaShortRaw()};
-        for (String opName : operatorNames) {
-            if (!TextUtils.isEmpty(opName)) {
-                Matcher matcher = stringPattern.matcher(opName);
-                if (matcher.find()) {
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
     /**
      * Updates the network's name based on incoming spn and plmn.
      */
@@ -538,18 +501,18 @@
     }
 
     /**
-     * Updates the current state based on mServiceState, mSignalStrength, mDataNetType,
-     * mDataState, and mSimState.  It should be called any time one of these is updated.
+     * Updates the current state based on mServiceState, mSignalStrength, mDataState,
+     * mDisplayInfo, and mSimState.  It should be called any time one of these is updated.
      * This will call listeners if necessary.
      */
     private final void updateTelephony() {
         if (DEBUG) {
             Log.d(mTag, "updateTelephonySignalStrength: hasService=" +
-                    Utils.isInService(mServiceState) + " ss=" + mSignalStrength);
+                    Utils.isInService(mServiceState) + " ss=" + mSignalStrength
+                    + " displayInfo=" + mDisplayInfo);
         }
         checkDefaultData();
-        mCurrentState.connected = Utils.isInService(mServiceState)
-                && mSignalStrength != null;
+        mCurrentState.connected = Utils.isInService(mServiceState) && mSignalStrength != null;
         if (mCurrentState.connected) {
             if (!mSignalStrength.isGsm() && mConfig.alwaysShowCdmaRssi) {
                 mCurrentState.level = getCdmaLevel();
@@ -558,17 +521,8 @@
             }
         }
 
-        // When the device is camped on a 5G Non-Standalone network, the data network type is still
-        // LTE. In this case, we first check which 5G icon should be shown.
-        MobileIconGroup nr5GIconGroup = getNr5GIconGroup();
-        if (mConfig.nrIconDisplayGracePeriodMs > 0) {
-            nr5GIconGroup = adjustNr5GIconGroupByDisplayGraceTime(nr5GIconGroup);
-        }
-
         String iconKey = getIconKey();
-        if (nr5GIconGroup != null) {
-            mCurrentState.iconGroup = nr5GIconGroup;
-        } else if (mNetworkToIconLookup.get(iconKey) != null) {
+        if (mNetworkToIconLookup.get(iconKey) != null) {
             mCurrentState.iconGroup = mNetworkToIconLookup.get(iconKey);
         } else {
             mCurrentState.iconGroup = mDefaultIcons;
@@ -580,8 +534,7 @@
         if (isCarrierNetworkChangeActive()) {
             mCurrentState.iconGroup = TelephonyIcons.CARRIER_NETWORK_CHANGE;
         } else if (isDataDisabled() && !mConfig.alwaysShowDataRatIcon) {
-            if (mSubscriptionInfo.getSubscriptionId()
-                    != mDefaults.getDefaultDataSubId()) {
+            if (mSubscriptionInfo.getSubscriptionId() != mDefaults.getDefaultDataSubId()) {
                 mCurrentState.iconGroup = TelephonyIcons.NOT_DEFAULT_DATA;
             } else {
                 mCurrentState.iconGroup = TelephonyIcons.DATA_DISABLED;
@@ -623,91 +576,6 @@
         notifyListenersIfNecessary();
     }
 
-    private int getNrState(ServiceState serviceState) {
-        NetworkRegistrationInfo nri = serviceState.getNetworkRegistrationInfo(
-                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-        if (nri != null) {
-            return nri.getNrState();
-        }
-        return NetworkRegistrationInfo.NR_STATE_NONE;
-    }
-
-    private MobileIconGroup getNr5GIconGroup() {
-        if (mServiceState == null) return null;
-
-        int nrState = getNrState(mServiceState);
-        if (nrState == NetworkRegistrationInfo.NR_STATE_CONNECTED) {
-            // Check if the NR 5G is using millimeter wave and the icon is config.
-            if (mServiceState.getNrFrequencyRange() == ServiceState.FREQUENCY_RANGE_MMWAVE) {
-                if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED_MMWAVE)) {
-                    return mConfig.nr5GIconMap.get(Config.NR_CONNECTED_MMWAVE);
-                }
-            }
-
-            // If NR 5G is not using millimeter wave or there is no icon for millimeter wave, we
-            // check the normal 5G icon.
-            if (mConfig.nr5GIconMap.containsKey(Config.NR_CONNECTED)) {
-                return mConfig.nr5GIconMap.get(Config.NR_CONNECTED);
-            }
-        } else if (nrState == NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED) {
-            if (mCurrentState.activityDormant) {
-                if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED_RRC_IDLE)) {
-                    return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED_RRC_IDLE);
-                }
-            } else {
-                if (mConfig.nr5GIconMap.containsKey(Config.NR_NOT_RESTRICTED_RRC_CON)) {
-                    return mConfig.nr5GIconMap.get(Config.NR_NOT_RESTRICTED_RRC_CON);
-                }
-            }
-        } else if (nrState == NetworkRegistrationInfo.NR_STATE_RESTRICTED) {
-            if (mConfig.nr5GIconMap.containsKey(Config.NR_RESTRICTED)) {
-                return mConfig.nr5GIconMap.get(Config.NR_RESTRICTED);
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * The function to adjust MobileIconGroup depend on CarrierConfig's time
-     * nextIconGroup == null imply next state could be 2G/3G/4G/4G+
-     * nextIconGroup != null imply next state will be 5G/5G+
-     * Flag : mIsShowingIconGracefully
-     * ---------------------------------------------------------------------------------
-     * |   Last state   |  Current state  | Flag |       Action                        |
-     * ---------------------------------------------------------------------------------
-     * |     5G/5G+     | 2G/3G/4G/4G+    | true | return previous IconGroup           |
-     * |     5G/5G+     |     5G/5G+      | true | Bypass                              |
-     * |  2G/3G/4G/4G+  |     5G/5G+      | true | Bypass                              |
-     * |  2G/3G/4G/4G+  | 2G/3G/4G/4G+    | true | Bypass                              |
-     * |  SS.connected  | SS.disconnect   |  T|F | Reset timer                         |
-     * |NETWORK_TYPE_LTE|!NETWORK_TYPE_LTE|  T|F | Reset timer                         |
-     * |     5G/5G+     | 2G/3G/4G/4G+    | false| Bypass                              |
-     * |     5G/5G+     |     5G/5G+      | false| Bypass                              |
-     * |  2G/3G/4G/4G+  |     5G/5G+      | false| SendMessageDelay(time), flag->true  |
-     * |  2G/3G/4G/4G+  | 2G/3G/4G/4G+    | false| Bypass                              |
-     * ---------------------------------------------------------------------------------
-     */
-    private MobileIconGroup adjustNr5GIconGroupByDisplayGraceTime(
-            MobileIconGroup candidateIconGroup) {
-        if (mIsShowingIconGracefully && candidateIconGroup == null) {
-            candidateIconGroup = (MobileIconGroup) mCurrentState.iconGroup;
-        } else if (!mIsShowingIconGracefully && candidateIconGroup != null
-                && mLastState.iconGroup != candidateIconGroup) {
-            mDisplayGraceHandler.sendMessageDelayed(
-                    mDisplayGraceHandler.obtainMessage(MSG_DISPLAY_GRACE),
-                    mConfig.nrIconDisplayGracePeriodMs);
-            mIsShowingIconGracefully = true;
-        } else if (!mCurrentState.connected || mDataState == TelephonyManager.DATA_DISCONNECTED
-                || candidateIconGroup == null) {
-            mDisplayGraceHandler.removeMessages(MSG_DISPLAY_GRACE);
-            mIsShowingIconGracefully = false;
-            candidateIconGroup = null;
-        }
-
-        return candidateIconGroup;
-    }
-
     boolean isDataDisabled() {
         return !mPhone.isDataConnectionEnabled();
     }
@@ -718,8 +586,6 @@
                 || activity == TelephonyManager.DATA_ACTIVITY_IN;
         mCurrentState.activityOut = activity == TelephonyManager.DATA_ACTIVITY_INOUT
                 || activity == TelephonyManager.DATA_ACTIVITY_OUT;
-        mCurrentState.activityDormant = activity == TelephonyManager.DATA_ACTIVITY_DORMANT;
-
         notifyListenersIfNecessary();
     }
 
@@ -729,13 +595,10 @@
         pw.println("  mSubscription=" + mSubscriptionInfo + ",");
         pw.println("  mServiceState=" + mServiceState + ",");
         pw.println("  mSignalStrength=" + mSignalStrength + ",");
+        pw.println("  mDisplayInfo=" + mDisplayInfo + ",");
         pw.println("  mDataState=" + mDataState + ",");
-        pw.println("  mDataNetType=" + mDataNetType + ",");
-        pw.println("  mCA=" + mCA + ",");
-        pw.println("  mCAPlus=" + mCAPlus + ",");
         pw.println("  mInflateSignalStrengths=" + mInflateSignalStrengths + ",");
         pw.println("  isDataDisabled=" + isDataDisabled() + ",");
-        pw.println("  mIsShowingIconGracefully=" + mIsShowingIconGracefully + ",");
     }
 
     class MobilePhoneStateListener extends PhoneStateListener {
@@ -760,14 +623,8 @@
                         + " dataState=" + state.getDataRegistrationState());
             }
             mServiceState = state;
-            if (mServiceState != null) {
-                NetworkRegistrationInfo regInfo = mServiceState.getNetworkRegistrationInfo(
-                        DOMAIN_PS, TRANSPORT_TYPE_WWAN);
-                if (regInfo != null) {
-                    updateDataNetType(regInfo.getAccessNetworkTechnology());
-                }
-            }
-            updateTelephony();
+            // onDisplayInfoChanged is invoked directly after onServiceStateChanged, so not calling
+            // updateTelephony() to prevent icon flickering in case of overrides.
         }
 
         @Override
@@ -777,35 +634,12 @@
                         + " type=" + networkType);
             }
             mDataState = state;
-            updateDataNetType(networkType);
+            if (networkType != mDisplayInfo.getNetworkType()) {
+                mDisplayInfo = new DisplayInfo(networkType, DisplayInfo.OVERRIDE_NETWORK_TYPE_NONE);
+            }
             updateTelephony();
         }
 
-        private void updateDataNetType(int networkType) {
-            mDataNetType = networkType;
-            mCA = false;
-            mCAPlus = false;
-            if (mDataNetType == TelephonyManager.NETWORK_TYPE_LTE) {
-                if (isCarrierSpecificDataIcon()) {
-                    mCAPlus = true;
-                } else if (mServiceState != null && isUsingCarrierAggregation(mServiceState)) {
-                    mCA = true;
-                }
-            }
-        }
-
-        private boolean isUsingCarrierAggregation(ServiceState serviceState) {
-            NetworkRegistrationInfo nri = serviceState.getNetworkRegistrationInfo(
-                    NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
-            if (nri != null) {
-                DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
-                if (dsri != null) {
-                    return dsri.isUsingCarrierAggregation();
-                }
-            }
-            return false;
-        }
-
         @Override
         public void onDataActivity(int direction) {
             if (DEBUG) {
@@ -820,7 +654,6 @@
                 Log.d(mTag, "onCarrierNetworkChange: active=" + active);
             }
             mCurrentState.carrierNetworkChangeMode = active;
-
             updateTelephony();
         }
 
@@ -830,7 +663,16 @@
             updateDataSim();
             updateTelephony();
         }
-    };
+
+        @Override
+        public void onDisplayInfoChanged(DisplayInfo displayInfo) {
+            if (DEBUG) {
+                Log.d(mTag, "onDisplayInfoChanged: displayInfo=" + displayInfo);
+            }
+            mDisplayInfo = displayInfo;
+            updateTelephony();
+        }
+    }
 
     static class MobileIconGroup extends SignalController.IconGroup {
         final int mDataContentDescription; // mContentDescriptionDataType
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index 4f382e7..9003de1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -49,7 +49,6 @@
 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.Log;
 import android.util.MathUtils;
 import android.util.SparseArray;
@@ -64,7 +63,6 @@
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGroup;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -72,10 +70,8 @@
 import java.util.BitSet;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Map;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -846,12 +842,6 @@
         pw.println(emergencyToString(mEmergencySource));
 
         pw.println("  - config ------");
-        pw.print("  patternOfCarrierSpecificDataIcon=");
-        pw.println(mConfig.patternOfCarrierSpecificDataIcon);
-        pw.print("  nr5GIconMap=");
-        pw.println(mConfig.nr5GIconMap.toString());
-        pw.print("  nrIconDisplayGracePeriodMs=");
-        pw.println(mConfig.nrIconDisplayGracePeriodMs);
         for (int i = 0; i < mMobileSignalControllers.size(); i++) {
             MobileSignalController mobileSignalController = mMobileSignalControllers.valueAt(i);
             mobileSignalController.dump(pw);
@@ -1132,14 +1122,6 @@
 
     @VisibleForTesting
     static class Config {
-        static final int NR_CONNECTED_MMWAVE = 1;
-        static final int NR_CONNECTED = 2;
-        static final int NR_NOT_RESTRICTED_RRC_IDLE = 3;
-        static final int NR_NOT_RESTRICTED_RRC_CON = 4;
-        static final int NR_RESTRICTED = 5;
-
-        Map<Integer, MobileIconGroup> nr5GIconMap = new HashMap<>();
-
         boolean showAtLeast3G = false;
         boolean show4gFor3g = false;
         boolean alwaysShowCdmaRssi = false;
@@ -1148,22 +1130,6 @@
         boolean hspaDataDistinguishable;
         boolean inflateSignalStrengths = false;
         boolean alwaysShowDataRatIcon = false;
-        public String patternOfCarrierSpecificDataIcon = "";
-        public long nrIconDisplayGracePeriodMs;
-
-        /**
-         * Mapping from NR 5G status string to an integer. The NR 5G status string should match
-         * those in carrier config.
-         */
-        private static final Map<String, Integer> NR_STATUS_STRING_TO_INDEX;
-        static {
-            NR_STATUS_STRING_TO_INDEX = new HashMap<>(5);
-            NR_STATUS_STRING_TO_INDEX.put("connected_mmwave", NR_CONNECTED_MMWAVE);
-            NR_STATUS_STRING_TO_INDEX.put("connected", NR_CONNECTED);
-            NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_idle", NR_NOT_RESTRICTED_RRC_IDLE);
-            NR_STATUS_STRING_TO_INDEX.put("not_restricted_rrc_con", NR_NOT_RESTRICTED_RRC_CON);
-            NR_STATUS_STRING_TO_INDEX.put("restricted", NR_RESTRICTED);
-        }
 
         static Config readConfig(Context context) {
             Config config = new Config();
@@ -1192,64 +1158,9 @@
                         CarrierConfigManager.KEY_SHOW_4G_FOR_3G_DATA_ICON_BOOL);
                 config.hideLtePlus = b.getBoolean(
                         CarrierConfigManager.KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL);
-                config.patternOfCarrierSpecificDataIcon = b.getString(
-                        CarrierConfigManager.KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING);
-                String nr5GIconConfiguration =
-                        b.getString(CarrierConfigManager.KEY_5G_ICON_CONFIGURATION_STRING);
-                if (!TextUtils.isEmpty(nr5GIconConfiguration)) {
-                    String[] nr5GIconConfigPairs = nr5GIconConfiguration.trim().split(",");
-                    for (String pair : nr5GIconConfigPairs) {
-                        add5GIconMapping(pair, config);
-                    }
-                }
-                setDisplayGraceTime(
-                        b.getInt(CarrierConfigManager.KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT),
-                        config);
             }
 
             return config;
         }
-
-        /**
-         * Add a mapping from NR 5G status to the 5G icon. All the icon resources come from
-         * {@link TelephonyIcons}.
-         *
-         * @param keyValuePair the NR 5G status and icon name separated by a colon.
-         * @param config container that used to store the parsed configs.
-         */
-        @VisibleForTesting
-        static void add5GIconMapping(String keyValuePair, Config config) {
-            String[] kv = (keyValuePair.trim().toLowerCase()).split(":");
-
-            if (kv.length != 2) {
-                if (DEBUG) Log.e(TAG, "Invalid 5G icon configuration, config = " + keyValuePair);
-                return;
-            }
-
-            String key = kv[0], value = kv[1];
-
-            // There is no icon config for the specific 5G status.
-            if (value.equals("none")) return;
-
-            if (NR_STATUS_STRING_TO_INDEX.containsKey(key)
-                    && TelephonyIcons.ICON_NAME_TO_ICON.containsKey(value)) {
-                config.nr5GIconMap.put(
-                        NR_STATUS_STRING_TO_INDEX.get(key),
-                        TelephonyIcons.ICON_NAME_TO_ICON.get(value));
-            }
-        }
-
-        /**
-         * Set display gracefully period time(MS) depend on carrierConfig KEY
-         * KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, and this function will convert to ms.
-         * {@link CarrierConfigManager}.
-         *
-         * @param time   showing 5G icon gracefully in the period of the time(SECOND)
-         * @param config container that used to store the parsed configs.
-         */
-        @VisibleForTesting
-        static void setDisplayGraceTime(int time, Config config) {
-            config.nrIconDisplayGracePeriodMs = time * DateUtils.SECOND_IN_MILLIS;
-        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
index 749b56c..3a45691 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SignalController.java
@@ -261,7 +261,6 @@
         boolean enabled;
         boolean activityIn;
         boolean activityOut;
-        public boolean activityDormant;
         int level;
         IconGroup iconGroup;
         int inetCondition;
@@ -278,7 +277,6 @@
             inetCondition = state.inetCondition;
             activityIn = state.activityIn;
             activityOut = state.activityOut;
-            activityDormant = state.activityDormant;
             rssi = state.rssi;
             time = state.time;
         }
@@ -302,7 +300,6 @@
                     .append("iconGroup=").append(iconGroup).append(',')
                     .append("activityIn=").append(activityIn).append(',')
                     .append("activityOut=").append(activityOut).append(',')
-                    .append("activityDormant=").append(activityDormant).append(',')
                     .append("rssi=").append(rssi).append(',')
                     .append("lastModified=").append(sSDF.format(time));
         }
@@ -320,7 +317,6 @@
                     && other.iconGroup == iconGroup
                     && other.activityIn == activityIn
                     && other.activityOut == activityOut
-                    && other.activityDormant == activityDormant
                     && other.rssi == rssi;
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 39de0f3..241d978 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -17,8 +17,12 @@
 package com.android.systemui.statusbar.tv;
 
 import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.systemui.SystemUI;
@@ -40,6 +44,9 @@
 @Singleton
 public class TvStatusBar extends SystemUI implements CommandQueue.Callbacks {
 
+    private static final String ACTION_OPEN_TV_NOTIFICATIONS_PANEL =
+            "com.android.tv.action.OPEN_NOTIFICATIONS_PANEL";
+
     private final CommandQueue mCommandQueue;
 
     @Inject
@@ -61,4 +68,23 @@
 
         new AudioRecordingDisclosureBar(mContext).start();
     }
+
+    @Override
+    public void animateExpandNotificationsPanel() {
+        startSystemActivity(new Intent(ACTION_OPEN_TV_NOTIFICATIONS_PANEL));
+    }
+
+    @Override
+    public void animateCollapsePanels(int flags, boolean force) {
+        startSystemActivity(new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME));
+    }
+
+    private void startSystemActivity(Intent intent) {
+        PackageManager pm = mContext.getPackageManager();
+        ResolveInfo ri = pm.resolveActivity(intent, PackageManager.MATCH_SYSTEM_ONLY);
+        if (ri != null && ri.activityInfo != null) {
+            intent.setPackage(ri.activityInfo.packageName);
+            mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
index 2e30d32..0aa965b 100644
--- a/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/usb/UsbResolverActivity.java
@@ -190,4 +190,9 @@
         }
         return true;
     }
+
+    @Override
+    protected boolean shouldShowTabs() {
+        return false;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/util/Assert.java b/packages/SystemUI/src/com/android/systemui/util/Assert.java
index f6e921e..3f05657 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Assert.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Assert.java
@@ -24,12 +24,17 @@
  * Helper providing common assertions.
  */
 public class Assert {
+    private static final Looper sMainLooper = Looper.getMainLooper();
+    private static Looper sTestLooper = null;
 
     @VisibleForTesting
-    public static Looper sMainLooper = Looper.getMainLooper();
+    public static void setTestableLooper(Looper testLooper) {
+        sTestLooper = testLooper;
+    }
 
     public static void isMainThread() {
-        if (!sMainLooper.isCurrentThread()) {
+        if (!sMainLooper.isCurrentThread()
+                && (sTestLooper == null || !sTestLooper.isCurrentThread())) {
             throw new IllegalStateException("should be called from the main thread."
                     + " sMainLooper.threadName=" + sMainLooper.getThread().getName()
                     + " Thread.currentThread()=" + Thread.currentThread().getName());
@@ -37,7 +42,8 @@
     }
 
     public static void isNotMainThread() {
-        if (sMainLooper.isCurrentThread()) {
+        if (sMainLooper.isCurrentThread()
+                && (sTestLooper == null || sTestLooper.isCurrentThread())) {
             throw new IllegalStateException("should not be called from the main thread.");
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
index 0487ce6..ca4b67d 100644
--- a/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/FloatingContentCoordinator.kt
@@ -132,7 +132,6 @@
      *
      * @param content The content that has moved.
      */
-    @JvmOverloads
     fun onContentMoved(content: FloatingContent) {
 
         // Ignore calls when we are currently resolving conflicts, since those calls are from
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
index f4157f2..8625d63 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimator.kt
@@ -126,6 +126,13 @@
     internal var startAction: () -> Unit = ::startInternal
 
     /**
+     * Action to run when [cancel] is called. This can be changed by
+     * [PhysicsAnimatorTestUtils.prepareForTest] to cancel animations from the main thread, which
+     * is required.
+     */
+    internal var cancelAction: (Set<FloatPropertyCompat<in T>>) -> Unit = ::cancelInternal
+
+    /**
      * Springs a property to the given value, using the provided configuration settings.
      *
      * Springs are used when you know the exact value to which you want to animate. They can be
@@ -429,10 +436,13 @@
                         max = max(currentValue, this.max)
                     }
 
-                    // Apply the configuration and start the animation. Since flings can't be
-                    // redirected while in motion, cancel it first.
+                    // Flings can't be updated to a new position while maintaining velocity, because
+                    // we're using the explicitly provided start velocity. Cancel any flings (or
+                    // springs) on this property before flinging.
+                    cancel(animatedProperty)
+
+                    // Apply the configuration and start the animation.
                     getFlingAnimation(animatedProperty)
-                            .also { it.cancel() }
                             .also { flingConfig.applyToAnimation(it) }
                             .start()
                 }
@@ -707,11 +717,26 @@
         return springConfigs.keys.union(flingConfigs.keys)
     }
 
+    /**
+     * Cancels the given properties. This is typically called immediately by [cancel], unless this
+     * animator is under test.
+     */
+    internal fun cancelInternal(properties: Set<FloatPropertyCompat<in T>>) {
+        for (property in properties) {
+            flingAnimations[property]?.cancel()
+            springAnimations[property]?.cancel()
+        }
+    }
+
     /** Cancels all in progress animations on all properties. */
     fun cancel() {
-        for (dynamicAnim in flingAnimations.values.union(springAnimations.values)) {
-            dynamicAnim.cancel()
-        }
+        cancelAction(flingAnimations.keys)
+        cancelAction(springAnimations.keys)
+    }
+
+    /** Cancels in progress animations on the provided properties only. */
+    fun cancel(vararg properties: FloatPropertyCompat<in T>) {
+        cancelAction(properties.toSet())
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
index 965decd..c50eeac 100644
--- a/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
+++ b/packages/SystemUI/src/com/android/systemui/util/animation/PhysicsAnimatorTestUtils.kt
@@ -363,8 +363,12 @@
         private val testEndListeners = ArrayList<PhysicsAnimator.EndListener<T>>()
         private val testUpdateListeners = ArrayList<PhysicsAnimator.UpdateListener<T>>()
 
+        /** Whether we're currently in the middle of executing startInternal(). */
+        private var currentlyRunningStartInternal = false
+
         init {
             animator.startAction = ::startForTest
+            animator.cancelAction = ::cancelForTest
         }
 
         internal fun addTestEndListener(listener: PhysicsAnimator.EndListener<T>) {
@@ -437,7 +441,29 @@
                     }
                 })
 
+                currentlyRunningStartInternal = true
                 animator.startInternal()
+                currentlyRunningStartInternal = false
+                unblockLatch.countDown()
+            }
+
+            unblockLatch.await(timeoutMs, TimeUnit.MILLISECONDS)
+        }
+
+        private fun cancelForTest(properties: Set<FloatPropertyCompat<in T>>) {
+            // If this was called from startInternal, we are already on the animation thread, and
+            // should just call cancelInternal rather than posting it. If we post it, the
+            // cancellation will occur after the rest of startInternal() and we'll immediately
+            // cancel the animation we worked so hard to start!
+            if (currentlyRunningStartInternal) {
+                animator.cancelInternal(properties)
+                return
+            }
+
+            val unblockLatch = CountDownLatch(1)
+
+            animationThreadHandler.post {
+                animator.cancelInternal(properties)
                 unblockLatch.countDown()
             }
 
diff --git a/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
new file mode 100644
index 0000000..2276ba1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/magnetictarget/MagnetizedObject.kt
@@ -0,0 +1,618 @@
+/*
+ * 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.systemui.util.magnetictarget
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.database.ContentObserver
+import android.graphics.PointF
+import android.os.Handler
+import android.os.UserHandle
+import android.os.VibrationEffect
+import android.os.Vibrator
+import android.provider.Settings
+import android.view.MotionEvent
+import android.view.VelocityTracker
+import android.view.View
+import androidx.dynamicanimation.animation.DynamicAnimation
+import androidx.dynamicanimation.animation.FloatPropertyCompat
+import androidx.dynamicanimation.animation.SpringForce
+import com.android.systemui.util.animation.PhysicsAnimator
+import kotlin.math.hypot
+
+/**
+ * Utility class for creating 'magnetized' objects that are attracted to one or more magnetic
+ * targets. Magnetic targets attract objects that are dragged near them, and hold them there unless
+ * they're moved away or released. Releasing objects inside a magnetic target typically performs an
+ * action on the object.
+ *
+ * MagnetizedObject also supports flinging to targets, which will result in the object being pulled
+ * into the target and released as if it was dragged into it.
+ *
+ * To use this class, either construct an instance with an object of arbitrary type, or use the
+ * [MagnetizedObject.magnetizeView] shortcut method if you're magnetizing a view. Then, set
+ * [magnetListener] to receive event callbacks. In your touch handler, pass all MotionEvents
+ * that move this object to [maybeConsumeMotionEvent]. If that method returns true, consider the
+ * event consumed by the MagnetizedObject and don't move the object unless it begins returning false
+ * again.
+ *
+ * @param context Context, used to retrieve a Vibrator instance for vibration effects.
+ * @param underlyingObject The actual object that we're magnetizing.
+ * @param xProperty Property that sets the x value of the object's position.
+ * @param yProperty Property that sets the y value of the object's position.
+ */
+abstract class MagnetizedObject<T : Any>(
+    val context: Context,
+
+    /** The actual object that is animated. */
+    val underlyingObject: T,
+
+    /** Property that gets/sets the object's X value. */
+    val xProperty: FloatPropertyCompat<in T>,
+
+    /** Property that gets/sets the object's Y value. */
+    val yProperty: FloatPropertyCompat<in T>
+) {
+
+    /** Return the width of the object. */
+    abstract fun getWidth(underlyingObject: T): Float
+
+    /** Return the height of the object. */
+    abstract fun getHeight(underlyingObject: T): Float
+
+    /**
+     * Fill the provided array with the location of the top-left of the object, relative to the
+     * entire screen. Compare to [View.getLocationOnScreen].
+     */
+    abstract fun getLocationOnScreen(underlyingObject: T, loc: IntArray)
+
+    /** Methods for listening to events involving a magnetized object.  */
+    interface MagnetListener {
+
+        /**
+         * Called when touch events move within the magnetic field of a target, causing the
+         * object to animate to the target and become 'stuck' there. The animation happens
+         * automatically here - you should not move the object. You can, however, change its state
+         * to indicate to the user that it's inside the target and releasing it will have an effect.
+         *
+         * [maybeConsumeMotionEvent] is now returning true and will continue to do so until a call
+         * to [onUnstuckFromTarget] or [onReleasedInTarget].
+         *
+         * @param target The target that the object is now stuck to.
+         */
+        fun onStuckToTarget(target: MagneticTarget)
+
+        /**
+         * Called when the object is no longer stuck to a target. This means that either touch
+         * events moved outside of the magnetic field radius, or that a forceful fling out of the
+         * target was detected.
+         *
+         * The object won't be automatically animated out of the target, since you're responsible
+         * for moving the object again. You should move it (or animate it) using your own
+         * movement/animation logic.
+         *
+         * Reverse any effects applied in [onStuckToTarget] here.
+         *
+         * If [wasFlungOut] is true, [maybeConsumeMotionEvent] returned true for the ACTION_UP event
+         * that concluded the fling. If [wasFlungOut] is false, that means a drag gesture is ongoing
+         * and [maybeConsumeMotionEvent] is now returning false.
+         *
+         * @param target The target that this object was just unstuck from.
+         * @param velX The X velocity of the touch gesture when it exited the magnetic field.
+         * @param velY The Y velocity of the touch gesture when it exited the magnetic field.
+         * @param wasFlungOut Whether the object was unstuck via a fling gesture. This means that
+         * an ACTION_UP event was received, and that the gesture velocity was sufficient to conclude
+         * that the user wants to un-stick the object despite no touch events occurring outside of
+         * the magnetic field radius.
+         */
+        fun onUnstuckFromTarget(
+            target: MagneticTarget,
+            velX: Float,
+            velY: Float,
+            wasFlungOut: Boolean
+        )
+
+        /**
+         * Called when the object is released inside a target, or flung towards it with enough
+         * velocity to reach it.
+         *
+         * @param target The target that the object was released in.
+         */
+        fun onReleasedInTarget(target: MagneticTarget)
+    }
+
+    private val animator: PhysicsAnimator<T> = PhysicsAnimator.getInstance(underlyingObject)
+    private val objectLocationOnScreen = IntArray(2)
+
+    /**
+     * Targets that have been added to this object. These will all be considered when determining
+     * magnetic fields and fling trajectories.
+     */
+    private val associatedTargets = ArrayList<MagneticTarget>()
+
+    private val velocityTracker: VelocityTracker = VelocityTracker.obtain()
+    private val vibrator: Vibrator = context.getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
+
+    /** Whether touch events are presently occurring within the magnetic field area of a target. */
+    val objectStuckToTarget: Boolean
+        get() = targetObjectIsStuckTo != null
+
+    /** The target the object is stuck to, or null if the object is not stuck to any target. */
+    private var targetObjectIsStuckTo: MagneticTarget? = null
+
+    /**
+     * Sets the listener to receive events. This must be set, or [maybeConsumeMotionEvent]
+     * will always return false and no magnetic effects will occur.
+     */
+    lateinit var magnetListener: MagnetizedObject.MagnetListener
+
+    /**
+     * Sets whether forcefully flinging the object vertically towards a target causes it to be
+     * attracted to the target and then released immediately, despite never being dragged within the
+     * magnetic field.
+     */
+    var flingToTargetEnabled = true
+
+    /**
+     * If fling to target is enabled, forcefully flinging the object towards a target will cause
+     * it to be attracted to the target and then released immediately, despite never being dragged
+     * within the magnetic field.
+     *
+     * This sets the width of the area considered 'near' enough a target to be considered a fling,
+     * in terms of percent of the target view's width. For example, setting this to 3f means that
+     * flings towards a 100px-wide target will be considered 'near' enough if they're towards the
+     * 300px-wide area around the target.
+     *
+     * Flings whose trajectory intersects the area will be attracted and released - even if the
+     * target view itself isn't intersected:
+     *
+     * |             |
+     * |           0 |
+     * |          /  |
+     * |         /   |
+     * |      X /    |
+     * |.....###.....|
+     *
+     *
+     * Flings towards the target whose trajectories do not intersect the area will be treated as
+     * normal flings and the magnet will leave the object alone:
+     *
+     * |             |
+     * |             |
+     * |   0         |
+     * |  /          |
+     * | /    X      |
+     * |.....###.....|
+     *
+     */
+    var flingToTargetWidthPercent = 3f
+
+    /**
+     * Sets the minimum velocity (in pixels per second) required to fling an object to the target
+     * without dragging it into the magnetic field.
+     */
+    var flingToTargetMinVelocity = 4000f
+
+    /**
+     * Sets the minimum velocity (in pixels per second) required to fling un-stuck an object stuck
+     * to the target. If this velocity is reached, the object will be freed even if it wasn't moved
+     * outside the magnetic field radius.
+     */
+    var flingUnstuckFromTargetMinVelocity = 1000f
+
+    /**
+     * Sets the maximum velocity above which the object will not stick to the target. Even if the
+     * object is dragged through the magnetic field, it will not stick to the target until the
+     * velocity is below this value.
+     */
+    var stickToTargetMaxVelocity = 2000f
+
+    /**
+     * Enable or disable haptic vibration effects when the object interacts with the magnetic field.
+     *
+     * If you're experiencing crashes when the object enters targets, ensure that you have the
+     * android.permission.VIBRATE permission!
+     */
+    var hapticsEnabled = true
+
+    /** Whether the HAPTIC_FEEDBACK_ENABLED setting is true. */
+    private var systemHapticsEnabled = false
+
+    /** Default spring configuration to use for animating the object into a target. */
+    var springConfig = PhysicsAnimator.SpringConfig(
+            SpringForce.STIFFNESS_MEDIUM, SpringForce.DAMPING_RATIO_NO_BOUNCY)
+
+    /**
+     * Spring configuration to use to spring the object into a target specifically when it's flung
+     * towards (rather than dragged near) it.
+     */
+    var flungIntoTargetSpringConfig = springConfig
+
+    init {
+        val hapticSettingObserver =
+                object : ContentObserver(Handler.getMain()) {
+            override fun onChange(selfChange: Boolean) {
+                systemHapticsEnabled =
+                        Settings.System.getIntForUser(
+                                context.contentResolver,
+                                Settings.System.HAPTIC_FEEDBACK_ENABLED,
+                                0,
+                                UserHandle.USER_CURRENT) != 0
+            }
+        }
+
+        context.contentResolver.registerContentObserver(
+                Settings.System.getUriFor(Settings.System.HAPTIC_FEEDBACK_ENABLED),
+                true /* notifyForDescendants */, hapticSettingObserver)
+
+        // Trigger the observer once to initialize systemHapticsEnabled.
+        hapticSettingObserver.onChange(false /* selfChange */)
+    }
+
+    /**
+     * Adds the provided MagneticTarget to this object. The object will now be attracted to the
+     * target if it strays within its magnetic field or is flung towards it.
+     *
+     * If this target (or its magnetic field) overlaps another target added to this object, the
+     * prior target will take priority.
+     */
+    fun addTarget(target: MagneticTarget) {
+        associatedTargets.add(target)
+        target.updateLocationOnScreen()
+    }
+
+    /**
+     * Shortcut that accepts a View and a magnetic field radius and adds it as a magnetic target.
+     *
+     * @return The MagneticTarget instance for the given View. This can be used to change the
+     * target's magnetic field radius after it's been added. It can also be added to other
+     * magnetized objects.
+     */
+    fun addTarget(target: View, magneticFieldRadiusPx: Int): MagneticTarget {
+        return MagneticTarget(target, magneticFieldRadiusPx).also { addTarget(it) }
+    }
+
+    /**
+     * Removes the given target from this object. The target will no longer attract the object.
+     */
+    fun removeTarget(target: MagneticTarget) {
+        associatedTargets.remove(target)
+    }
+
+    /**
+     * Provide this method with all motion events that move the magnetized object. If the
+     * location of the motion events moves within the magnetic field of a target, or indicate a
+     * fling-to-target gesture, this method will return true and you should not move the object
+     * yourself until it returns false again.
+     *
+     * Note that even when this method returns true, you should continue to pass along new motion
+     * events so that we know when the events move back outside the magnetic field area.
+     *
+     * This method will always return false if you haven't set a [magnetListener].
+     */
+    fun maybeConsumeMotionEvent(ev: MotionEvent): Boolean {
+        // Short-circuit if we don't have a listener or any targets, since those are required.
+        if (associatedTargets.size == 0) {
+            return false
+        }
+
+        // When a gesture begins, recalculate target views' positions on the screen in case they
+        // have changed. Also, clear state.
+        if (ev.action == MotionEvent.ACTION_DOWN) {
+            updateTargetViewLocations()
+
+            // Clear the velocity tracker and assume we're not stuck to a target yet.
+            velocityTracker.clear()
+            targetObjectIsStuckTo = null
+        }
+
+        addMovement(ev)
+
+        val targetObjectIsInMagneticFieldOf = associatedTargets.firstOrNull { target ->
+            val distanceFromTargetCenter = hypot(
+                    ev.rawX - target.centerOnScreen.x,
+                    ev.rawY - target.centerOnScreen.y)
+            distanceFromTargetCenter < target.magneticFieldRadiusPx
+        }
+
+        // If we aren't currently stuck to a target, and we're in the magnetic field of a target,
+        // we're newly stuck.
+        val objectNewlyStuckToTarget =
+                !objectStuckToTarget && targetObjectIsInMagneticFieldOf != null
+
+        // If we are currently stuck to a target, we're in the magnetic field of a target, and that
+        // target isn't the one we're currently stuck to, then touch events have moved into a
+        // adjacent target's magnetic field.
+        val objectMovedIntoDifferentTarget =
+                objectStuckToTarget &&
+                        targetObjectIsInMagneticFieldOf != null &&
+                        targetObjectIsStuckTo != targetObjectIsInMagneticFieldOf
+
+        if (objectNewlyStuckToTarget || objectMovedIntoDifferentTarget) {
+            velocityTracker.computeCurrentVelocity(1000)
+            val velX = velocityTracker.xVelocity
+            val velY = velocityTracker.yVelocity
+
+            // If the object is moving too quickly within the magnetic field, do not stick it. This
+            // only applies to objects newly stuck to a target. If the object is moved into a new
+            // target, it wasn't moving at all (since it was stuck to the previous one).
+            if (objectNewlyStuckToTarget && hypot(velX, velY) > stickToTargetMaxVelocity) {
+                return false
+            }
+
+            // This touch event is newly within the magnetic field - let the listener know, and
+            // animate sticking to the magnet.
+            targetObjectIsStuckTo = targetObjectIsInMagneticFieldOf
+            cancelAnimations()
+            magnetListener.onStuckToTarget(targetObjectIsInMagneticFieldOf!!)
+            animateStuckToTarget(targetObjectIsInMagneticFieldOf!!, velX, velY, false)
+
+            vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
+        } else if (targetObjectIsInMagneticFieldOf == null && objectStuckToTarget) {
+            velocityTracker.computeCurrentVelocity(1000)
+
+            // This touch event is newly outside the magnetic field - let the listener know. It will
+            // move the object out of the target using its own movement logic.
+            cancelAnimations()
+            magnetListener.onUnstuckFromTarget(
+                    targetObjectIsStuckTo!!, velocityTracker.xVelocity, velocityTracker.yVelocity,
+                    wasFlungOut = false)
+            targetObjectIsStuckTo = null
+
+            vibrateIfEnabled(VibrationEffect.EFFECT_TICK)
+        }
+
+        // First, check for relevant gestures concluding with an ACTION_UP.
+        if (ev.action == MotionEvent.ACTION_UP) {
+
+            velocityTracker.computeCurrentVelocity(1000 /* units */)
+            val velX = velocityTracker.xVelocity
+            val velY = velocityTracker.yVelocity
+
+            // Cancel the magnetic animation since we might still be springing into the magnetic
+            // target, but we're about to fling away or release.
+            cancelAnimations()
+
+            if (objectStuckToTarget) {
+                if (hypot(velX, velY) > flingUnstuckFromTargetMinVelocity) {
+                    // If the object is stuck, but it was forcefully flung away from the target,
+                    // tell the listener so the object can be animated out of the target.
+                    magnetListener.onUnstuckFromTarget(
+                            targetObjectIsStuckTo!!, velX, velY, wasFlungOut = true)
+                } else {
+                    // If the object is stuck and not flung away, it was released inside the target.
+                    magnetListener.onReleasedInTarget(targetObjectIsStuckTo!!)
+                    vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
+                }
+
+                // Either way, we're no longer stuck.
+                targetObjectIsStuckTo = null
+                return true
+            }
+
+            // The target we're flinging towards, or null if we're not flinging towards any target.
+            val flungToTarget = associatedTargets.firstOrNull { target ->
+                isForcefulFlingTowardsTarget(target, ev.rawX, ev.rawY, velX, velY)
+            }
+
+            if (flungToTarget != null) {
+                // If this is a fling-to-target, animate the object to the magnet and then release
+                // it.
+                magnetListener.onStuckToTarget(flungToTarget)
+                targetObjectIsStuckTo = flungToTarget
+
+                animateStuckToTarget(flungToTarget, velX, velY, true) {
+                    targetObjectIsStuckTo = null
+                    magnetListener.onReleasedInTarget(flungToTarget)
+                    vibrateIfEnabled(VibrationEffect.EFFECT_HEAVY_CLICK)
+                }
+
+                return true
+            }
+
+            // If it's not either of those things, we are not interested.
+            return false
+        }
+
+        return objectStuckToTarget // Always consume touch events if the object is stuck.
+    }
+
+    /** Plays the given vibration effect if haptics are enabled. */
+    @SuppressLint("MissingPermission")
+    private fun vibrateIfEnabled(effect: Int) {
+        if (hapticsEnabled && systemHapticsEnabled) {
+            vibrator.vibrate(effect.toLong())
+        }
+    }
+
+    /** Adds the movement to the velocity tracker using raw coordinates. */
+    private fun addMovement(event: MotionEvent) {
+        // Add movement to velocity tracker using raw screen X and Y coordinates instead
+        // of window coordinates because the window frame may be moving at the same time.
+        val deltaX = event.rawX - event.x
+        val deltaY = event.rawY - event.y
+        event.offsetLocation(deltaX, deltaY)
+        velocityTracker.addMovement(event)
+        event.offsetLocation(-deltaX, -deltaY)
+    }
+
+    /** Animates sticking the object to the provided target with the given start velocities.  */
+    private fun animateStuckToTarget(
+        target: MagneticTarget,
+        velX: Float,
+        velY: Float,
+        flung: Boolean,
+        after: (() -> Unit)? = null
+    ) {
+        target.updateLocationOnScreen()
+        getLocationOnScreen(underlyingObject, objectLocationOnScreen)
+
+        // Calculate the difference between the target's center coordinates and the object's.
+        // Animating the object's x/y properties by these values will center the object on top
+        // of the magnetic target.
+        val xDiff = target.centerOnScreen.x -
+                getWidth(underlyingObject) / 2f - objectLocationOnScreen[0]
+        val yDiff = target.centerOnScreen.y -
+                getHeight(underlyingObject) / 2f - objectLocationOnScreen[1]
+
+        val springConfig = if (flung) flungIntoTargetSpringConfig else springConfig
+
+        cancelAnimations()
+
+        // Animate to the center of the target.
+        animator
+                .spring(xProperty, xProperty.getValue(underlyingObject) + xDiff, velX,
+                        springConfig)
+                .spring(yProperty, yProperty.getValue(underlyingObject) + yDiff, velY,
+                        springConfig)
+
+        if (after != null) {
+            animator.withEndActions(after)
+        }
+
+        animator.start()
+    }
+
+    /**
+     * Whether or not the provided values match a 'fast fling' towards the provided target. If it
+     * does, we consider it a fling-to-target gesture.
+     */
+    private fun isForcefulFlingTowardsTarget(
+        target: MagneticTarget,
+        rawX: Float,
+        rawY: Float,
+        velX: Float,
+        velY: Float
+    ): Boolean {
+        if (!flingToTargetEnabled) {
+            return false
+        }
+
+        // Whether velocity is sufficient, depending on whether we're flinging into a target at the
+        // top or the bottom of the screen.
+        val velocitySufficient =
+                if (rawY < target.centerOnScreen.y) velY > flingToTargetMinVelocity
+                else velY < flingToTargetMinVelocity
+
+        if (!velocitySufficient) {
+            return false
+        }
+
+        // Whether the trajectory of the fling intersects the target area.
+        var targetCenterXIntercept = rawX
+
+        // Only do math if the X velocity is non-zero, otherwise X won't change.
+        if (velX != 0f) {
+            // Rise over run...
+            val slope = velY / velX
+            // ...y = mx + b, b = y / mx...
+            val yIntercept = rawY - slope * rawX
+
+            // ...calculate the x value when y = the target's y-coordinate.
+            targetCenterXIntercept = (target.centerOnScreen.y - yIntercept) / slope
+        }
+
+        // The width of the area we're looking for a fling towards.
+        val targetAreaWidth = target.targetView.width * flingToTargetWidthPercent
+
+        // Velocity was sufficient, so return true if the intercept is within the target area.
+        return targetCenterXIntercept > target.centerOnScreen.x - targetAreaWidth / 2 &&
+                targetCenterXIntercept < target.centerOnScreen.x + targetAreaWidth / 2
+    }
+
+    /** Cancel animations on this object's x/y properties. */
+    internal fun cancelAnimations() {
+        animator.cancel(xProperty, yProperty)
+    }
+
+    /** Updates the locations on screen of all of the [associatedTargets]. */
+    internal fun updateTargetViewLocations() {
+        associatedTargets.forEach { it.updateLocationOnScreen() }
+    }
+
+    /**
+     * Represents a target view with a magnetic field radius and cached center-on-screen
+     * coordinates.
+     *
+     * Instances of MagneticTarget are passed to a MagnetizedObject's [addTarget], and can then
+     * attract the object if it's dragged near or flung towards it. MagneticTargets can be added to
+     * multiple objects.
+     */
+    class MagneticTarget(
+        internal val targetView: View,
+        var magneticFieldRadiusPx: Int
+    ) {
+        internal val centerOnScreen = PointF()
+
+        private val tempLoc = IntArray(2)
+
+        fun updateLocationOnScreen() {
+            targetView.getLocationOnScreen(tempLoc)
+
+            // Add half of the target size to get the center, and subtract translation since the
+            // target could be animating in while we're doing this calculation.
+            centerOnScreen.set(
+                    tempLoc[0] + targetView.width / 2f - targetView.translationX,
+                    tempLoc[1] + targetView.height / 2f - targetView.translationY)
+        }
+    }
+
+    companion object {
+
+        /**
+         * Magnetizes the given view. Magnetized views are attracted to one or more magnetic
+         * targets. Magnetic targets attract objects that are dragged near them, and hold them there
+         * unless they're moved away or released. Releasing objects inside a magnetic target
+         * typically performs an action on the object.
+         *
+         * Magnetized views can also be flung to targets, which will result in the view being pulled
+         * into the target and released as if it was dragged into it.
+         *
+         * To use the returned MagnetizedObject<View> instance, first set [magnetListener] to
+         * receive event callbacks. In your touch handler, pass all MotionEvents that move this view
+         * to [maybeConsumeMotionEvent]. If that method returns true, consider the event consumed by
+         * MagnetizedObject and don't move the view unless it begins returning false again.
+         *
+         * The view will be moved via translationX/Y properties, and its
+         * width/height will be determined via getWidth()/getHeight(). If you are animating
+         * something other than a view, or want to position your view using properties other than
+         * translationX/Y, implement an instance of [MagnetizedObject].
+         *
+         * Note that the magnetic library can't re-order your view automatically. If the view
+         * renders on top of the target views, it will obscure the target when it sticks to it.
+         * You'll want to bring the view to the front in [MagnetListener.onStuckToTarget].
+         */
+        @JvmStatic
+        fun <T : View> magnetizeView(view: T): MagnetizedObject<T> {
+            return object : MagnetizedObject<T>(
+                    view.context,
+                    view,
+                    DynamicAnimation.TRANSLATION_X,
+                    DynamicAnimation.TRANSLATION_Y) {
+                override fun getWidth(underlyingObject: T): Float {
+                    return underlyingObject.width.toFloat()
+                }
+
+                override fun getHeight(underlyingObject: T): Float {
+                    return underlyingObject.height.toFloat() }
+
+                override fun getLocationOnScreen(underlyingObject: T, loc: IntArray) {
+                    underlyingObject.getLocationOnScreen(loc)
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java
new file mode 100644
index 0000000..a94af24
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingActivity.java
@@ -0,0 +1,223 @@
+/*
+ * 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.systemui.wifi;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.debug.IAdbManager;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.ServiceManager;
+import android.util.EventLog;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.CheckBox;
+import android.widget.Toast;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+import com.android.systemui.R;
+
+/**
+ * Alerts the user of an untrusted network when enabling wireless debugging.
+ * The user can either deny, allow, or allow with the "always allow on this
+ * network" checked.
+ */
+public class WifiDebuggingActivity extends AlertActivity
+                                  implements DialogInterface.OnClickListener {
+    private static final String TAG = "WifiDebuggingActivity";
+
+    private CheckBox mAlwaysAllow;
+    // Notifies when wifi is disabled, or the network changed
+    private WifiChangeReceiver mWifiChangeReceiver;
+    private WifiManager mWifiManager;
+    private String mBssid;
+    private boolean mClicked = false;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        Window window = getWindow();
+        window.addSystemFlags(
+                WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
+        window.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
+
+        super.onCreate(icicle);
+
+
+        mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+        mWifiChangeReceiver = new WifiChangeReceiver(this);
+
+        Intent intent = getIntent();
+        String ssid = intent.getStringExtra("ssid");
+        mBssid = intent.getStringExtra("bssid");
+
+        if (ssid == null || mBssid == null) {
+            finish();
+            return;
+        }
+
+        final AlertController.AlertParams ap = mAlertParams;
+        ap.mTitle = getString(R.string.wifi_debugging_title);
+        ap.mMessage = getString(R.string.wifi_debugging_message, ssid, mBssid);
+        ap.mPositiveButtonText = getString(R.string.wifi_debugging_allow);
+        ap.mNegativeButtonText = getString(android.R.string.cancel);
+        ap.mPositiveButtonListener = this;
+        ap.mNegativeButtonListener = this;
+
+        // add "always allow" checkbox
+        LayoutInflater inflater = LayoutInflater.from(ap.mContext);
+        View checkbox = inflater.inflate(com.android.internal.R.layout.always_use_checkbox, null);
+        mAlwaysAllow = (CheckBox) checkbox.findViewById(com.android.internal.R.id.alwaysUse);
+        mAlwaysAllow.setText(getString(R.string.wifi_debugging_always));
+        ap.mView = checkbox;
+        window.setCloseOnTouchOutside(false);
+
+        setupAlert();
+
+        // adding touch listener on affirmative button - checks if window is obscured
+        // if obscured, do not let user give permissions (could be tapjacking involved)
+        final View.OnTouchListener filterTouchListener = (View v, MotionEvent event) -> {
+            // Filter obscured touches by consuming them.
+            if (((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0)
+                    || ((event.getFlags() & MotionEvent.FLAG_WINDOW_IS_PARTIALLY_OBSCURED) != 0)) {
+                if (event.getAction() == MotionEvent.ACTION_UP) {
+                    // TODO: need a different value for safety net?
+                    EventLog.writeEvent(0x534e4554, "62187985"); // safety net logging
+                    Toast.makeText(v.getContext(),
+                            R.string.touch_filtered_warning,
+                            Toast.LENGTH_SHORT).show();
+                }
+                return true;
+            }
+            return false;
+        };
+        mAlert.getButton(BUTTON_POSITIVE).setOnTouchListener(filterTouchListener);
+
+    }
+
+    @Override
+    public void onWindowAttributesChanged(WindowManager.LayoutParams params) {
+        super.onWindowAttributesChanged(params);
+    }
+
+    private class WifiChangeReceiver extends BroadcastReceiver {
+        private final Activity mActivity;
+        WifiChangeReceiver(Activity activity) {
+            mActivity = activity;
+        }
+
+        @Override
+        public void onReceive(Context content, Intent intent) {
+            String action = intent.getAction();
+            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                int state = intent.getIntExtra(
+                        WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
+                if (state == WifiManager.WIFI_STATE_DISABLED) {
+                    mActivity.finish();
+                }
+            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
+                NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
+                        WifiManager.EXTRA_NETWORK_INFO);
+                if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+                    if (!networkInfo.isConnected()) {
+                        mActivity.finish();
+                        return;
+                    }
+                    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+                    if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
+                        mActivity.finish();
+                        return;
+                    }
+                    String bssid = wifiInfo.getBSSID();
+                    if (bssid == null || bssid.isEmpty()) {
+                        mActivity.finish();
+                        return;
+                    }
+                    if (!bssid.equals(mBssid)) {
+                        mActivity.finish();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+        IntentFilter filter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        registerReceiver(mWifiChangeReceiver, filter);
+    }
+
+    @Override
+    protected void onStop() {
+        if (mWifiChangeReceiver != null) {
+            unregisterReceiver(mWifiChangeReceiver);
+        }
+        super.onStop();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+
+        // In the case where user dismissed the dialog, we don't get an onClick event.
+        // In that case, tell adb to deny the network connection.
+        if (!mClicked) {
+            try {
+                IBinder b = ServiceManager.getService(ADB_SERVICE);
+                IAdbManager service = IAdbManager.Stub.asInterface(b);
+                service.denyWirelessDebugging();
+            } catch (Exception e) {
+                Log.e(TAG, "Unable to notify Adb service", e);
+            }
+        }
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        mClicked = true;
+        boolean allow = (which == AlertDialog.BUTTON_POSITIVE);
+        boolean alwaysAllow = allow && mAlwaysAllow.isChecked();
+        try {
+            IBinder b = ServiceManager.getService(ADB_SERVICE);
+            IAdbManager service = IAdbManager.Stub.asInterface(b);
+            if (allow) {
+                service.allowWirelessDebugging(alwaysAllow, mBssid);
+            } else {
+                service.denyWirelessDebugging();
+            }
+        } catch (Exception e) {
+            Log.e(TAG, "Unable to notify Adb service", e);
+        }
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java
new file mode 100644
index 0000000..0266a84
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/wifi/WifiDebuggingSecondaryUserActivity.java
@@ -0,0 +1,113 @@
+/*
+ * 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.systemui.wifi;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.wifi.WifiInfo;
+import android.net.wifi.WifiManager;
+import android.os.Bundle;
+
+import com.android.internal.app.AlertActivity;
+import com.android.internal.app.AlertController;
+import com.android.systemui.R;
+
+/**
+ * Alerts the user that wireless debugging cannot be enabled by a secondary user.
+ */
+public class WifiDebuggingSecondaryUserActivity extends AlertActivity
+        implements DialogInterface.OnClickListener {
+    private WifiChangeReceiver mWifiChangeReceiver;
+    private WifiManager mWifiManager;
+
+    @Override
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+
+        mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
+        mWifiChangeReceiver = new WifiChangeReceiver(this);
+
+        final AlertController.AlertParams ap = mAlertParams;
+        ap.mTitle = getString(R.string.wifi_debugging_secondary_user_title);
+        ap.mMessage = getString(R.string.wifi_debugging_secondary_user_message);
+        ap.mPositiveButtonText = getString(android.R.string.ok);
+        ap.mPositiveButtonListener = this;
+
+        setupAlert();
+    }
+
+    private class WifiChangeReceiver extends BroadcastReceiver {
+        private final Activity mActivity;
+        WifiChangeReceiver(Activity activity) {
+            mActivity = activity;
+        }
+
+        @Override
+        public void onReceive(Context content, Intent intent) {
+            String action = intent.getAction();
+            if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
+                int state = intent.getIntExtra(
+                        WifiManager.EXTRA_WIFI_STATE, WifiManager.WIFI_STATE_DISABLED);
+                if (state == WifiManager.WIFI_STATE_DISABLED) {
+                    mActivity.finish();
+                }
+            } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
+                NetworkInfo networkInfo = (NetworkInfo) intent.getParcelableExtra(
+                        WifiManager.EXTRA_NETWORK_INFO);
+                if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
+                    if (!networkInfo.isConnected()) {
+                        mActivity.finish();
+                        return;
+                    }
+                    WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
+                    if (wifiInfo == null || wifiInfo.getNetworkId() == -1) {
+                        mActivity.finish();
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public void onStart() {
+        super.onStart();
+
+        IntentFilter filter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
+        filter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
+        registerReceiver(mWifiChangeReceiver, filter);
+    }
+
+    @Override
+    protected void onStop() {
+        if (mWifiChangeReceiver != null) {
+            unregisterReceiver(mWifiChangeReceiver);
+        }
+        super.onStop();
+    }
+
+    @Override
+    public void onClick(DialogInterface dialog, int which) {
+        finish();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
index bc24ad0..c66f07d 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayController.java
@@ -101,6 +101,11 @@
                                 return;
                             }
                             Display display = getDisplay(displayId);
+                            if (display == null) {
+                                Slog.w(TAG, "Skipping Display Configuration change on invalid"
+                                        + " display. It may have been removed.");
+                                return;
+                            }
                             Context perDisplayContext = mContext;
                             if (displayId != Display.DEFAULT_DISPLAY) {
                                 perDisplayContext = mContext.createDisplayContext(display);
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
index 7dad05d..1b62cbf 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java
@@ -34,6 +34,7 @@
 import android.view.animation.Interpolator;
 import android.view.animation.PathInterpolator;
 
+import com.android.systemui.TransactionPool;
 import com.android.systemui.dagger.qualifiers.Main;
 
 import java.util.ArrayList;
@@ -48,8 +49,8 @@
 public class DisplayImeController implements DisplayController.OnDisplaysChangedListener {
     private static final String TAG = "DisplayImeController";
 
-    static final int ANIMATION_DURATION_SHOW_MS = 275;
-    static final int ANIMATION_DURATION_HIDE_MS = 340;
+    public static final int ANIMATION_DURATION_SHOW_MS = 275;
+    public static final int ANIMATION_DURATION_HIDE_MS = 340;
     static final Interpolator INTERPOLATOR = new PathInterpolator(0.4f, 0f, 0.2f, 1f);
     private static final int DIRECTION_NONE = 0;
     private static final int DIRECTION_SHOW = 1;
@@ -57,6 +58,7 @@
 
     SystemWindows mSystemWindows;
     final Handler mHandler;
+    final TransactionPool mTransactionPool;
 
     final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>();
 
@@ -64,9 +66,10 @@
 
     @Inject
     public DisplayImeController(SystemWindows syswin, DisplayController displayController,
-            @Main Handler mainHandler) {
+            @Main Handler mainHandler, TransactionPool transactionPool) {
         mHandler = mainHandler;
         mSystemWindows = syswin;
+        mTransactionPool = transactionPool;
         displayController.addDisplayWindowListener(this);
     }
 
@@ -255,18 +258,18 @@
                         show ? ANIMATION_DURATION_SHOW_MS : ANIMATION_DURATION_HIDE_MS);
 
                 mAnimation.addUpdateListener(animation -> {
-                    SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+                    SurfaceControl.Transaction t = mTransactionPool.acquire();
                     float value = (float) animation.getAnimatedValue();
                     t.setPosition(mImeSourceControl.getLeash(), x, value);
                     dispatchPositionChanged(mDisplayId, imeTop(imeSource, value), t);
                     t.apply();
-                    t.close();
+                    mTransactionPool.release(t);
                 });
                 mAnimation.setInterpolator(INTERPOLATOR);
                 mAnimation.addListener(new AnimatorListenerAdapter() {
                     @Override
                     public void onAnimationStart(Animator animation) {
-                        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+                        SurfaceControl.Transaction t = mTransactionPool.acquire();
                         t.setPosition(mImeSourceControl.getLeash(), x, startY);
                         dispatchStartPositioning(mDisplayId, imeTop(imeSource, startY),
                                 imeTop(imeSource, endY), mAnimationDirection == DIRECTION_SHOW,
@@ -275,11 +278,11 @@
                             t.show(mImeSourceControl.getLeash());
                         }
                         t.apply();
-                        t.close();
+                        mTransactionPool.release(t);
                     }
                     @Override
                     public void onAnimationEnd(Animator animation) {
-                        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+                        SurfaceControl.Transaction t = mTransactionPool.acquire();
                         t.setPosition(mImeSourceControl.getLeash(), x, endY);
                         dispatchEndPositioning(mDisplayId, imeTop(imeSource, endY),
                                 mAnimationDirection == DIRECTION_SHOW, t);
@@ -287,7 +290,7 @@
                             t.hide(mImeSourceControl.getLeash());
                         }
                         t.apply();
-                        t.close();
+                        mTransactionPool.release(t);
 
                         mAnimationDirection = DIRECTION_NONE;
                         mAnimation = null;
diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java
index 64b0b66..4652abf 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayLayout.java
@@ -35,6 +35,7 @@
 import android.graphics.Rect;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.util.DisplayMetrics;
 import android.util.RotationUtils;
 import android.util.Size;
 import android.view.Display;
@@ -191,6 +192,11 @@
         return mDensityDpi;
     }
 
+    /** Get the density scale for the display. */
+    public float density() {
+        return mDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
+    }
+
     /** Get whether this layout is landscape. */
     public boolean isLandscape() {
         return mWidth > mHeight;
diff --git a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
index 044a2a6..23df991 100644
--- a/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
+++ b/packages/SystemUI/src/com/android/systemui/wm/SystemWindows.java
@@ -162,6 +162,23 @@
         return pd.getWindow(windowType);
     }
 
+    /**
+     * Gets the SurfaceControl associated with a root view. This is the same surface that backs the
+     * ViewRootImpl.
+     */
+    public SurfaceControl getViewSurface(View rootView) {
+        for (int i = 0; i < mPerDisplay.size(); ++i) {
+            for (int iWm = 0; iWm < mPerDisplay.valueAt(i).mWwms.size(); ++iWm) {
+                SurfaceControl out =
+                        mPerDisplay.valueAt(i).mWwms.get(iWm).getSurfaceControlForWindow(rootView);
+                if (out != null) {
+                    return out;
+                }
+            }
+        }
+        return null;
+    }
+
     private class PerDisplay {
         final int mDisplayId;
         private final SparseArray<SysUiWindowManager> mWwms = new SparseArray<>();
@@ -256,6 +273,10 @@
         void updateConfiguration(Configuration configuration) {
             setConfiguration(configuration);
         }
+
+        SurfaceControl getSurfaceControlForWindow(View rootView) {
+            return getSurfaceControl(rootView);
+        }
     }
 
     class ContainerWindow extends IWindow.Stub {
diff --git a/packages/SystemUI/tests/Android.mk b/packages/SystemUI/tests/Android.mk
index e5f56d4..38da21e 100644
--- a/packages/SystemUI/tests/Android.mk
+++ b/packages/SystemUI/tests/Android.mk
@@ -46,6 +46,9 @@
 # UI it doesn't own. This is necessary to allow screenshots to be taken
 LOCAL_CERTIFICATE := platform
 
+LOCAL_FULL_LIBS_MANIFEST_FILES := $(LOCAL_PATH)/AndroidManifest.xml
+LOCAL_MANIFEST_FILE := AndroidManifest-base.xml
+
 # Provide jack a list of classes to exclude from code coverage.
 # This is needed because the SystemUITests compile SystemUI source directly, rather than using
 # LOCAL_INSTRUMENTATION_FOR := SystemUI.
diff --git a/packages/SystemUI/tests/AndroidManifest-base.xml b/packages/SystemUI/tests/AndroidManifest-base.xml
new file mode 100644
index 0000000..f08d3d2
--- /dev/null
+++ b/packages/SystemUI/tests/AndroidManifest-base.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<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"
+    android:sharedUserId="android.uid.system"
+    package="com.android.systemui.tests" />
diff --git a/packages/SystemUI/tests/AndroidManifest.xml b/packages/SystemUI/tests/AndroidManifest.xml
index c51624b..12c7048 100644
--- a/packages/SystemUI/tests/AndroidManifest.xml
+++ b/packages/SystemUI/tests/AndroidManifest.xml
@@ -18,7 +18,7 @@
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:sharedUserId="android.uid.system"
-    package="com.android.systemui.tests">
+    package="com.android.systemui" >
 
     <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
     <uses-permission android:name="android.permission.ACCESS_VOICE_INTERACTION_SERVICE" />
@@ -55,11 +55,6 @@
 
     <application android:debuggable="true" android:largeHeap="true">
         <uses-library android:name="android.test.runner" />
-        <activity android:name="com.android.systemui.screenshot.ScreenshotStubActivity" />
-
-        <service
-            android:name="com.android.systemui.qs.external.TileLifecycleManagerTests$FakeTileService"
-            android:process=":killable" />
 
         <receiver android:name="com.android.systemui.SliceBroadcastRelayHandlerTest$Receiver">
             <intent-filter>
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
index 082782d..7231b8a 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardPresentationTest.java
@@ -37,12 +37,12 @@
     @Test
     public void testInflation_doesntCrash() {
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         InjectionInflationController inflationController = new InjectionInflationController(
                 SystemUIFactory.getInstance().getRootComponent());
         Context context = getContext();
-        KeyguardPresentation keyguardPresentation =
-                new KeyguardPresentation(context, context.getDisplay(), inflationController);
+        KeyguardPresentation keyguardPresentation = new KeyguardPresentation(context,
+                context.getDisplayNoVerify(), inflationController);
         keyguardPresentation.onCreate(null /*savedInstanceState */);
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 116f8fc..462b042 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -19,7 +19,6 @@
 import android.net.Uri;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
 
@@ -51,7 +50,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         InjectionInflationController inflationController = new InjectionInflationController(
                 SystemUIFactory.getInstance().getRootComponent());
         LayoutInflater layoutInflater = inflationController
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
index e4b83cc..bc3c3d9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewTest.java
@@ -20,14 +20,12 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.LayoutInflater;
 
 import com.android.systemui.R;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.util.Assert;
 import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Before;
@@ -50,7 +48,7 @@
 
     @Before
     public void setUp() {
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
         InjectionInflationController inflationController = new InjectionInflationController(
                 SystemUIFactory.getInstance().getRootComponent());
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 7e4ba92..6a093963 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -22,6 +22,7 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
@@ -75,6 +76,7 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 @SmallTest
@@ -117,6 +119,8 @@
     private SubscriptionManager mSubscriptionManager;
     @Mock
     private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock
+    private Executor mBackgroundExecutor;
     private TestableLooper mTestableLooper;
     private TestableKeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
@@ -137,7 +141,9 @@
         when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(true);
         when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true);
         when(mUserManager.isPrimaryUser()).thenReturn(true);
-        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mStrongAuthTracker
+                .isUnlockingWithBiometricAllowed(anyBoolean() /* isStrongBiometric */))
+                .thenReturn(true);
         context.addMockSystemService(TrustManager.class, mTrustManager);
         context.addMockSystemService(FingerprintManager.class, mFingerprintManager);
         context.addMockSystemService(BiometricManager.class, mBiometricManager);
@@ -147,6 +153,7 @@
         context.addMockSystemService(SubscriptionManager.class, mSubscriptionManager);
 
         mTestableLooper = TestableLooper.get(this);
+        allowTestableLooperAsMainThread();
         mKeyguardUpdateMonitor = new TestableKeyguardUpdateMonitor(context);
     }
 
@@ -449,7 +456,10 @@
 
     @Test
     public void testOnFaceAuthenticated_skipsFaceWhenAuthenticated() {
-        mKeyguardUpdateMonitor.onFaceAuthenticated(KeyguardUpdateMonitor.getCurrentUser());
+        // test whether face will be skipped if authenticated, so the value of isStrongBiometric
+        // doesn't matter here
+        mKeyguardUpdateMonitor.onFaceAuthenticated(KeyguardUpdateMonitor.getCurrentUser(),
+                true /* isStrongBiometric */);
         mKeyguardUpdateMonitor.sendKeyguardBouncerChanged(true);
         mTestableLooper.processAllMessages();
 
@@ -459,18 +469,36 @@
     @Test
     public void testGetUserCanSkipBouncer_whenFace() {
         int user = KeyguardUpdateMonitor.getCurrentUser();
-        mKeyguardUpdateMonitor.onFaceAuthenticated(user);
+        mKeyguardUpdateMonitor.onFaceAuthenticated(user, true /* isStrongBiometric */);
         assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
     }
 
     @Test
+    public void testGetUserCanSkipBouncer_whenFace_nonStrongAndDisallowed() {
+        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(false /* isStrongBiometric */))
+                .thenReturn(false);
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        mKeyguardUpdateMonitor.onFaceAuthenticated(user, false /* isStrongBiometric */);
+        assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isFalse();
+    }
+
+    @Test
     public void testGetUserCanSkipBouncer_whenFingerprint() {
         int user = KeyguardUpdateMonitor.getCurrentUser();
-        mKeyguardUpdateMonitor.onFingerprintAuthenticated(user);
+        mKeyguardUpdateMonitor.onFingerprintAuthenticated(user, true /* isStrongBiometric */);
         assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isTrue();
     }
 
     @Test
+    public void testGetUserCanSkipBouncer_whenFingerprint_nonStrongAndDisallowed() {
+        when(mStrongAuthTracker.isUnlockingWithBiometricAllowed(false /* isStrongBiometric */))
+                .thenReturn(false);
+        int user = KeyguardUpdateMonitor.getCurrentUser();
+        mKeyguardUpdateMonitor.onFingerprintAuthenticated(user, false /* isStrongBiometric */);
+        assertThat(mKeyguardUpdateMonitor.getUserCanSkipBouncer(user)).isFalse();
+    }
+
+    @Test
     public void testGetUserCanSkipBouncer_whenTrust() {
         int user = KeyguardUpdateMonitor.getCurrentUser();
         mKeyguardUpdateMonitor.onTrustChanged(true /* enabled */, user, 0 /* flags */);
@@ -584,7 +612,7 @@
         protected TestableKeyguardUpdateMonitor(Context context) {
             super(context,
                     TestableLooper.get(KeyguardUpdateMonitorTest.this).getLooper(),
-                    mBroadcastDispatcher, mDumpController);
+                    mBroadcastDispatcher, mDumpController, mBackgroundExecutor);
             mStrongAuthTracker = KeyguardUpdateMonitorTest.this.mStrongAuthTracker;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 3330d1e..6199181 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -93,6 +93,8 @@
                 mMockPluginManager, mMockColorExtractor, mMockContentResolver,
                 mMockCurrentUserObserable, mMockSettingsWrapper, mFakeDockManager);
 
+        mClockManager.addBuiltinClock(() -> new BubbleClockController(
+                getContext().getResources(), inflater, mMockColorExtractor));
         mClockManager.addOnClockChangedListener(mMockListener1);
         mClockManager.addOnClockChangedListener(mMockListener2);
         reset(mMockListener1, mMockListener2);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
index ffe8c28..471149c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ExpandHelperTest.java
@@ -23,7 +23,6 @@
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.annotation.UiThreadTest;
@@ -33,7 +32,6 @@
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -52,7 +50,7 @@
     public void setUp() throws Exception {
         mDependency.injectMockDependency(KeyguardUpdateMonitor.class);
         mDependency.injectMockDependency(NotificationMediaManager.class);
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         Context context = getContext();
         mRow = new NotificationTestHelper(context, mDependency).createRow();
         mCallback = mock(ExpandHelper.Callback.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
index 8d11b54..c912b67 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
@@ -35,7 +35,6 @@
 import android.app.NotificationManager;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.Looper;
 import android.os.UserHandle;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
@@ -75,8 +74,8 @@
 
     @Before
     public void setUp() throws Exception {
-        // assume the TestLooper is the main looper for these tests
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        // allow the TestLooper to be asserted as the main thread these tests
+        allowTestableLooperAsMainThread();
 
         MockitoAnnotations.initMocks(this);
         mFsc = new ForegroundServiceController(mEntryManager, mAppOpsController, mMainHandler);
@@ -93,7 +92,7 @@
     public void testAppOpsChangedCalledFromBgThread() {
         try {
             // WHEN onAppOpChanged is called from a different thread than the MainLooper
-            com.android.systemui.util.Assert.sMainLooper = Looper.getMainLooper();
+            disallowTestableLooperAsMainThread();
             NotificationEntry entry = createFgEntry();
             mFsc.onAppOpChanged(
                     AppOpsManager.OP_CAMERA,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
index fc331d6..689eed9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ImageWallpaperTest.java
@@ -77,7 +77,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
         mEventCountdown = new CountDownLatch(1);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
index c85d600..7ac5443 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
@@ -25,6 +25,7 @@
 import android.os.ParcelFileDescriptor;
 import android.testing.DexmakerShareClassLoaderRule;
 import android.testing.LeakCheck;
+import android.testing.TestableLooper;
 import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
@@ -32,7 +33,6 @@
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.systemui.classifier.FalsingManagerFake;
 import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.util.Assert;
 
 import org.junit.After;
 import org.junit.Before;
@@ -86,11 +86,24 @@
     public void SysuiTeardown() {
         InstrumentationRegistry.registerInstance(mRealInstrumentation,
                 InstrumentationRegistry.getArguments());
-        // Reset the assert's main looper.
-        Assert.sMainLooper = Looper.getMainLooper();
+        // Reset the assert's testable looper to null.
+        disallowTestableLooperAsMainThread();
         SystemUIFactory.cleanup();
     }
 
+    /**
+     * Tests are run on the TestableLooper; however, there are parts of SystemUI that assert that
+     * the code is run from the main looper. Therefore, we allow the TestableLooper to pass these
+     * assertions since in a test, the TestableLooper is essentially the MainLooper.
+     */
+    protected void allowTestableLooperAsMainThread() {
+        com.android.systemui.util.Assert.setTestableLooper(TestableLooper.get(this).getLooper());
+    }
+
+    protected void disallowTestableLooperAsMainThread() {
+        com.android.systemui.util.Assert.setTestableLooper(null);
+    }
+
     protected LeakCheck getLeakCheck() {
         return null;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
index daea7a7..5e4f971 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/BubbleControllerTest.java
@@ -203,7 +203,8 @@
         // Bubbles get added to status bar window view
         mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController, mColorExtractor);
+                mConfigurationController, mKeyguardBypassController, mColorExtractor,
+                mDumpController);
         mNotificationShadeWindowController.setNotificationShadeView(
                 mSuperStatusBarViewFactory.getNotificationShadeWindowView());
         mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
index b412ca5..6677b80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/bubbles/NewNotifPipelineBubbleControllerTest.java
@@ -197,7 +197,8 @@
         // Bubbles get added to status bar window view
         mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController, mColorExtractor);
+                mConfigurationController, mKeyguardBypassController, mColorExtractor,
+                mDumpController);
         mNotificationShadeWindowController.setNotificationShadeView(
                 mSuperStatusBarViewFactory.getNotificationShadeWindowView());
         mNotificationShadeWindowController.attach();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
index 44454d9..e5ab9be 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/classifier/brightline/DistanceClassifierTest.java
@@ -60,10 +60,10 @@
         mClassifier.onTouchEvent(appendDownEvent(1, 1));
         assertThat(mClassifier.isFalseTouch(), is(true));
 
-        mClassifier.onTouchEvent(appendMoveEvent(1, 2));
+        mClassifier.onTouchEvent(appendMoveEvent(1, 40));
         assertThat(mClassifier.isFalseTouch(), is(true));
 
-        mClassifier.onTouchEvent(appendUpEvent(1, 40));
+        mClassifier.onTouchEvent(appendUpEvent(1, 80));
         assertThat(mClassifier.isFalseTouch(), is(false));
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
index 40075c8..02bfc19e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsBindingControllerImplTest.kt
@@ -45,7 +45,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
-class ControlsBindingControllerTest : SysuiTestCase() {
+class ControlsBindingControllerImplTest : SysuiTestCase() {
 
     companion object {
         fun <T> any(): T = Mockito.any<T>()
@@ -95,7 +95,7 @@
 
         assertEquals(1, providers.size)
         val provider = providers.first()
-        verify(provider).maybeBindAndLoad(callback)
+        verify(provider).maybeBindAndLoad(any())
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
index ddd6b12..a3e59e5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ControlsProviderLifecycleManagerTest.kt
@@ -19,7 +19,6 @@
 import android.content.ComponentName
 import android.os.UserHandle
 import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
 import android.service.controls.IControlsSubscriber
 import android.service.controls.actions.ControlAction
@@ -32,13 +31,13 @@
 import org.junit.After
 import org.junit.Assert.assertEquals
 import org.junit.Assert.assertFalse
-import org.junit.Assert.assertNull
 import org.junit.Assert.assertTrue
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
 import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyString
 import org.mockito.ArgumentMatchers.eq
 import org.mockito.Captor
@@ -54,8 +53,6 @@
     @Mock
     private lateinit var actionCallbackService: IControlsActionCallback.Stub
     @Mock
-    private lateinit var loadCallbackService: IControlsLoadCallback.Stub
-    @Mock
     private lateinit var subscriberService: IControlsSubscriber.Stub
     @Mock
     private lateinit var service: IControlsProvider.Stub
@@ -85,7 +82,6 @@
         manager = ControlsProviderLifecycleManager(
                 context,
                 executor,
-                loadCallbackService,
                 actionCallbackService,
                 subscriberService,
                 UserHandle.of(0),
@@ -113,31 +109,29 @@
 
     @Test
     fun testMaybeBindAndLoad() {
-        manager.maybeBindAndLoad(loadCallback)
+        manager.maybeBindAndLoad(subscriberService)
 
-        verify(service).load(loadCallbackService)
+        verify(service).load(subscriberService)
 
         assertTrue(mContext.isBound(componentName))
-        assertEquals(loadCallback, manager.lastLoadCallback)
     }
 
     @Test
     fun testMaybeUnbind_bindingAndCallback() {
-        manager.maybeBindAndLoad(loadCallback)
+        manager.maybeBindAndLoad(subscriberService)
 
         manager.unbindService()
         assertFalse(mContext.isBound(componentName))
-        assertNull(manager.lastLoadCallback)
     }
 
     @Test
     fun testMaybeBindAndLoad_timeout() {
-        manager.maybeBindAndLoad(loadCallback)
+        manager.maybeBindAndLoad(subscriberService)
 
         executor.advanceClockToLast()
         executor.runAllReady()
 
-        verify(loadCallback).error(anyString())
+        verify(subscriberService).onError(any(), anyString())
     }
 
     @Test
@@ -160,4 +154,4 @@
                 eq(actionCallbackService))
         assertEquals(action, wrapperCaptor.getValue().getWrappedAction())
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
index 9e7ce06..cd82844 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/controller/ServiceWrapperTest.kt
@@ -18,7 +18,6 @@
 
 import android.os.RemoteException
 import android.service.controls.IControlsActionCallback
-import android.service.controls.IControlsLoadCallback
 import android.service.controls.IControlsProvider
 import android.service.controls.IControlsSubscriber
 import android.service.controls.IControlsSubscription
@@ -56,9 +55,6 @@
     private lateinit var subscriber: IControlsSubscriber
 
     @Mock
-    private lateinit var loadCallback: IControlsLoadCallback
-
-    @Mock
     private lateinit var actionCallback: IControlsActionCallback
 
     @Captor
@@ -81,16 +77,16 @@
 
     @Test
     fun testLoad_happyPath() {
-        val result = wrapper.load(loadCallback)
+        val result = wrapper.load(subscriber)
 
         assertTrue(result)
-        verify(service).load(loadCallback)
+        verify(service).load(subscriber)
     }
 
     @Test
     fun testLoad_error() {
         `when`(service.load(any())).thenThrow(exception)
-        val result = wrapper.load(loadCallback)
+        val result = wrapper.load(subscriber)
 
         assertFalse(result)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index acc30d9..9a707caa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -18,24 +18,30 @@
 
 import static android.view.WindowManagerPolicyConstants.OFF_BECAUSE_OF_USER;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.admin.DevicePolicyManager;
+import android.app.trust.TrustManager;
+import android.os.PowerManager;
+import android.os.PowerManager.WakeLock;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.systemui.DumpController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.classifier.FalsingManagerFake;
-import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.util.concurrency.FakeExecutor;
@@ -60,6 +66,9 @@
     private @Mock NotificationShadeWindowController mNotificationShadeWindowController;
     private @Mock BroadcastDispatcher mBroadcastDispatcher;
     private @Mock DismissCallbackRegistry mDismissCallbackRegistry;
+    private @Mock DumpController mDumpController;
+    private @Mock PowerManager mPowerManager;
+    private @Mock TrustManager mTrustManager;
     private FakeExecutor mUiBgExecutor = new FakeExecutor(new FakeSystemClock());
 
     private FalsingManagerFake mFalsingManager;
@@ -69,24 +78,33 @@
         MockitoAnnotations.initMocks(this);
         mFalsingManager = new FalsingManagerFake();
 
-        mDependency.injectTestDependency(FalsingManager.class, mFalsingManager);
-        mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mUpdateMonitor);
-
         when(mLockPatternUtils.getDevicePolicyManager()).thenReturn(mDevicePolicyManager);
+        when(mPowerManager.newWakeLock(anyInt(), any())).thenReturn(mock(WakeLock.class));
 
-        TestableLooper.get(this).runWithLooper(() -> {
-            mViewMediator = new KeyguardViewMediator(
-                    mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
-                    mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager,
-                    mDismissCallbackRegistry, mUiBgExecutor);
-        });
+        mViewMediator = new KeyguardViewMediator(
+                mContext, mFalsingManager, mLockPatternUtils, mBroadcastDispatcher,
+                mNotificationShadeWindowController, () -> mStatusBarKeyguardViewManager,
+                mDismissCallbackRegistry, mUpdateMonitor, mDumpController, mUiBgExecutor,
+                mPowerManager, mTrustManager);
+        mViewMediator.start();
     }
 
     @Test
     public void testOnGoingToSleep_UpdatesKeyguardGoingAway() {
-        mViewMediator.start();
         mViewMediator.onStartedGoingToSleep(OFF_BECAUSE_OF_USER);
         verify(mUpdateMonitor).setKeyguardGoingAway(false);
         verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean());
     }
+
+    @Test
+    public void testRegisterDumpable() {
+        verify(mDumpController).registerDumpable(eq(mViewMediator));
+        verify(mNotificationShadeWindowController, never()).setKeyguardGoingAway(anyBoolean());
+    }
+
+    @Test
+    public void testKeyguardGone_notGoingaway() {
+        mViewMediator.mViewMediatorCallback.keyguardGone();
+        verify(mNotificationShadeWindowController).setKeyguardGoingAway(eq(false));
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt
new file mode 100644
index 0000000..75be74b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/CellSignalStateTest.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.systemui.qs.carrier
+
+import android.testing.AndroidTestingRunner
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import org.junit.Assert.assertNotSame
+import org.junit.Assert.assertSame
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class CellSignalStateTest : SysuiTestCase() {
+
+    @Test
+    fun testChangeVisibility_sameObject() {
+        val c = CellSignalState()
+
+        val other = c.changeVisibility(c.visible)
+
+        assertSame(c, other)
+    }
+
+    @Test
+    fun testChangeVisibility_otherObject() {
+        val c = CellSignalState()
+
+        val other = c.changeVisibility(!c.visible)
+
+        assertNotSame(c, other)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSCarrierGroupControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
similarity index 98%
rename from packages/SystemUI/tests/src/com/android/systemui/qs/QSCarrierGroupControllerTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
index 715087d..fa02231 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSCarrierGroupControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierGroupControllerTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.qs;
+package com.android.systemui.qs.carrier;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
new file mode 100644
index 0000000..022dc84
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/carrier/QSCarrierTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.systemui.qs.carrier;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+import android.view.LayoutInflater;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class QSCarrierTest extends SysuiTestCase {
+
+    private QSCarrier mQSCarrier;
+    private TestableLooper mTestableLooper;
+
+    @Before
+    public void setUp() throws Exception {
+        mTestableLooper = TestableLooper.get(this);
+        LayoutInflater inflater = LayoutInflater.from(mContext);
+        mTestableLooper.runWithLooper(() ->
+                mQSCarrier = (QSCarrier) inflater.inflate(R.layout.qs_carrier, null));
+    }
+
+    @Test
+    public void testUpdateState_first() {
+        CellSignalState c = new CellSignalState(true, 0, "", "", false);
+
+        assertTrue(mQSCarrier.updateState(c));
+    }
+
+    @Test
+    public void testUpdateState_same() {
+        CellSignalState c = new CellSignalState(true, 0, "", "", false);
+
+        assertTrue(mQSCarrier.updateState(c));
+        assertFalse(mQSCarrier.updateState(c));
+    }
+
+    @Test
+    public void testUpdateState_changed() {
+        CellSignalState c = new CellSignalState(true, 0, "", "", false);
+
+        assertTrue(mQSCarrier.updateState(c));
+
+        CellSignalState other = c.changeVisibility(false);
+
+        assertTrue(mQSCarrier.updateState(other));
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
new file mode 100644
index 0000000..e8e98b4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/ScreenRecordTileTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.systemui.qs.tiles;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.service.quicksettings.Tile;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.Dependency;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.screenrecord.RecordingController;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+@SmallTest
+public class ScreenRecordTileTest extends SysuiTestCase {
+
+    @Mock
+    private RecordingController mController;
+    @Mock
+    private QSTileHost mHost;
+
+    private TestableLooper mTestableLooper;
+    private ScreenRecordTile mTile;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTestableLooper = TestableLooper.get(this);
+        mDependency.injectTestDependency(Dependency.BG_LOOPER, mTestableLooper.getLooper());
+        mController = mDependency.injectMockDependency(RecordingController.class);
+
+        when(mHost.getContext()).thenReturn(mContext);
+
+        mTile = new ScreenRecordTile(mHost, mController);
+    }
+
+    // Test that the tile is inactive and labeled correctly when the controller is neither starting
+    // or recording, and that clicking on the tile in this state brings up the record prompt
+    @Test
+    public void testNotActive() {
+        when(mController.isStarting()).thenReturn(false);
+        when(mController.isRecording()).thenReturn(false);
+
+        mTile.refreshState();
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_INACTIVE, mTile.getState().state);
+        assertTrue(mTile.getState().secondaryLabel.toString().equals(
+                mContext.getString(R.string.quick_settings_screen_record_start)));
+
+        mTile.handleClick();
+        verify(mController, times(1)).launchRecordPrompt();
+    }
+
+    // Test that the tile is active and labeled correctly when the controller is starting
+    @Test
+    public void testIsStarting() {
+        when(mController.isStarting()).thenReturn(true);
+        when(mController.isRecording()).thenReturn(false);
+
+        mTile.refreshState();
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
+        assertTrue(mTile.getState().secondaryLabel.toString().endsWith("..."));
+    }
+
+    // Test that the tile cancels countdown if it is clicked when the controller is starting
+    @Test
+    public void testCancelRecording() {
+        when(mController.isStarting()).thenReturn(true);
+        when(mController.isRecording()).thenReturn(false);
+
+        mTile.handleClick();
+
+        verify(mController, times(1)).cancelCountdown();
+    }
+
+    // Test that the tile is active and labeled correctly when the controller is recording
+    @Test
+    public void testIsRecording() {
+        when(mController.isStarting()).thenReturn(false);
+        when(mController.isRecording()).thenReturn(true);
+
+        mTile.refreshState();
+        mTestableLooper.processAllMessages();
+
+        assertEquals(Tile.STATE_ACTIVE, mTile.getState().state);
+        assertTrue(mTile.getState().secondaryLabel.toString().equals(
+                mContext.getString(R.string.quick_settings_screen_record_stop)));
+    }
+
+    // Test that the tile stops the recording if it is clicked when the controller is recording
+    @Test
+    public void testStopRecording() {
+        when(mController.isStarting()).thenReturn(false);
+        when(mController.isRecording()).thenReturn(true);
+
+        mTile.handleClick();
+
+        verify(mController, times(1)).stopRecording();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
new file mode 100644
index 0000000..b877c7f
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/screenrecord/RecordingControllerTest.java
@@ -0,0 +1,124 @@
+/*
+ * 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.systemui.screenrecord;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import static org.mockito.Mockito.verify;
+
+import android.app.PendingIntent;
+import android.os.Looper;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+/**
+ * Tests for exception handling and  bitmap configuration in adding smart actions to Screenshot
+ * Notification.
+ */
+public class RecordingControllerTest extends SysuiTestCase {
+
+    @Mock
+    RecordingController.RecordingStateChangeCallback mCallback;
+
+    RecordingController mController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mController = new RecordingController(mContext);
+        mController.addCallback(mCallback);
+    }
+
+    // Test that when a countdown in progress is cancelled, the controller goes from starting to not
+    // starting, and notifies listeners.
+    @Test
+    public void testCancelCountdown() {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        mController.startCountdown(100, 10, null, null);
+
+        assertTrue(mController.isStarting());
+        assertFalse(mController.isRecording());
+
+        mController.cancelCountdown();
+
+        assertFalse(mController.isStarting());
+        assertFalse(mController.isRecording());
+
+        verify(mCallback).onCountdownEnd();
+    }
+
+    // Test that when recording is started, the start intent is sent and listeners are notified.
+    @Test
+    public void testStartRecording() throws PendingIntent.CanceledException {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        PendingIntent startIntent = Mockito.mock(PendingIntent.class);
+        mController.startCountdown(0, 0, startIntent, null);
+
+        verify(mCallback).onCountdownEnd();
+        verify(startIntent).send();
+    }
+
+    // Test that when recording is stopped, the stop intent is sent and listeners are notified.
+    @Test
+    public void testStopRecording() throws PendingIntent.CanceledException {
+        if (Looper.myLooper() == null) {
+            Looper.prepare();
+        }
+
+        PendingIntent startIntent = Mockito.mock(PendingIntent.class);
+        PendingIntent stopIntent = Mockito.mock(PendingIntent.class);
+
+        mController.startCountdown(0, 0, startIntent, stopIntent);
+        mController.stopRecording();
+
+        assertFalse(mController.isStarting());
+        assertFalse(mController.isRecording());
+        verify(stopIntent).send();
+        verify(mCallback).onRecordingEnd();
+    }
+
+    // Test that updating the controller state works and notifies listeners.
+    @Test
+    public void testUpdateState() {
+        mController.updateState(true);
+        assertTrue(mController.isRecording());
+        verify(mCallback).onRecordingStart();
+
+        mController.updateState(false);
+        assertFalse(mController.isRecording());
+        verify(mCallback).onRecordingEnd();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java b/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
deleted file mode 100644
index 0b871e4..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/screenshot/ScreenshotStubActivity.java
+++ /dev/null
@@ -1,33 +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.systemui.screenshot;
-
-import android.app.Activity;
-import android.os.Bundle;
-
-import com.android.systemui.tests.R;
-
-/**
- * A stub activity used in {@link ScreenshotTest}.
- */
-public class ScreenshotStubActivity extends Activity {
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.main);
-    }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
index 1d4b4be..581d795 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/KeyguardIndicationControllerTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -124,7 +125,7 @@
         mContext.addMockSystemService(Context.TRUST_SERVICE, mock(TrustManager.class));
         mContext.addMockSystemService(Context.FINGERPRINT_SERVICE, mock(FingerprintManager.class));
 
-        when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mKeyguardUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mKeyguardUpdateMonitor.isScreenOn()).thenReturn(true);
         when(mKeyguardUpdateMonitor.isUserUnlocked(anyInt())).thenReturn(true);
         when(mIndicationArea.findViewById(R.id.keyguard_indication_text)).thenReturn(mTextView);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
index 72e6df2..a27c085 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/MediaArtworkProcessorTest.kt
@@ -16,15 +16,14 @@
 
 package com.android.systemui.statusbar
 
-import com.google.common.truth.Truth.assertThat
-
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.Color
-import android.graphics.Point
 import android.testing.AndroidTestingRunner
+import android.view.WindowManager.LayoutParams.TYPE_NOTIFICATION_SHADE
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
 import org.junit.After
 import org.junit.Before
 import org.junit.Test
@@ -32,6 +31,7 @@
 
 private const val WIDTH = 200
 private const val HEIGHT = 200
+private const val WINDOW_TYPE = TYPE_NOTIFICATION_SHADE
 
 @RunWith(AndroidTestingRunner::class)
 @SmallTest
@@ -46,10 +46,10 @@
     fun setUp() {
         processor = MediaArtworkProcessor()
 
-        val point = Point()
-        context.display.getSize(point)
-        screenWidth = point.x
-        screenHeight = point.y
+        val size = processor.getWindowSize(context, WINDOW_TYPE)
+
+        screenWidth = size.width
+        screenHeight = size.height
     }
 
     @After
@@ -63,7 +63,7 @@
         val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
         Canvas(artwork).drawColor(Color.BLUE)
         // WHEN the background is created from the artwork
-        val background = processor.processArtwork(context, artwork)!!
+        val background = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
         // THEN the background has the size of the screen that has been downsamples
         assertThat(background.height).isLessThan(screenHeight)
         assertThat(background.width).isLessThan(screenWidth)
@@ -76,8 +76,8 @@
         val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
         Canvas(artwork).drawColor(Color.BLUE)
         // WHEN the background is processed twice
-        val background1 = processor.processArtwork(context, artwork)!!
-        val background2 = processor.processArtwork(context, artwork)!!
+        val background1 = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
+        val background2 = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
         // THEN the two bitmaps are the same
         // Note: This is currently broken and trying to use caching causes issues
         assertThat(background1).isNotSameAs(background2)
@@ -89,7 +89,7 @@
         val artwork = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ALPHA_8)
         Canvas(artwork).drawColor(Color.BLUE)
         // WHEN the background is created from the artwork
-        val background = processor.processArtwork(context, artwork)!!
+        val background = processor.processArtwork(context, artwork, WINDOW_TYPE)!!
         // THEN the background has Config ARGB_8888
         assertThat(background.config).isEqualTo(Bitmap.Config.ARGB_8888)
     }
@@ -102,7 +102,7 @@
         // AND the artwork is recycled
         artwork.recycle()
         // WHEN the background is created from the artwork
-        val background = processor.processArtwork(context, artwork)
+        val background = processor.processArtwork(context, artwork, WINDOW_TYPE)
         // THEN the processed bitmap is null
         assertThat(background).isNull()
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 6d83ac3..644ed3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -85,7 +85,7 @@
                 Dependency.get(NotificationLockscreenUserManager.class);
         NotificationViewHierarchyManager viewHierarchyManager =
                 Dependency.get(NotificationViewHierarchyManager.class);
-        entryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
+        entryManager.setUpWithPresenter(mPresenter);
         entryManager.addNotificationEntryListener(mEntryListener);
         gutsManager.setUpWithPresenter(mPresenter, mListContainer,
                 mCheckSaveListener, mOnSettingsClickListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
index 60163f2..8e87e0a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationViewHierarchyManagerTest.java
@@ -54,7 +54,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.util.Assert;
 
 import com.google.android.collect.Lists;
 
@@ -90,7 +89,7 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         mTestableLooper = TestableLooper.get(this);
-        Assert.sMainLooper = mTestableLooper.getLooper();
+        allowTestableLooperAsMainThread();
         mHandler = Handler.createAsync(mTestableLooper.getLooper());
 
         mDependency.injectTestDependency(NotificationEntryManager.class, mEntryManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
index 9d667a9..0a38f16 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/AboveShelfObserverTest.java
@@ -21,7 +21,6 @@
 
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.widget.FrameLayout;
 
@@ -46,7 +45,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mNotificationTestHelper = new NotificationTestHelper(getContext(), mDependency);
         mHostLayout = new FrameLayout(getContext());
         mObserver = new AboveShelfObserver(mHostLayout);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
index f1fba79..98f12ce 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationEntryManagerTest.java
@@ -52,74 +52,55 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.ArraySet;
-import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.statusbar.NotificationVisibility;
-import com.android.internal.util.NotificationMessagingUtil;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.FeatureFlags;
 import com.android.systemui.statusbar.NotificationLifetimeExtender;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.NotificationRemoveInterceptor;
 import com.android.systemui.statusbar.RankingBuilder;
-import com.android.systemui.statusbar.RemoteInputController;
 import com.android.systemui.statusbar.SmartReplyController;
-import com.android.systemui.statusbar.StatusBarIconView;
 import com.android.systemui.statusbar.notification.NotificationEntryManager.KeyguardEnvironment;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
-import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRowController;
-import com.android.systemui.statusbar.notification.row.NotifBindPipeline;
-import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.row.RowContentBindParams;
-import com.android.systemui.statusbar.notification.row.RowContentBindStage;
+import com.android.systemui.statusbar.notification.row.NotificationEntryManagerInflationTest;
 import com.android.systemui.statusbar.notification.row.RowInflaterTask;
-import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
-import com.android.systemui.util.Assert;
 import com.android.systemui.util.leak.LeakDetector;
-import com.android.systemui.util.time.FakeSystemClock;
 
-import org.junit.After;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.ArgumentCaptor;
 import org.mockito.InOrder;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
-import org.mockito.stubbing.Answer;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
 
+/**
+ * Unit tests for {@link NotificationEntryManager}. This test will not test any interactions with
+ * inflation. Instead, for functional inflation tests, see
+ * {@link NotificationEntryManagerInflationTest}.
+ */
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper()
@@ -130,17 +111,11 @@
     @Mock private NotificationPresenter mPresenter;
     @Mock private KeyguardEnvironment mEnvironment;
     @Mock private ExpandableNotificationRow mRow;
-    @Mock private NotificationListContainer mListContainer;
     @Mock private NotificationEntryListener mEntryListener;
     @Mock private NotificationRemoveInterceptor mRemoveInterceptor;
-    @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
     @Mock private HeadsUpManager mHeadsUpManager;
     @Mock private RankingMap mRankingMap;
-    @Mock private RemoteInputController mRemoteInputController;
-    @Mock private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
-    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
     @Mock private NotificationGroupManager mGroupManager;
-    @Mock private NotificationGutsManager mGutsManager;
     @Mock private NotificationRemoteInputManager mRemoteInputManager;
     @Mock private DeviceProvisionedController mDeviceProvisionedController;
     @Mock private RowInflaterTask mAsyncInflationTask;
@@ -148,18 +123,12 @@
     @Mock private FeatureFlags mFeatureFlags;
     @Mock private LeakDetector mLeakDetector;
     @Mock private NotificationMediaManager mNotificationMediaManager;
-    @Mock private ExpandableNotificationRowComponent.Builder
-            mExpandableNotificationRowComponentBuilder;
-    @Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
-    @Mock private FalsingManager mFalsingManager;
-    @Mock private KeyguardBypassController mKeyguardBypassController;
-    @Mock private StatusBarStateController mStatusBarStateController;
+    @Mock private NotificationRowBinder mNotificationRowBinder;
 
     private int mId;
     private NotificationEntry mEntry;
     private StatusBarNotification mSbn;
-    private TestableNotificationEntryManager mEntryManager;
-    private CountDownLatch mCountDownLatch;
+    private NotificationEntryManager mEntryManager;
 
     private void setUserSentiment(String key, int sentiment) {
         doAnswer(invocationOnMock -> {
@@ -203,41 +172,16 @@
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(SmartReplyController.class);
 
-        mCountDownLatch = new CountDownLatch(1);
-
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mDependency.injectTestDependency(Dependency.MAIN_HANDLER,
                 Handler.createAsync(TestableLooper.get(this).getLooper()));
-        when(mRemoteInputManager.getController()).thenReturn(mRemoteInputController);
-        when(mListContainer.getViewParentForNotification(any())).thenReturn(
-                new FrameLayout(mContext));
 
         mEntry = createNotification();
         mSbn = mEntry.getSbn();
 
-        mEntry.expandedIcon = mock(StatusBarIconView.class);
-
-        RowContentBindStage bindStage = mock(RowContentBindStage.class);
-        when(bindStage.getStageParams(any())).thenReturn(new RowContentBindParams());
-        NotificationRowBinderImpl notificationRowBinder =
-                new NotificationRowBinderImpl(mContext,
-                        new NotificationMessagingUtil(mContext),
-                        mRemoteInputManager,
-                        mLockscreenUserManager,
-                        mock(NotifBindPipeline.class),
-                        bindStage,
-                        true, /* allowLongPress */
-                        mKeyguardBypassController,
-                        mStatusBarStateController,
-                        mGroupManager,
-                        mGutsManager,
-                        mNotificationInterruptionStateProvider,
-                        RowInflaterTask::new,
-                        mExpandableNotificationRowComponentBuilder);
-
         when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
         when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
-        mEntryManager = new TestableNotificationEntryManager(
+        mEntryManager = new NotificationEntryManager(
                 mLogger,
                 mGroupManager,
                 new NotificationRankingManager(
@@ -251,161 +195,54 @@
                         mock(HighPriorityProvider.class)),
                 mEnvironment,
                 mFeatureFlags,
-                () -> notificationRowBinder,
+                () -> mNotificationRowBinder,
                 () -> mRemoteInputManager,
                 mLeakDetector,
                 mock(ForegroundServiceDismissalFeatureController.class)
         );
-        mEntryManager.setUpWithPresenter(mPresenter, mListContainer, mHeadsUpManager);
+        mEntryManager.setUpWithPresenter(mPresenter);
         mEntryManager.addNotificationEntryListener(mEntryListener);
         mEntryManager.addNotificationRemoveInterceptor(mRemoveInterceptor);
 
-        notificationRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
-        notificationRowBinder.setInflationCallback(mEntryManager);
-        notificationRowBinder.setNotificationClicker(mock(NotificationClicker.class));
-
-        setUserSentiment(
-                mEntry.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
-
-        ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
-                ArgumentCaptor.forClass(ExpandableNotificationRow.class);
-        when(mExpandableNotificationRowComponentBuilder
-                .expandableNotificationRow(viewCaptor.capture()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-        when(mExpandableNotificationRowComponentBuilder
-                .notificationEntry(any()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-        when(mExpandableNotificationRowComponentBuilder
-                .onDismissRunnable(any()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-        when(mExpandableNotificationRowComponentBuilder
-                .inflationCallback(any()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-        when(mExpandableNotificationRowComponentBuilder
-                .rowContentBindStage(any()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-        when(mExpandableNotificationRowComponentBuilder
-                .onExpandClickListener(any()))
-                .thenReturn(mExpandableNotificationRowComponentBuilder);
-
-        when(mExpandableNotificationRowComponentBuilder.build())
-                .thenReturn(mExpandableNotificationRowComponent);
-        when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
-                .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
-                        new ExpandableNotificationRowController(
-                                viewCaptor.getValue(),
-                                mock(ActivatableNotificationViewController.class),
-                                mNotificationMediaManager,
-                                mock(PluginManager.class),
-                                new FakeSystemClock(),
-                                "FOOBAR", "FOOBAR",
-                                mKeyguardBypassController,
-                                mGroupManager,
-                                bindStage,
-                                mock(NotificationLogger.class),
-                                mHeadsUpManager,
-                                mPresenter,
-                                mStatusBarStateController,
-                                mEntryManager,
-                                mGutsManager,
-                                true,
-                                null,
-                                mFalsingManager
-                        ));
+        setUserSentiment(mSbn.getKey(), Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
-    @After
-    public void tearDown() {
-        // CLEAN UP inflation tasks so they don't callback in a future test
-        mEntry.abortTask();
-    }
-
-    // TODO: These tests are closer to functional tests and we should move them to their own file.
-    // and also strip some of the verifies that make the test too complex
     @Test
-    @Ignore
-    public void testAddNotification() throws Exception {
-        TestableLooper.get(this).processAllMessages();
-
-        doAnswer(invocation -> {
-            mCountDownLatch.countDown();
-            return null;
-        }).when(mBindCallback).onBindRow(any(), any(), any(), any());
-
-        // Post on main thread, otherwise we will be stuck waiting here for the inflation finished
-        // callback forever, since it won't execute until the tests ends.
+    public void testAddNotification_setsUserSentiment() {
         mEntryManager.addNotification(mSbn, mRankingMap);
-        TestableLooper.get(this).processMessages(1);
-        assertTrue(mCountDownLatch.await(10, TimeUnit.SECONDS));
-        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
 
-        // Check that no inflation error occurred.
-        verify(mEntryListener, never()).onInflationError(any(), any());
-
-        // Row inflation:
         ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
                 NotificationEntry.class);
-        verify(mBindCallback).onBindRow(entryCaptor.capture(), any(), eq(mSbn), any());
+        verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
         NotificationEntry entry = entryCaptor.getValue();
-        verify(mRemoteInputManager).bindRow(entry.getRow());
 
-        // Row content inflation:
-        verify(mEntryListener).onNotificationAdded(entry);
-        verify(mPresenter).updateNotificationViews();
-
-        assertEquals(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()), entry);
-        assertNotNull(entry.getRow());
-        assertEquals(mEntry.getUserSentiment(),
-                Ranking.USER_SENTIMENT_NEUTRAL);
+        assertEquals(entry.getUserSentiment(), Ranking.USER_SENTIMENT_NEUTRAL);
     }
 
     @Test
-    @Ignore
-    public void testUpdateNotification() throws Exception {
-        TestableLooper.get(this).processAllMessages();
-
+    public void testUpdateNotification_updatesUserSentiment() {
         mEntryManager.addActiveNotificationForTest(mEntry);
-
         setUserSentiment(
                 mEntry.getKey(), Ranking.USER_SENTIMENT_NEGATIVE);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
-        TestableLooper.get(this).processMessages(1);
-        // Wait for content update.
-        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
 
-        verify(mEntryListener, never()).onInflationError(any(), any());
-
-        verify(mEntryListener).onPreEntryUpdated(mEntry);
-        verify(mPresenter).updateNotificationViews();
-        verify(mEntryListener).onPostEntryUpdated(mEntry);
-
-        assertNotNull(mEntry.getRow());
-        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE,
-                mEntry.getUserSentiment());
+        assertEquals(Ranking.USER_SENTIMENT_NEGATIVE, mEntry.getUserSentiment());
     }
 
     @Test
-    @Ignore
     public void testUpdateNotification_prePostEntryOrder() throws Exception {
         TestableLooper.get(this).processAllMessages();
 
         mEntryManager.addActiveNotificationForTest(mEntry);
 
         mEntryManager.updateNotification(mSbn, mRankingMap);
-        TestableLooper.get(this).processMessages(1);
-        // Wait for content update.
-        assertTrue(mEntryManager.getCountDownLatch().await(10, TimeUnit.SECONDS));
-
-        verify(mEntryListener, never()).onInflationError(any(), any());
 
         // Ensure that update callbacks happen in correct order
         InOrder order = inOrder(mEntryListener, mPresenter, mEntryListener);
         order.verify(mEntryListener).onPreEntryUpdated(mEntry);
         order.verify(mPresenter).updateNotificationViews();
         order.verify(mEntryListener).onPostEntryUpdated(mEntry);
-
-        assertNotNull(mEntry.getRow());
     }
 
     @Test
@@ -415,8 +252,6 @@
 
         mEntryManager.removeNotification(mSbn.getKey(), mRankingMap, UNDEFINED_DISMISS_REASON);
 
-        verify(mEntryListener, never()).onInflationError(any(), any());
-
         verify(mPresenter).updateNotificationViews();
         verify(mEntryListener).onEntryRemoved(
                 eq(mEntry), any(), eq(false) /* removedByUser */);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
index 1116a33..97e0a31 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationFilterTest.java
@@ -32,7 +32,6 @@
 import android.os.Bundle;
 import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.annotation.UiThreadTest;
@@ -79,7 +78,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
         when(mMockStatusBarNotification.getUid()).thenReturn(UID_NORMAL);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
index b3d0d22..6388fe1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationSectionsFeatureManagerTest.kt
@@ -63,7 +63,7 @@
                 DeviceConfig.NAMESPACE_SYSTEMUI, NOTIFICATIONS_USE_PEOPLE_FILTERING, "true", false)
 
         assertTrue("People filtering should be enabled", manager!!.isFilteringEnabled())
-        assertTrue("Expecting 3 buckets when people filtering is enabled",
-                manager!!.getNumberOfBuckets() == 3)
+        assertTrue("Expecting 4 buckets when people filtering is enabled",
+                manager!!.getNumberOfBuckets() == 4)
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
index 0e730e5..d522f90 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/TestableNotificationEntryManager.kt
@@ -22,11 +22,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationRankingManager
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
 import com.android.systemui.statusbar.phone.NotificationGroupManager
 import com.android.systemui.util.leak.LeakDetector
-
 import java.util.concurrent.CountDownLatch
 
 /**
@@ -53,11 +50,9 @@
     }
 
     fun setUpForTest(
-        presenter: NotificationPresenter?,
-        listContainer: NotificationListContainer?,
-        headsUpManager: HeadsUpManagerPhone?
+        presenter: NotificationPresenter?
     ) {
-        super.setUpWithPresenter(presenter, listContainer, headsUpManager)
+        super.setUpWithPresenter(presenter)
     }
 
     fun setActiveNotificationList(activeList: List<NotificationEntry>) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 12e9d31..605b59e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -77,7 +77,6 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionLogger;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifDismissInterceptor;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -129,7 +128,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
 
         when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(true);
         when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(true);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index c6b496d..f11c42b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_ALERTING
 import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager.BUCKET_SILENT
 import com.android.systemui.statusbar.phone.NotificationGroupManager
@@ -42,6 +43,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mockito.mock
+import org.mockito.Mockito.`when` as whenever
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -52,18 +54,20 @@
     }
     private lateinit var personNotificationIdentifier: PeopleNotificationIdentifier
     private lateinit var rankingManager: TestableNotificationRankingManager
+    private lateinit var sectionsManager: NotificationSectionsFeatureManager
 
     @Before
     fun setup() {
         personNotificationIdentifier =
                 mock(PeopleNotificationIdentifier::class.java)
+        sectionsManager = mock(NotificationSectionsFeatureManager::class.java)
         rankingManager = TestableNotificationRankingManager(
                 lazyMedia,
                 mock(NotificationGroupManager::class.java),
                 mock(HeadsUpManager::class.java),
                 mock(NotificationFilter::class.java),
                 mock(NotificationEntryManagerLogger::class.java),
-                mock(NotificationSectionsFeatureManager::class.java),
+                sectionsManager,
                 personNotificationIdentifier,
                 HighPriorityProvider(personNotificationIdentifier)
         )
@@ -145,6 +149,97 @@
     }
 
     @Test
+    fun testSort_headsUp_trumpsPeople() {
+        whenever(sectionsManager.isFilteringEnabled()).thenReturn(true)
+        val aN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val a = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(aN)
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+
+        whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(true)
+        whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(true)
+
+        val bN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val b = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg2")
+                .setOpPkg("pkg2")
+                .setTag("tag")
+                .setNotification(bN)
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        b.row = mock(ExpandableNotificationRow::class.java).also {
+            whenever(it.isHeadsUp).thenReturn(true)
+        }
+
+        whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(false)
+        whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(false)
+
+        assertEquals(listOf(b, a), rankingManager.updateRanking(null, listOf(a, b), "test"))
+    }
+
+    @Test
+    fun testSort_importantPeople() {
+        whenever(sectionsManager.isFilteringEnabled()).thenReturn(true)
+        val aN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val a = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg")
+                .setOpPkg("pkg")
+                .setTag("tag")
+                .setNotification(aN)
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(false)
+        whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(true)
+
+        val bN = Notification.Builder(mContext, "test")
+                .setStyle(Notification.MessagingStyle(""))
+                .build()
+        val b = NotificationEntryBuilder()
+                .setImportance(IMPORTANCE_HIGH)
+                .setPkg("pkg2")
+                .setOpPkg("pkg2")
+                .setTag("tag")
+                .setNotification(bN)
+                .setChannel(NotificationChannel("test", "", IMPORTANCE_DEFAULT))
+                .setUser(mContext.getUser())
+                .setOverrideGroupKey("")
+                .build()
+        whenever(personNotificationIdentifier.isImportantPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(false)
+        whenever(personNotificationIdentifier.isPeopleNotification(a.sbn, a.ranking))
+                .thenReturn(true)
+
+        assertEquals(
+                listOf(b, a),
+                rankingManager.updateRanking(null, listOf(a, b), "test"))
+    }
+
+    @Test
     fun testSort_properlySetsAlertingBucket() {
         val notif = Notification.Builder(mContext, "test") .build()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 27ca18c..e570ab8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -51,7 +51,6 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifPromoter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSection;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
-import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.FakeSystemClock;
 
 import org.junit.Before;
@@ -101,7 +100,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
 
         mListBuilder = new ShadeListBuilder(mSystemClock, mLogger, mock(DumpController.class));
         mListBuilder.setOnRenderListListener(mOnRenderListListener);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
index eb1af7c..67b1aad 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ForegroundCoordinatorTest.java
@@ -44,7 +44,6 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender;
-import com.android.systemui.util.Assert;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
@@ -84,7 +83,7 @@
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
 
         mForegroundCoordinator =
                 new ForegroundCoordinator(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
index 867a9b9..abce8b5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/people/PeopleHubViewControllerTest.kt
@@ -43,7 +43,7 @@
 
     @JvmField @Rule val mockito: MockitoRule = MockitoJUnit.rule()
 
-    @Mock private lateinit var mockViewBoundary: PeopleHubSectionFooterViewBoundary
+    @Mock private lateinit var mockViewBoundary: PeopleHubViewBoundary
     @Mock private lateinit var mockActivityStarter: ActivityStarter
 
     @Test
@@ -67,7 +67,7 @@
                 return mockSubscription
             }
         }
-        val adapter = PeopleHubSectionFooterViewAdapterImpl(fakeFactoryDataSource)
+        val adapter = PeopleHubViewAdapterImpl(fakeFactoryDataSource)
 
         adapter.bindView(mockViewBoundary)
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
index a891810..e960185 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRowTest.java
@@ -39,7 +39,6 @@
 import android.app.AppOpsManager;
 import android.app.NotificationChannel;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.util.ArraySet;
 import android.view.NotificationHeaderView;
@@ -79,7 +78,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         mGroupRow = mNotificationTestHelper.createGroup();
         mGroupRow.setHeadsUpAnimatingAwayListener(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
index a8c438a..481bac2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -49,7 +49,6 @@
 import com.android.systemui.bubbles.BubbleController;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -75,7 +74,7 @@
 
     @Before
     public void setUp() {
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
         mDependency.injectMockDependency(BubbleController.class);
         when(mGutsManager.openGuts(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
index 27b263f..138ea39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationConversationInfoTest.java
@@ -21,6 +21,8 @@
 import static android.app.NotificationManager.IMPORTANCE_HIGH;
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.print.PrintManager.PRINT_SPOOLER_PACKAGE_NAME;
+import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
+import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
 import static android.view.View.GONE;
 import static android.view.View.VISIBLE;
 
@@ -55,6 +57,7 @@
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Icon;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -449,6 +452,7 @@
 
     @Test
     public void testBindNotification_bubbleActionVisibleWhenCanBubble()  {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         mNotificationInfo.bindNotification(
                 mShortcutManager,
                 mLauncherApps,
@@ -469,7 +473,8 @@
     }
 
     @Test
-    public void testBindNotification_bubbleActionVisibleWhenCannotBubble()  {
+    public void testBindNotification_bubbleAction_noBubbleMetadata()  {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         mNotificationInfo.bindNotification(
                 mShortcutManager,
                 mLauncherApps,
@@ -490,6 +495,28 @@
     }
 
     @Test
+    public void testBindNotification_bubbleActionGloballyOff()  {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+        mNotificationInfo.bindNotification(
+                mShortcutManager,
+                mLauncherApps,
+                mMockPackageManager,
+                mMockINotificationManager,
+                mVisualStabilityManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mBubbleEntry,
+                null,
+                null,
+                null,
+                mIconFactory,
+                true);
+
+        View bubbleView = mNotificationInfo.findViewById(R.id.bubble);
+        assertEquals(View.GONE, bubbleView.getVisibility());
+    }
+
+    @Test
     public void testAddToHome() throws Exception {
         when(mShortcutManager.isRequestPinShortcutSupported()).thenReturn(true);
 
@@ -550,6 +577,7 @@
 
     @Test
     public void testBubble_promotesBubble() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         mNotificationChannel.setAllowBubbles(false);
         mConversationChannel.setAllowBubbles(false);
 
@@ -584,6 +612,7 @@
 
     @Test
     public void testBubble_demotesBubble() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         mBubbleEntry.getSbn().getNotification().flags |= FLAG_BUBBLE;
 
         mNotificationInfo.bindNotification(
@@ -617,6 +646,7 @@
 
     @Test
     public void testBubble_noChannelChange() throws Exception {
+        Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
         mNotificationInfo.bindNotification(
                 mShortcutManager,
                 mLauncherApps,
@@ -645,7 +675,11 @@
     }
 
     @Test
-    public void testFavorite_favorite() throws Exception {
+    public void testFavorite_favorite_noBubble() throws Exception {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                BUBBLE_IMPORTANT_CONVERSATIONS, 0);
+        mNotificationChannel.setAllowBubbles(false);
+        mConversationChannel.setAllowBubbles(false);
         mNotificationInfo.bindNotification(
                 mShortcutManager,
                 mLauncherApps,
@@ -673,6 +707,44 @@
         verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
                 anyString(), anyInt(), captor.capture());
         assertTrue(captor.getValue().isImportantConversation());
+        assertFalse(captor.getValue().canBubble());
+        verify(mBubbleController, never()).onUserCreatedBubbleFromNotification(mEntry);
+    }
+
+    @Test
+    public void testFavorite_favorite_bubble() throws Exception {
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                BUBBLE_IMPORTANT_CONVERSATIONS, 1);
+        mNotificationChannel.setAllowBubbles(false);
+        mConversationChannel.setAllowBubbles(false);
+        mNotificationInfo.bindNotification(
+                mShortcutManager,
+                mLauncherApps,
+                mMockPackageManager,
+                mMockINotificationManager,
+                mVisualStabilityManager,
+                TEST_PACKAGE_NAME,
+                mNotificationChannel,
+                mEntry,
+                null,
+                null,
+                null,
+                mIconFactory,
+                true);
+
+        ImageButton fave = mNotificationInfo.findViewById(R.id.fave);
+        assertEquals(mContext.getString(R.string.notification_conversation_unfavorite),
+                fave.getContentDescription().toString());
+
+        fave.performClick();
+        mTestableLooper.processAllMessages();
+
+        ArgumentCaptor<NotificationChannel> captor =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), anyInt(), captor.capture());
+        assertTrue(captor.getValue().isImportantConversation());
+        assertTrue(captor.getValue().canBubble());
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
new file mode 100644
index 0000000..ac40808
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationEntryManagerInflationTest.java
@@ -0,0 +1,385 @@
+/*
+ * 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.systemui.statusbar.notification.row;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+
+import static junit.framework.Assert.assertNotNull;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.Notification;
+import android.os.Handler;
+import android.service.notification.NotificationListenerService;
+import android.service.notification.NotificationListenerService.Ranking;
+import android.service.notification.StatusBarNotification;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.util.NotificationMessagingUtil;
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.FeatureFlags;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.SbnBuilder;
+import com.android.systemui.statusbar.SmartReplyController;
+import com.android.systemui.statusbar.notification.ForegroundServiceDismissalFeatureController;
+import com.android.systemui.statusbar.notification.NotificationClicker;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.NotificationEntryManagerLogger;
+import com.android.systemui.statusbar.notification.NotificationFilter;
+import com.android.systemui.statusbar.notification.NotificationInterruptionStateProvider;
+import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.NotificationRankingManager;
+import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier;
+import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.notification.row.dagger.ExpandableNotificationRowComponent;
+import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
+import com.android.systemui.statusbar.phone.NotificationGroupManager;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
+import com.android.systemui.statusbar.policy.SmartReplyConstants;
+import com.android.systemui.util.leak.LeakDetector;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.mockito.stubbing.Answer;
+
+/**
+ * Functional tests for notification inflation from {@link NotificationEntryManager}.
+ */
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper(setAsMainLooper = true)
+public class NotificationEntryManagerInflationTest extends SysuiTestCase {
+
+    private static final String TEST_TITLE = "Title";
+    private static final String TEST_TEXT = "Text";
+    private static final long TIMEOUT_TIME = 10000;
+    private static final Runnable TIMEOUT_RUNNABLE = () -> {
+        throw new RuntimeException("Timed out waiting to inflate");
+    };
+
+    @Mock private NotificationPresenter mPresenter;
+    @Mock private NotificationEntryManager.KeyguardEnvironment mEnvironment;
+    @Mock private NotificationListContainer mListContainer;
+    @Mock private NotificationEntryListener mEntryListener;
+    @Mock private NotificationRowBinderImpl.BindRowCallback mBindCallback;
+    @Mock private HeadsUpManager mHeadsUpManager;
+    @Mock private NotificationInterruptionStateProvider mNotificationInterruptionStateProvider;
+    @Mock private NotificationLockscreenUserManager mLockscreenUserManager;
+    @Mock private NotificationGutsManager mGutsManager;
+    @Mock private NotificationRemoteInputManager mRemoteInputManager;
+    @Mock private NotificationMediaManager mNotificationMediaManager;
+    @Mock private ExpandableNotificationRowComponent.Builder
+            mExpandableNotificationRowComponentBuilder;
+    @Mock private ExpandableNotificationRowComponent mExpandableNotificationRowComponent;
+    @Mock private FalsingManager mFalsingManager;
+    @Mock private KeyguardBypassController mKeyguardBypassController;
+    @Mock private StatusBarStateController mStatusBarStateController;
+
+    @Mock private NotificationGroupManager mGroupManager;
+    @Mock private FeatureFlags mFeatureFlags;
+    @Mock private LeakDetector mLeakDetector;
+
+    @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
+    @Mock private NotificationRowComponent.Builder mNotificationRowComponentBuilder;
+
+    private StatusBarNotification mSbn;
+    private NotificationListenerService.RankingMap mRankingMap;
+    private NotificationEntryManager mEntryManager;
+    private NotificationRowBinderImpl mRowBinder;
+    private Handler mHandler;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        mDependency.injectMockDependency(SmartReplyController.class);
+
+        mHandler = Handler.createAsync(TestableLooper.get(this).getLooper());
+
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(R.drawable.ic_person)
+                .setContentTitle(TEST_TITLE)
+                .setContentText(TEST_TEXT)
+                .build();
+        mSbn = new SbnBuilder()
+                .setNotification(notification)
+                .build();
+
+        when(mFeatureFlags.isNewNotifPipelineEnabled()).thenReturn(false);
+        when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
+
+        mEntryManager = new NotificationEntryManager(
+                mock(NotificationEntryManagerLogger.class),
+                mGroupManager,
+                new NotificationRankingManager(
+                        () -> mock(NotificationMediaManager.class),
+                        mGroupManager,
+                        mHeadsUpManager,
+                        mock(NotificationFilter.class),
+                        mock(NotificationEntryManagerLogger.class),
+                        mock(NotificationSectionsFeatureManager.class),
+                        mock(PeopleNotificationIdentifier.class),
+                        mock(HighPriorityProvider.class)),
+                mEnvironment,
+                mFeatureFlags,
+                () -> mRowBinder,
+                () -> mRemoteInputManager,
+                mLeakDetector,
+                mock(ForegroundServiceDismissalFeatureController.class)
+        );
+
+        NotifRemoteViewCache cache = new NotifRemoteViewCacheImpl(mEntryManager);
+        NotifBindPipeline pipeline = new NotifBindPipeline(
+                mEntryManager,
+                mock(NotifBindPipelineLogger.class));
+        NotificationContentInflater binder = new NotificationContentInflater(
+                cache,
+                mRemoteInputManager,
+                () -> mock(SmartReplyConstants.class),
+                () -> mock(SmartReplyController.class));
+        RowContentBindStage stage = new RowContentBindStage(
+                binder,
+                mock(NotifInflationErrorManager.class),
+                mock(RowContentBindStageLogger.class));
+        pipeline.setStage(stage);
+
+        ArgumentCaptor<ExpandableNotificationRow> viewCaptor =
+                ArgumentCaptor.forClass(ExpandableNotificationRow.class);
+        when(mExpandableNotificationRowComponentBuilder
+                .expandableNotificationRow(viewCaptor.capture()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+        when(mExpandableNotificationRowComponentBuilder
+                .notificationEntry(any()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+        when(mExpandableNotificationRowComponentBuilder
+                .onDismissRunnable(any()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+        when(mExpandableNotificationRowComponentBuilder
+                .inflationCallback(any()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+        when(mExpandableNotificationRowComponentBuilder
+                .rowContentBindStage(any()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+        when(mExpandableNotificationRowComponentBuilder
+                .onExpandClickListener(any()))
+                .thenReturn(mExpandableNotificationRowComponentBuilder);
+
+        when(mExpandableNotificationRowComponentBuilder.build())
+                .thenReturn(mExpandableNotificationRowComponent);
+        when(mExpandableNotificationRowComponent.getExpandableNotificationRowController())
+                .thenAnswer((Answer<ExpandableNotificationRowController>) invocation ->
+                        new ExpandableNotificationRowController(
+                                viewCaptor.getValue(),
+                                mock(ActivatableNotificationViewController.class),
+                                mNotificationMediaManager,
+                                mock(PluginManager.class),
+                                new FakeSystemClock(),
+                                "FOOBAR", "FOOBAR",
+                                mKeyguardBypassController,
+                                mGroupManager,
+                                stage,
+                                mock(NotificationLogger.class),
+                                mHeadsUpManager,
+                                mPresenter,
+                                mStatusBarStateController,
+                                mEntryManager,
+                                mGutsManager,
+                                true,
+                                null,
+                                mFalsingManager
+                        ));
+
+        when(mNotificationRowComponentBuilder.activatableNotificationView(any()))
+                .thenReturn(mNotificationRowComponentBuilder);
+        when(mNotificationRowComponentBuilder.build()).thenReturn(
+                () -> mActivatableNotificationViewController);
+
+        mRowBinder = new NotificationRowBinderImpl(
+                mContext,
+                new NotificationMessagingUtil(mContext),
+                mRemoteInputManager,
+                mLockscreenUserManager,
+                pipeline,
+                stage,
+                true, /* allowLongPress */
+                mock(KeyguardBypassController.class),
+                mock(StatusBarStateController.class),
+                mGroupManager,
+                mGutsManager,
+                mNotificationInterruptionStateProvider,
+                RowInflaterTask::new,
+                mExpandableNotificationRowComponentBuilder);
+
+        mEntryManager.setUpWithPresenter(mPresenter);
+        mEntryManager.addNotificationEntryListener(mEntryListener);
+
+        mRowBinder.setUpWithPresenter(mPresenter, mListContainer, mBindCallback);
+        mRowBinder.setInflationCallback(mEntryManager);
+        mRowBinder.setNotificationClicker(mock(NotificationClicker.class));
+
+        Ranking ranking = new Ranking();
+        ranking.populate(
+                mSbn.getKey(),
+                0,
+                false,
+                0,
+                0,
+                IMPORTANCE_DEFAULT,
+                null,
+                null,
+                null,
+                null,
+                null,
+                true,
+                Ranking.USER_SENTIMENT_NEUTRAL,
+                false,
+                -1,
+                false,
+                null,
+                null,
+                false,
+                false,
+                false);
+        mRankingMap = new NotificationListenerService.RankingMap(new Ranking[] {ranking});
+
+        TestableLooper.get(this).processAllMessages();
+    }
+
+    @After
+    public void cleanUp() {
+        // Don't leave anything on main thread
+        TestableLooper.get(this).processAllMessages();
+    }
+
+    @Test
+    public void testAddNotification() {
+        // WHEN a notification is added
+        mEntryManager.addNotification(mSbn, mRankingMap);
+        ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
+                NotificationEntry.class);
+        verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
+        NotificationEntry entry = entryCaptor.getValue();
+
+        // Wait for inflation
+        // row inflation, system notification, remote views, contracted view
+        waitForMessages(4);
+
+        // THEN the notification has its row inflated
+        assertNotNull(entry.getRow());
+        assertNotNull(entry.getRow().getPrivateLayout().getContractedChild());
+
+        // THEN inflation callbacks are called
+        verify(mBindCallback).onBindRow(eq(entry), any(), eq(mSbn), any());
+        verify(mEntryListener, never()).onInflationError(any(), any());
+        verify(mEntryListener).onEntryInflated(entry);
+        verify(mEntryListener).onNotificationAdded(entry);
+
+        // THEN the notification is active
+        assertNotNull(mEntryManager.getActiveNotificationUnfiltered(mSbn.getKey()));
+
+        // THEN we update the presenter
+        verify(mPresenter).updateNotificationViews();
+    }
+
+    @Test
+    public void testUpdateNotification() {
+        // GIVEN a notification already added
+        mEntryManager.addNotification(mSbn, mRankingMap);
+        ArgumentCaptor<NotificationEntry> entryCaptor = ArgumentCaptor.forClass(
+                NotificationEntry.class);
+        verify(mEntryListener).onPendingEntryAdded(entryCaptor.capture());
+        NotificationEntry entry = entryCaptor.getValue();
+        waitForMessages(4);
+
+        Mockito.reset(mEntryListener);
+        Mockito.reset(mPresenter);
+
+        // WHEN the notification is updated
+        mEntryManager.updateNotification(mSbn, mRankingMap);
+
+        // Wait for inflation
+        // remote views, contracted view
+        waitForMessages(2);
+
+        // THEN the notification has its row and inflated
+        assertNotNull(entry.getRow());
+
+        // THEN inflation callbacks are called
+        verify(mEntryListener, never()).onInflationError(any(), any());
+        verify(mEntryListener).onEntryReinflated(entry);
+
+        // THEN we update the presenter
+        verify(mPresenter).updateNotificationViews();
+    }
+
+    /**
+     * Wait for a certain number of messages to finish before continuing, timing out if they never
+     * occur.
+     *
+     * As part of the inflation pipeline, the main thread is forced to deal with several callbacks
+     * due to the nature of the API used (generally because they're {@link android.os.AsyncTask}
+     * callbacks). In order, these are
+     *
+     * 1) Callback after row inflation. See {@link RowInflaterTask}.
+     * 2) Callback checking if row is system notification. See
+     *    {@link ExpandableNotificationRow#setEntry}
+     * 3) Callback after remote views are created. See
+     *    {@link NotificationContentInflater.AsyncInflationTask}.
+     * 4-6) Callback after each content view is inflated/rebound from remote view. See
+     *      {@link NotificationContentInflater#applyRemoteView} and {@link InflationFlag}.
+     *
+     * Depending on the test, only some of these will be necessary. For example, generally, not
+     * every content view is inflated or the row may not be inflated if one already exists.
+     *
+     * Currently, the burden is on the developer to figure these out until we have a much more
+     * test-friendly way of executing inflation logic (i.e. pass in an executor).
+     */
+    private void waitForMessages(int numMessages) {
+        mHandler.postDelayed(TIMEOUT_RUNNABLE, TIMEOUT_TIME);
+        TestableLooper.get(this).processMessages(numMessages);
+        mHandler.removeCallbacks(TIMEOUT_RUNNABLE);
+    }
+
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index bbb6723..54c0bde 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -74,7 +74,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Ignore;
@@ -118,7 +117,7 @@
     @Before
     public void setUp() {
         mTestableLooper = TestableLooper.get(this);
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mDependency.injectTestDependency(DeviceProvisionedController.class,
                 mDeviceProvisionedController);
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
new file mode 100644
index 0000000..7f48cd1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInlineImageResolverTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.systemui.statusbar.notification.row;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotSame;
+import static org.junit.Assert.assertSame;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+
+import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
+import android.net.Uri;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class NotificationInlineImageResolverTest extends SysuiTestCase {
+
+    NotificationInlineImageResolver mResolver;
+    Bitmap mBitmap;
+    BitmapDrawable mBitmapDrawable;
+    Uri mUri;
+
+    @Before
+    public void setup() {
+        mResolver = spy(new NotificationInlineImageResolver(mContext, null));
+        mBitmap = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888);
+        mBitmapDrawable = new BitmapDrawable(mContext.getResources(), mBitmap);
+        mUri = mock(Uri.class);
+    }
+
+    @Test
+    public void refreshMaxImageSizes() {
+        assertNotEquals("Starts different height", mResolver.mMaxImageHeight, 20);
+        assertNotEquals("Starts different width", mResolver.mMaxImageWidth, 15);
+
+        doReturn(20).when(mResolver).getMaxImageHeight();
+        doReturn(15).when(mResolver).getMaxImageWidth();
+
+        mResolver.updateMaxImageSizes();
+
+        assertEquals("Height matches new config", mResolver.mMaxImageHeight, 20);
+        assertEquals("Width matches new config", mResolver.mMaxImageWidth, 15);
+    }
+
+    @Test
+    public void resolveImage_sizeTooBig() throws IOException {
+        doReturn(mBitmapDrawable).when(mResolver).resolveImageInternal(mUri);
+        mResolver.mMaxImageHeight = 5;
+        mResolver.mMaxImageWidth = 5;
+
+        // original bitmap size is 10x10
+        BitmapDrawable resolved = (BitmapDrawable) mResolver.resolveImage(mUri);
+        Bitmap resolvedBitmap = resolved.getBitmap();
+        assertEquals("Bitmap width reduced", 5, resolvedBitmap.getWidth());
+        assertEquals("Bitmap height reduced", 5, resolvedBitmap.getHeight());
+        assertNotSame("Bitmap replaced", resolvedBitmap, mBitmap);
+    }
+
+    @Test
+    public void resolveImage_sizeOK() throws IOException {
+        doReturn(mBitmapDrawable).when(mResolver).resolveImageInternal(mUri);
+        mResolver.mMaxImageWidth = 15;
+        mResolver.mMaxImageHeight = 15;
+
+        // original bitmap size is 10x10
+        BitmapDrawable resolved = (BitmapDrawable) mResolver.resolveImage(mUri);
+        Bitmap resolvedBitmap = resolved.getBitmap();
+        assertEquals("Bitmap width unchanged", 10, resolvedBitmap.getWidth());
+        assertEquals("Bitmap height unchanged", 10, resolvedBitmap.getHeight());
+        assertSame("Bitmap not replaced", resolvedBitmap, mBitmap);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
index 9a52ee8..5a89fc4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationTestHelper.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.ExpansionLogger;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow.OnExpandClickListener;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.statusbar.phone.ConfigurationControllerImpl;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
@@ -102,8 +103,8 @@
         mStatusBarStateController = mock(StatusBarStateController.class);
         mGroupManager = new NotificationGroupManager(mStatusBarStateController);
         mHeadsUpManager = new HeadsUpManagerPhone(mContext, mStatusBarStateController,
-                mock(KeyguardBypassController.class));
-        mHeadsUpManager.setUp(null, mGroupManager, null, null);
+                mock(KeyguardBypassController.class), mock(NotificationGroupManager.class),
+                mock(ConfigurationControllerImpl.class));
         mGroupManager.setHeadsUpManager(mHeadsUpManager);
 
         NotificationContentInflater contentBinder = new NotificationContentInflater(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
index 0790cb7..b661b28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationCustomViewWrapperTest.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification.row.wrapper;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.RemoteViews;
@@ -43,7 +42,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mRow = new NotificationTestHelper(mContext, mDependency).createRow();
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
index 038eff7..69e4f22 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationMediaTemplateViewWrapperTest.java
@@ -26,7 +26,6 @@
 import android.media.session.MediaSession;
 import android.media.session.PlaybackState;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.RemoteViews;
@@ -64,7 +63,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
 
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
index 9567f33..830e8d9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/wrapper/NotificationViewWrapperTest.java
@@ -20,7 +20,6 @@
 
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.LinearLayout;
@@ -31,7 +30,6 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -48,7 +46,7 @@
 
     @Before
     public void setup() throws Exception {
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mView = mock(View.class);
         mRow = new NotificationTestHelper(getContext(), mDependency).createRow();
         mNotificationViewWrapper = new TestableNotificationViewWrapper(mContext, mView, mRow);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
index 1773175..a2029c7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationChildrenContainerTest.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.NotificationHeaderView;
 import android.view.View;
@@ -44,7 +43,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         mNotificationTestHelper = new NotificationTestHelper(mContext, mDependency);
         mGroup = mNotificationTestHelper.createGroup();
         mChildrenContainer = mGroup.getChildrenContainer();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
index 2d1bc78..ba2b946 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManagerTest.java
@@ -24,7 +24,6 @@
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 
 import androidx.test.filters.SmallTest;
@@ -66,7 +65,7 @@
         mRoundnessManager = new NotificationRoundnessManager(
                 mBypassController,
                 new NotificationSectionsFeatureManager(new DeviceConfigProxy(), mContext));
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
         mFirst = testHelper.createRow();
         mFirst.setHeadsUpAnimatingAwayListener(animatingAway
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index 51f214d..abfbcd9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -45,8 +45,7 @@
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.notification.NotificationSectionsFeatureManager;
-import com.android.systemui.statusbar.notification.people.PeopleHubSectionFooterViewAdapter;
-import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
+import com.android.systemui.statusbar.notification.people.PeopleHubViewAdapter;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationViewController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.dagger.NotificationRowComponent;
@@ -71,7 +70,7 @@
     @Mock private ActivityStarterDelegate mActivityStarterDelegate;
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private ConfigurationController mConfigurationController;
-    @Mock private PeopleHubSectionFooterViewAdapter mPeopleHubAdapter;
+    @Mock private PeopleHubViewAdapter mPeopleHubAdapter;
     @Mock private NotificationSectionsFeatureManager mSectionsFeatureManager;
     @Mock private NotificationRowComponent mNotificationRowComponent;
     @Mock private ActivatableNotificationViewController mActivatableNotificationViewController;
@@ -90,18 +89,8 @@
                         mStatusBarStateController,
                         mConfigurationController,
                         mPeopleHubAdapter,
-                        mSectionsFeatureManager,
-                        new NotificationRowComponent.Builder() {
-                    @Override
-                    public NotificationRowComponent.Builder activatableNotificationView(
-                            ActivatableNotificationView view) {
-                        return this;
-                    }
-
-                    @Override
-                    public NotificationRowComponent build() {
-                        return mNotificationRowComponent;
-                    }});
+                        mSectionsFeatureManager
+                );
         // Required in order for the header inflation to work properly
         when(mNssl.generateLayoutParams(any(AttributeSet.class)))
                 .thenReturn(new ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 9ccee75..0cb6585 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -144,7 +144,7 @@
     @Before
     @UiThreadTest
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
 
         mOriginalInterruptionModelSetting = Settings.Secure.getInt(mContext.getContentResolver(),
                 NOTIFICATION_NEW_INTERRUPTION_MODEL, 0);
@@ -185,7 +185,7 @@
                 mock(LeakDetector.class),
                 mock(ForegroundServiceDismissalFeatureController.class)
         );
-        mEntryManager.setUpForTest(mock(NotificationPresenter.class), null, mHeadsUpManager);
+        mEntryManager.setUpForTest(mock(NotificationPresenter.class));
         when(mFeatureFlags.isNewNotifPipelineRenderingEnabled()).thenReturn(false);
 
         NotificationShelf notificationShelf = mock(NotificationShelf.class);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 769b774..813923d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -97,7 +97,8 @@
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
         when(mUpdateMonitor.isDeviceInteractive()).thenReturn(true);
         when(mKeyguardStateController.isFaceAuthEnabled()).thenReturn(true);
-        when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true);
+        when(mKeyguardBypassController.onBiometricAuthenticated(any(), anyBoolean()))
+                .thenReturn(true);
         when(mKeyguardBypassController.canPlaySubtleWindowAnimations()).thenReturn(true);
         mContext.addMockSystemService(PowerManager.class, mPowerManager);
         mDependency.injectTestDependency(NotificationMediaManager.class, mMediaManager);
@@ -112,11 +113,28 @@
 
     @Test
     public void onBiometricAuthenticated_whenFingerprintAndBiometricsDisallowed_showBouncer() {
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(true /* isStrongBiometric */))
+                .thenReturn(false);
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FINGERPRINT);
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
         verify(mStatusBarKeyguardViewManager).showBouncer(eq(false));
         verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(),
                 anyFloat());
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER);
+    }
+
+    @Test
+    public void onBiometricAuthenticated_whenFingerprint_nonStrongBioDisallowed_showBouncer() {
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(false /* isStrongBiometric */))
+                .thenReturn(false);
+        mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
+                BiometricSourceType.FINGERPRINT, false /* isStrongBiometric */);
+        verify(mStatusBarKeyguardViewManager).showBouncer(eq(false));
+        verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(),
+                anyFloat());
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_SHOW_BOUNCER);
     }
 
     @Test
@@ -124,44 +142,60 @@
         reset(mUpdateMonitor);
         reset(mStatusBarKeyguardViewManager);
         when(mStatusBarKeyguardViewManager.isShowing()).thenReturn(true);
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mDozeScrimController.isPulsing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FINGERPRINT);
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
 
         verify(mKeyguardViewMediator).onWakeAndUnlocking();
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
     }
 
     @Test
     public void onBiometricAuthenticated_whenFingerprint_dismissKeyguard() {
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FINGERPRINT);
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
         verify(mShadeController).animateCollapsePanels(anyInt(), anyBoolean(), anyBoolean(),
                 anyFloat());
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_UNLOCK_COLLAPSING);
     }
 
     @Test
     public void onBiometricAuthenticated_whenFingerprintOnBouncer_dismissBouncer() {
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FINGERPRINT);
+                BiometricSourceType.FINGERPRINT, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
     }
 
     @Test
     public void onBiometricAuthenticated_whenFace_dontDismissKeyguard() {
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(),
                 anyBoolean(), anyFloat());
         verify(mStatusBarKeyguardViewManager, never()).notifyKeyguardAuthenticated(anyBoolean());
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_NONE);
     }
 
     @Test
@@ -169,13 +203,17 @@
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
 
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(),
                 anyBoolean(), anyFloat());
         verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_UNLOCK_FADING);
     }
 
     @Test
@@ -184,9 +222,11 @@
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
 
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         // Wake up before showing the bouncer
         verify(mStatusBarKeyguardViewManager, never()).showBouncer(eq(false));
@@ -202,9 +242,11 @@
         reset(mUpdateMonitor);
         mBiometricUnlockController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
 
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(false);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(false);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
         verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(),
@@ -215,23 +257,30 @@
 
     @Test
     public void onBiometricAuthenticated_whenFaceOnBouncer_dismissBouncer() {
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_DISMISS_BOUNCER);
     }
 
     @Test
     public void onBiometricAuthenticated_whenBypassOnBouncer_dismissBouncer() {
         reset(mKeyguardBypassController);
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
-        when(mKeyguardBypassController.onBiometricAuthenticated(any())).thenReturn(true);
+        when(mKeyguardBypassController.onBiometricAuthenticated(any(), anyBoolean()))
+                .thenReturn(true);
         when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
         assertThat(mBiometricUnlockController.getMode())
@@ -240,11 +289,13 @@
 
     @Test
     public void onBiometricAuthenticated_whenBypassOnBouncer_respectsCanPlaySubtleAnim() {
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
         when(mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mStatusBarKeyguardViewManager).notifyKeyguardAuthenticated(eq(false));
         assertThat(mBiometricUnlockController.getMode())
@@ -255,13 +306,17 @@
     public void onBiometricAuthenticated_whenFaceAndPulsing_dontDismissKeyguard() {
         reset(mUpdateMonitor);
         reset(mStatusBarKeyguardViewManager);
-        when(mUpdateMonitor.isUnlockingWithBiometricAllowed()).thenReturn(true);
+        when(mUpdateMonitor.isUnlockingWithBiometricAllowed(anyBoolean())).thenReturn(true);
         when(mDozeScrimController.isPulsing()).thenReturn(true);
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(UserHandle.USER_CURRENT,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
 
         verify(mShadeController, never()).animateCollapsePanels(anyInt(), anyBoolean(),
                 anyBoolean(), anyFloat());
+        assertThat(mBiometricUnlockController.getMode())
+                .isEqualTo(BiometricUnlockController.MODE_ONLY_WAKE);
     }
 
     @Test
@@ -270,8 +325,10 @@
         mBiometricUnlockController.onFinishedGoingToSleep(-1);
         verify(mHandler, never()).post(any());
 
+        // the value of isStrongBiometric doesn't matter here since we only care about the returned
+        // value of isUnlockingWithBiometricAllowed()
         mBiometricUnlockController.onBiometricAuthenticated(1 /* userId */,
-                BiometricSourceType.FACE);
+                BiometricSourceType.FACE, true /* isStrongBiometric */);
         mBiometricUnlockController.onFinishedGoingToSleep(-1);
         verify(mHandler).post(any());
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
index f71d0fc..a74657e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpAppearanceControllerTest.java
@@ -23,7 +23,6 @@
 import static org.mockito.Mockito.when;
 
 import android.testing.AndroidTestingRunner;
-import android.testing.TestableLooper;
 import android.testing.TestableLooper.RunWithLooper;
 import android.view.View;
 import android.widget.TextView;
@@ -69,7 +68,7 @@
 
     @Before
     public void setUp() throws Exception {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         NotificationTestHelper testHelper = new NotificationTestHelper(getContext(), mDependency);
         mFirst = testHelper.createRow();
         mDependency.injectTestDependency(DarkIconDispatcher.class, mDarkIconDispatcher);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
index 50d8bf0b0..6d642ec 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhoneTest.java
@@ -62,16 +62,21 @@
     @Mock private StatusBar mBar;
     @Mock private StatusBarStateController mStatusBarStateController;
     @Mock private KeyguardBypassController mBypassController;
+    @Mock private ConfigurationControllerImpl mConfigurationController;
     private boolean mLivesPastNormalTime;
 
     private final class TestableHeadsUpManagerPhone extends HeadsUpManagerPhone {
-        TestableHeadsUpManagerPhone(Context context, View notificationShadeWindowView,
-                NotificationGroupManager groupManager, StatusBar bar,
+        TestableHeadsUpManagerPhone(
+                Context context,
+                NotificationGroupManager groupManager,
                 VisualStabilityManager vsManager,
                 StatusBarStateController statusBarStateController,
-                KeyguardBypassController keyguardBypassController) {
-            super(context, statusBarStateController, keyguardBypassController);
-            setUp(notificationShadeWindowView, groupManager, bar, vsManager);
+                KeyguardBypassController keyguardBypassController,
+                ConfigurationController configurationController
+        ) {
+            super(context, statusBarStateController, keyguardBypassController,
+                    groupManager, configurationController);
+            setup(vsManager);
             mMinimumDisplayTime = TEST_MINIMUM_DISPLAY_TIME;
             mAutoDismissNotificationDecay = TEST_AUTO_DISMISS_TIME;
         }
@@ -91,8 +96,8 @@
         mDependency.injectMockDependency(BubbleController.class);
         mDependency.injectMockDependency(NotificationShadeWindowController.class);
         mDependency.injectMockDependency(ConfigurationController.class);
-        mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mNotificationShadeWindowView,
-                mGroupManager, mBar, mVSManager, mStatusBarStateController, mBypassController);
+        mHeadsUpManager = new TestableHeadsUpManagerPhone(mContext, mGroupManager, mVSManager,
+                mStatusBarStateController, mBypassController, mConfigurationController);
         super.setUp();
         mHeadsUpManager.mHandler = mTestHandler;
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
index 67b8e07..35971bd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardBouncerTest.java
@@ -96,7 +96,7 @@
 
     @Before
     public void setup() {
-        com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
         mDependency.injectTestDependency(KeyguardUpdateMonitor.class, mKeyguardUpdateMonitor);
         mDependency.injectTestDependency(KeyguardSecurityModel.class, mKeyguardSecurityModel);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
index 5fb7159..13bf38c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewTest.java
@@ -138,6 +138,8 @@
     @Mock
     private NotificationEntryManager mNotificationEntryManager;
     @Mock
+    private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+    @Mock
     private KeyguardStateController mKeyguardStateController;
     @Mock
     private DozeLog mDozeLog;
@@ -221,7 +223,7 @@
                 mDozeParameters, mCommandQueue, mVibratorHelper,
                 mLatencyTracker, mPowerManager, mAccessibilityManager, 0, mUpdateMonitor,
                 mMetricsLogger, mActivityManager, mZenModeController, mConfigurationController,
-                mFlingAnimationUtilsBuilder);
+                mFlingAnimationUtilsBuilder, mStatusBarTouchableRegionManager);
         mNotificationPanelViewController.initDependencies(mStatusBar, mGroupManager,
                 mNotificationShelf, mNotificationAreaController, mScrimController);
         mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
index 7d52df7..2782f3d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowControllerTest.java
@@ -32,6 +32,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.colorextraction.ColorExtractor;
+import com.android.systemui.DumpController;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
@@ -58,6 +59,7 @@
     @Mock private KeyguardBypassController mKeyguardBypassController;
     @Mock private SysuiColorExtractor mColorExtractor;
     @Mock ColorExtractor.GradientColors mGradientColors;
+    @Mock private DumpController mDumpController;
 
     private NotificationShadeWindowController mNotificationShadeWindowController;
 
@@ -69,7 +71,8 @@
 
         mNotificationShadeWindowController = new NotificationShadeWindowController(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
-                mConfigurationController, mKeyguardBypassController, mColorExtractor);
+                mConfigurationController, mKeyguardBypassController, mColorExtractor,
+                mDumpController);
         mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
 
         mNotificationShadeWindowController.attach();
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 2e6fbe7..408dfc0 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
@@ -36,7 +36,6 @@
 
 import android.animation.Animator;
 import android.app.AlarmManager;
-import android.content.res.Resources;
 import android.graphics.Color;
 import android.os.Handler;
 import android.testing.AndroidTestingRunner;
@@ -91,8 +90,6 @@
     @Mock
     LightBarController mLightBarController;
     @Mock
-    Resources mResources;
-    @Mock
     DelayedWakeLock.Builder mDelayedWakeLockBuilder;
     @Mock
     private DelayedWakeLock mWakeLock;
@@ -216,8 +213,7 @@
         when(mDockManager.isDocked()).thenReturn(false);
 
         mScrimController = new ScrimController(mLightBarController,
-                mDozeParamenters, mAlarmManager, mKeyguardStateController,
-                mResources, mDelayedWakeLockBuilder,
+                mDozeParamenters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
                 new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor, mSysuiColorExtractor,
                 mDockManager);
         mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index db17a6e..d81b8c2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -50,6 +50,7 @@
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -236,6 +237,7 @@
     @Mock private LightsOutNotifController mLightsOutNotifController;
     @Mock private ViewMediatorCallback mViewMediatorCallback;
     @Mock private DismissCallbackRegistry mDismissCallbackRegistry;
+    @Mock private StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
     @Mock private ScreenPinningRequest mScreenPinningRequest;
     @Mock private LockscreenLockIconController mLockscreenLockIconController;
     @Mock private StatusBarNotificationActivityStarter.Builder
@@ -255,7 +257,8 @@
         mDependency.injectTestDependency(NotificationFilter.class, mNotificationFilter);
 
         IPowerManager powerManagerService = mock(IPowerManager.class);
-        mPowerManager = new PowerManager(mContext, powerManagerService,
+        IThermalService thermalService = mock(IThermalService.class);
+        mPowerManager = new PowerManager(mContext, powerManagerService, thermalService,
                 Handler.createAsync(Looper.myLooper()));
 
         mNotificationInterruptionStateProvider =
@@ -397,7 +400,8 @@
                 mKeyguardDismissUtil,
                 mExtensionController,
                 mUserInfoControllerImpl,
-                mDismissCallbackRegistry);
+                mDismissCallbackRegistry,
+                mStatusBarTouchableRegionManager);
 
         when(mNotificationShadeWindowView.findViewById(R.id.lock_icon_container)).thenReturn(
                 mLockIconContainer);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 9a0e97a..a0d551c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -45,6 +45,7 @@
 import android.provider.Settings.Global;
 import android.telephony.CdmaEriInformation;
 import android.telephony.CellSignalStrength;
+import android.telephony.DisplayInfo;
 import android.telephony.NetworkRegistrationInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
@@ -96,6 +97,7 @@
     protected PhoneStateListener mPhoneStateListener;
     protected SignalStrength mSignalStrength;
     protected ServiceState mServiceState;
+    protected DisplayInfo mDisplayInfo;
     protected NetworkRegistrationInfo mFakeRegInfo;
     protected ConnectivityManager mMockCm;
     protected WifiManager mMockWm;
@@ -159,6 +161,7 @@
 
         mSignalStrength = mock(SignalStrength.class);
         mServiceState = mock(ServiceState.class);
+        mDisplayInfo = mock(DisplayInfo.class);
 
         mFakeRegInfo = new NetworkRegistrationInfo.Builder()
                 .setTransportType(TRANSPORT_TYPE_WWAN)
@@ -167,6 +170,9 @@
                 .build();
         doReturn(mFakeRegInfo).when(mServiceState)
                 .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mDisplayInfo).getNetworkType();
+        doReturn(DisplayInfo.OVERRIDE_NETWORK_TYPE_NONE).when(mDisplayInfo)
+                .getOverrideNetworkType();
 
         mEriInformation = new CdmaEriInformation(CdmaEriInformation.ERI_OFF,
                 CdmaEriInformation.ERI_ICON_MODE_NORMAL);
@@ -260,33 +266,6 @@
             NetworkCapabilities.TRANSPORT_CELLULAR, true, true);
     }
 
-    public void setupDefaultNr5GIconConfiguration() {
-        NetworkControllerImpl.Config.add5GIconMapping("connected_mmwave:5g_plus", mConfig);
-        NetworkControllerImpl.Config.add5GIconMapping("connected:5g", mConfig);
-    }
-
-    public void setupNr5GIconConfigurationForNotRestrictedRrcCon() {
-        NetworkControllerImpl.Config.add5GIconMapping("connected_mmwave:5g_plus", mConfig);
-        NetworkControllerImpl.Config.add5GIconMapping("connected:5g_plus", mConfig);
-        NetworkControllerImpl.Config.add5GIconMapping("not_restricted_rrc_con:5g", mConfig);
-    }
-
-    public void setupNr5GIconConfigurationForNotRestrictedRrcIdle() {
-        NetworkControllerImpl.Config.add5GIconMapping("connected_mmwave:5g_plus", mConfig);
-        NetworkControllerImpl.Config.add5GIconMapping("connected:5g_plus", mConfig);
-        NetworkControllerImpl.Config.add5GIconMapping("not_restricted_rrc_idle:5g", mConfig);
-    }
-
-    public void setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds() {
-        final int enableDisplayGraceTimeSec = 30;
-        NetworkControllerImpl.Config.setDisplayGraceTime(enableDisplayGraceTimeSec, mConfig);
-    }
-
-    public void setupDefaultNr5GIconDisplayGracePeriodTime_disabled() {
-        final int disableDisplayGraceTimeSec = 0;
-        NetworkControllerImpl.Config.setDisplayGraceTime(disableDisplayGraceTimeSec, mConfig);
-    }
-
     public void setConnectivityViaBroadcast(
         int networkType, boolean validated, boolean isConnected) {
         setConnectivityCommon(networkType, validated, isConnected);
@@ -369,6 +348,7 @@
     protected void updateServiceState() {
         Log.d(TAG, "Sending Service State: " + mServiceState);
         mPhoneStateListener.onServiceStateChanged(mServiceState);
+        mPhoneStateListener.onDisplayInfoChanged(mDisplayInfo);
     }
 
     public void updateCallState(int state) {
@@ -384,6 +364,7 @@
                 .build();
         when(mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN))
                 .thenReturn(fakeRegInfo);
+        when(mDisplayInfo.getNetworkType()).thenReturn(dataNetType);
         mPhoneStateListener.onDataConnectionStateChanged(dataState, dataNetType);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
index a906d9f..3eb0c44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
@@ -3,17 +3,13 @@
 import static android.telephony.AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
 import static android.telephony.NetworkRegistrationInfo.DOMAIN_PS;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyInt;
-import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
 import android.net.NetworkCapabilities;
 import android.os.Looper;
 import android.telephony.NetworkRegistrationInfo;
-import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.AndroidTestingRunner;
@@ -24,7 +20,6 @@
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Mockito;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -180,254 +175,6 @@
     }
 
     @Test
-    public void testNr5GIcon_NrNotRestrictedRrcCon_show5GIcon() {
-        setupNr5GIconConfigurationForNotRestrictedRrcCon();
-        setupDefaultSignal();
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        updateDataActivity(TelephonyManager.DATA_ACTIVITY_INOUT);
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyLastMobileDataIndicators(true, DEFAULT_SIGNAL_STRENGTH, TelephonyIcons.ICON_5G,
-                true, DEFAULT_QS_SIGNAL_STRENGTH, TelephonyIcons.ICON_5G, true, true);
-    }
-
-    @Test
-    public void testNr5GIcon_NrNotRestrictedRrcIdle_show5GIcon() {
-        setupNr5GIconConfigurationForNotRestrictedRrcIdle();
-        setupDefaultSignal();
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        updateDataActivity(TelephonyManager.DATA_ACTIVITY_DORMANT);
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_NOT_RESTRICTED);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-    }
-
-    @Test
-    public void testNr5GIcon_NrConnectedWithoutMMWave_show5GIcon() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultSignal();
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-    }
-
-    @Test
-    public void testNr5GIcon_NrConnectedWithMMWave_show5GPlusIcon() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultSignal();
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G_PLUS);
-    }
-
-    @Test
-    public void testNr5GIcon_NrRestricted_showLteIcon() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultSignal();
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_RESTRICTED);
-        mPhoneStateListener.onServiceStateChanged(mServiceState);
-
-        verifyDataIndicators(TelephonyIcons.ICON_LTE);
-    }
-
-    @Test
-    public void testNr5GIcon_displayGracePeriodTime_enabled() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-        mPhoneStateListener.onServiceStateChanged(mServiceState);
-
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        // While nrIconDisplayGracePeriodMs > 0 & is Nr5G, mIsShowingIconGracefully should be true
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        assertTrue(mConfig.nrIconDisplayGracePeriodMs > 0);
-        assertTrue(mMobileSignalController.mIsShowingIconGracefully);
-    }
-
-    @Test
-    public void testNr5GIcon_displayGracePeriodTime_disabled() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
-        setupDefaultSignal();
-
-        assertTrue(mConfig.nrIconDisplayGracePeriodMs == 0);
-
-        // While nrIconDisplayGracePeriodMs <= 0, mIsShowingIconGracefully should be false
-        setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-
-        assertFalse(mMobileSignalController.mIsShowingIconGracefully);
-    }
-
-    @Test
-    public void testNr5GIcon_enableDisplayGracePeriodTime_showIconGracefully() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-        mPhoneStateListener.onServiceStateChanged(mServiceState);
-
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        // Enabled timer Nr5G switch to None Nr5G, showing 5G icon gracefully
-        ServiceState ssLte = Mockito.mock(ServiceState.class);
-        setNrState(ssLte, NetworkRegistrationInfo.NR_STATE_NONE);
-        doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ssLte).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ssLte);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-    }
-
-    @Test
-    public void testNr5GIcon_disableDisplayGracePeriodTime_showLatestIconImmediately() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-
-        setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_NONE);
-        doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-
-        verifyDataIndicators(TelephonyIcons.ICON_LTE);
-    }
-
-    @Test
-    public void testNr5GIcon_resetDisplayGracePeriodTime_whenDataDisconnected() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-        setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(mServiceState).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        // Disabled timer, when out of service, reset timer to display latest state
-        updateDataConnectionState(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        setNrState(mServiceState, NetworkRegistrationInfo.NR_STATE_NONE);
-        doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(mServiceState).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_DISCONNECTED,
-                TelephonyManager.NETWORK_TYPE_UMTS);
-
-        verifyDataIndicators(0);
-    }
-
-    @Test
-    public void testNr5GIcon_enableDisplayGracePeriodTime_show5G_switching_5GPlus() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-        mPhoneStateListener.onServiceStateChanged(mServiceState);
-
-        ServiceState ss5G = Mockito.mock(ServiceState.class);
-        setNrState(ss5G, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss5G).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss5G);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        // When timeout enabled, 5G/5G+ switching should be updated immediately
-        ServiceState ss5GPlus = Mockito.mock(ServiceState.class);
-        setNrState(ss5GPlus, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(ss5GPlus).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss5GPlus);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G_PLUS);
-    }
-
-    @Test
-    public void testNr5GIcon_carrierDisabledDisplayGracePeriodTime_shouldUpdateIconImmediately() {
-        setupDefaultNr5GIconConfiguration();
-        setupDefaultNr5GIconDisplayGracePeriodTime_enableThirtySeconds();
-        setupDefaultSignal();
-        mNetworkController.handleConfigurationChanged();
-        mPhoneStateListener.onServiceStateChanged(mServiceState);
-
-        ServiceState ss = Mockito.mock(ServiceState.class);
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_CONNECTED);
-        doReturn(ServiceState.FREQUENCY_RANGE_HIGH).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        // State from NR_5G to NONE NR_5G with timeout, should show previous 5G icon
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_NONE);
-        doReturn(ServiceState.FREQUENCY_RANGE_UNKNOWN).when(ss).getNrFrequencyRange();
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-        mPhoneStateListener.onServiceStateChanged(ss);
-
-        verifyDataIndicators(TelephonyIcons.ICON_5G);
-
-        // Update nrIconDisplayGracePeriodMs to 0
-        setupDefaultNr5GIconDisplayGracePeriodTime_disabled();
-        mNetworkController.handleConfigurationChanged();
-
-        // State from NR_5G to NONE NR_STATE_RESTRICTED, showing corresponding icon
-        setNrState(ss, NetworkRegistrationInfo.NR_STATE_RESTRICTED);
-        mPhoneStateListener.onDataConnectionStateChanged(TelephonyManager.DATA_CONNECTED,
-                TelephonyManager.NETWORK_TYPE_LTE);
-
-        assertTrue(mConfig.nrIconDisplayGracePeriodMs == 0);
-        verifyDataIndicators(TelephonyIcons.ICON_LTE);
-    }
-
-    @Test
     public void testDataDisabledIcon_UserNotSetup() {
         setupNetworkController();
         when(mMockTm.isDataConnectionEnabled()).thenReturn(false);
@@ -488,6 +235,7 @@
                 .build();
         when(mServiceState.getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN))
                 .thenReturn(fakeRegInfo);
+        when(mDisplayInfo.getNetworkType()).thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
         updateServiceState();
         verifyDataIndicators(TelephonyIcons.ICON_H);
     }
@@ -523,10 +271,4 @@
                 true, DEFAULT_QS_SIGNAL_STRENGTH, dataIcon, false,
                 false);
     }
-
-    private void setNrState(ServiceState ss, int nrState) {
-        mFakeRegInfo.setNrState(nrState);
-        doReturn(mFakeRegInfo).when(ss)
-                .getNetworkRegistrationInfo(DOMAIN_PS, TRANSPORT_TYPE_WWAN);
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
index df62254..86add98 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/RemoteInputViewTest.java
@@ -43,7 +43,6 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationTestHelper;
 import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.util.Assert;
 
 import org.junit.After;
 import org.junit.Before;
@@ -74,7 +73,7 @@
 
     @Before
     public void setUp() throws Exception {
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
 
         mDependency.injectTestDependency(RemoteInputQuickSettingsDisabler.class,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt
new file mode 100644
index 0000000..f1672b1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/magnetictarget/MagnetizedObjectTest.kt
@@ -0,0 +1,442 @@
+/*
+ * 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.systemui.util.magnetictarget
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import android.view.MotionEvent
+import android.view.View
+import androidx.dynamicanimation.animation.FloatPropertyCompat
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.animation.PhysicsAnimatorTestUtils
+import org.junit.Assert.assertEquals
+import org.junit.Assert.assertFalse
+import org.junit.Assert.assertTrue
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers
+import org.mockito.ArgumentMatchers.anyFloat
+import org.mockito.Mockito
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.doAnswer
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.times
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.verifyNoMoreInteractions
+
+@TestableLooper.RunWithLooper
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class MagnetizedObjectTest : SysuiTestCase() {
+    /** Incrementing value for fake MotionEvent timestamps. */
+    private var time = 0L
+
+    /** Value to add to each new MotionEvent's timestamp. */
+    private var timeStep = 100
+
+    private val underlyingObject = this
+
+    private lateinit var targetView: View
+
+    private val targetSize = 200
+    private val targetCenterX = 500
+    private val targetCenterY = 900
+    private val magneticFieldRadius = 200
+
+    private var objectX = 0f
+    private var objectY = 0f
+    private val objectSize = 50f
+
+    private lateinit var magneticTarget: MagnetizedObject.MagneticTarget
+    private lateinit var magnetizedObject: MagnetizedObject<*>
+    private lateinit var magnetListener: MagnetizedObject.MagnetListener
+
+    private val xProperty = object : FloatPropertyCompat<MagnetizedObjectTest>("") {
+        override fun setValue(target: MagnetizedObjectTest?, value: Float) {
+            objectX = value
+        }
+        override fun getValue(target: MagnetizedObjectTest?): Float {
+            return objectX
+        }
+    }
+
+    private val yProperty = object : FloatPropertyCompat<MagnetizedObjectTest>("") {
+        override fun setValue(target: MagnetizedObjectTest?, value: Float) {
+            objectY = value
+        }
+
+        override fun getValue(target: MagnetizedObjectTest?): Float {
+            return objectY
+        }
+    }
+
+    @Before
+    fun setup() {
+        PhysicsAnimatorTestUtils.prepareForTest()
+
+        // Mock the view since a real view's getLocationOnScreen() won't work unless it's attached
+        // to a real window (it'll always return x = 0, y = 0).
+        targetView = mock(View::class.java)
+        `when`(targetView.context).thenReturn(context)
+
+        // The mock target view will pretend that it's 200x200, and at (400, 800). This means it's
+        // occupying the bounds (400, 800, 600, 1000) and it has a center of (500, 900).
+        `when`(targetView.width).thenReturn(targetSize)  // width = 200
+        `when`(targetView.height).thenReturn(targetSize) // height = 200
+        doAnswer { invocation ->
+            (invocation.arguments[0] as IntArray).also { location ->
+                // Return the top left of the target.
+                location[0] = targetCenterX - targetSize / 2 // x = 400
+                location[1] = targetCenterY - targetSize / 2 // y = 800
+            }
+        }.`when`(targetView).getLocationOnScreen(ArgumentMatchers.any())
+        `when`(targetView.context).thenReturn(context)
+
+        magneticTarget = MagnetizedObject.MagneticTarget(targetView, magneticFieldRadius)
+
+        magnetListener = mock(MagnetizedObject.MagnetListener::class.java)
+        magnetizedObject = object : MagnetizedObject<MagnetizedObjectTest>(
+                context, underlyingObject, xProperty, yProperty) {
+            override fun getWidth(underlyingObject: MagnetizedObjectTest): Float {
+                return objectSize
+            }
+
+            override fun getHeight(underlyingObject: MagnetizedObjectTest): Float {
+                return objectSize
+            }
+
+            override fun getLocationOnScreen(
+                underlyingObject: MagnetizedObjectTest,
+                loc: IntArray
+            ) {
+                loc[0] = objectX.toInt()
+                loc[1] = objectY.toInt() }
+        }
+
+        magnetizedObject.magnetListener = magnetListener
+        magnetizedObject.addTarget(magneticTarget)
+
+        timeStep = 100
+    }
+
+    @Test
+    fun testMotionEventConsumption() {
+        // Start at (0, 0). No magnetic field here.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 0, y = 0, action = MotionEvent.ACTION_DOWN)))
+
+        // Move to (400, 400), which is solidly outside the magnetic field.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 200, y = 200)))
+
+        // Move to (305, 705). This would be in the magnetic field radius if magnetic fields were
+        // square. It's not, because they're not.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = targetCenterX - magneticFieldRadius + 5,
+                y = targetCenterY - magneticFieldRadius + 5)))
+
+        // Move to (400, 800). That's solidly in the radius so the magnetic target should begin
+        // consuming events.
+        assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = targetCenterX - 100,
+                y = targetCenterY - 100)))
+
+        // Release at (400, 800). Since we're in the magnetic target, it should return true and
+        // consume the ACTION_UP.
+        assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 400, y = 800, action = MotionEvent.ACTION_UP)))
+
+        // ACTION_DOWN outside the field.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 200, y = 200, action = MotionEvent.ACTION_DOWN)))
+
+        // Move to the center. We absolutely should consume events there.
+        assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = targetCenterX,
+                y = targetCenterY)))
+
+        // Drag out to (0, 0) and we should be returning false again.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 0, y = 0)))
+
+        // The ACTION_UP event shouldn't be consumed either since it's outside the field.
+        assertFalse(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = 0, y = 0, action = MotionEvent.ACTION_UP)))
+    }
+
+    @Test
+    fun testMotionEventConsumption_downInMagneticField() {
+        // We should consume DOWN events if they occur in the field.
+        assertTrue(magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = targetCenterX, y = targetCenterY, action = MotionEvent.ACTION_DOWN)))
+    }
+
+    @Test
+    fun testMoveIntoAroundAndOutOfMagneticField() {
+        // Move around but don't touch the magnetic field.
+        dispatchMotionEvents(
+                getMotionEvent(x = 0, y = 0, action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(x = 100, y = 100),
+                getMotionEvent(x = 200, y = 200))
+
+        // You can't become unstuck if you were never stuck in the first place.
+        verify(magnetListener, never()).onStuckToTarget(magneticTarget)
+        verify(magnetListener, never()).onUnstuckFromTarget(
+                eq(magneticTarget), ArgumentMatchers.anyFloat(), ArgumentMatchers.anyFloat(),
+                eq(false))
+
+        // Move into and then around inside the magnetic field.
+        dispatchMotionEvents(
+                getMotionEvent(x = targetCenterX - 100, y = targetCenterY - 100),
+                getMotionEvent(x = targetCenterX, y = targetCenterY),
+                getMotionEvent(x = targetCenterX + 100, y = targetCenterY + 100))
+
+        // We should only have received one call to onStuckToTarget and none to unstuck.
+        verify(magnetListener, times(1)).onStuckToTarget(magneticTarget)
+        verify(magnetListener, never()).onUnstuckFromTarget(
+                eq(magneticTarget), ArgumentMatchers.anyFloat(), ArgumentMatchers.anyFloat(),
+                eq(false))
+
+        // Move out of the field and then release.
+        dispatchMotionEvents(
+                getMotionEvent(x = 100, y = 100),
+                getMotionEvent(x = 100, y = 100, action = MotionEvent.ACTION_UP))
+
+        // We should have received one unstuck call and no more stuck calls. We also should never
+        // have received an onReleasedInTarget call.
+        verify(magnetListener, times(1)).onUnstuckFromTarget(
+                eq(magneticTarget), ArgumentMatchers.anyFloat(), ArgumentMatchers.anyFloat(),
+                eq(false))
+        verifyNoMoreInteractions(magnetListener)
+    }
+
+    @Test
+    fun testMoveIntoOutOfAndBackIntoMagneticField() {
+        // Move into the field
+        dispatchMotionEvents(
+                getMotionEvent(
+                        x = targetCenterX - magneticFieldRadius,
+                        y = targetCenterY - magneticFieldRadius,
+                        action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(
+                        x = targetCenterX, y = targetCenterY))
+
+        verify(magnetListener, times(1)).onStuckToTarget(magneticTarget)
+        verify(magnetListener, never()).onReleasedInTarget(magneticTarget)
+
+        // Move back out.
+        dispatchMotionEvents(
+                getMotionEvent(
+                        x = targetCenterX - magneticFieldRadius,
+                        y = targetCenterY - magneticFieldRadius))
+
+        verify(magnetListener, times(1)).onUnstuckFromTarget(
+                eq(magneticTarget), ArgumentMatchers.anyFloat(), ArgumentMatchers.anyFloat(),
+                eq(false))
+        verify(magnetListener, never()).onReleasedInTarget(magneticTarget)
+
+        // Move in again and release in the magnetic field.
+        dispatchMotionEvents(
+                getMotionEvent(x = targetCenterX - 100, y = targetCenterY - 100),
+                getMotionEvent(x = targetCenterX + 50, y = targetCenterY + 50),
+                getMotionEvent(x = targetCenterX, y = targetCenterY),
+                getMotionEvent(
+                        x = targetCenterX, y = targetCenterY, action = MotionEvent.ACTION_UP))
+
+        verify(magnetListener, times(2)).onStuckToTarget(magneticTarget)
+        verify(magnetListener).onReleasedInTarget(magneticTarget)
+        verifyNoMoreInteractions(magnetListener)
+    }
+
+    @Test
+    fun testFlingTowardsTarget_towardsTarget() {
+        timeStep = 10
+
+        // Forcefully fling the object towards the target (but never touch the magnetic field).
+        dispatchMotionEvents(
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = 0,
+                        action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = targetCenterY / 2),
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = targetCenterY - magneticFieldRadius * 2,
+                        action = MotionEvent.ACTION_UP))
+
+        // Nevertheless it should have ended up stuck to the target.
+        verify(magnetListener, times(1)).onStuckToTarget(magneticTarget)
+    }
+
+    @Test
+    fun testFlingTowardsTarget_towardsButTooSlow() {
+        // Very, very slowly fling the object towards the target (but never touch the magnetic
+        // field). This value is only used to create MotionEvent timestamps, it will not block the
+        // test for 10 seconds.
+        timeStep = 10000
+        dispatchMotionEvents(
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = 0,
+                        action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = targetCenterY / 2),
+                getMotionEvent(
+                        x = targetCenterX,
+                        y = targetCenterY - magneticFieldRadius * 2,
+                        action = MotionEvent.ACTION_UP))
+
+        // No sticking should have occurred.
+        verifyNoMoreInteractions(magnetListener)
+    }
+
+    @Test
+    fun testFlingTowardsTarget_missTarget() {
+        timeStep = 10
+        // Forcefully fling the object down, but not towards the target.
+        dispatchMotionEvents(
+                getMotionEvent(
+                        x = 0,
+                        y = 0,
+                        action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(
+                        x = 0,
+                        y = targetCenterY / 2),
+                getMotionEvent(
+                        x = 0,
+                        y = targetCenterY - magneticFieldRadius * 2,
+                        action = MotionEvent.ACTION_UP))
+
+        verifyNoMoreInteractions(magnetListener)
+    }
+
+    @Test
+    fun testMagnetAnimation() {
+        // Make sure the object starts at (0, 0).
+        assertEquals(0f, objectX)
+        assertEquals(0f, objectY)
+
+        // Trigger the magnet animation, and block the test until it ends.
+        PhysicsAnimatorTestUtils.setAllAnimationsBlock(true)
+        magnetizedObject.maybeConsumeMotionEvent(getMotionEvent(
+                x = targetCenterX,
+                y = targetCenterY,
+                action = MotionEvent.ACTION_DOWN))
+
+        // The object's (top-left) position should now position it centered over the target.
+        assertEquals(targetCenterX - objectSize / 2, objectX)
+        assertEquals(targetCenterY - objectSize / 2, objectY)
+    }
+
+    @Test
+    fun testMultipleTargets() {
+        val secondMagneticTarget = getSecondMagneticTarget()
+
+        // Drag into the second target.
+        dispatchMotionEvents(
+                getMotionEvent(x = 0, y = 0, action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(x = 100, y = 900))
+
+        // Verify that we received an onStuck for the second target, and no others.
+        verify(magnetListener).onStuckToTarget(secondMagneticTarget)
+        verifyNoMoreInteractions(magnetListener)
+
+        // Drag into the original target.
+        dispatchMotionEvents(
+                getMotionEvent(x = 0, y = 0),
+                getMotionEvent(x = 500, y = 900))
+
+        // We should have unstuck from the second one and stuck into the original one.
+        verify(magnetListener).onUnstuckFromTarget(
+                eq(secondMagneticTarget), anyFloat(), anyFloat(), eq(false))
+        verify(magnetListener).onStuckToTarget(magneticTarget)
+        verifyNoMoreInteractions(magnetListener)
+    }
+
+    @Test
+    fun testMultipleTargets_flingIntoSecond() {
+        val secondMagneticTarget = getSecondMagneticTarget()
+
+        timeStep = 10
+
+        // Fling towards the second target.
+        dispatchMotionEvents(
+                getMotionEvent(x = 100, y = 0, action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(x = 100, y = 350),
+                getMotionEvent(x = 100, y = 650, action = MotionEvent.ACTION_UP))
+
+        // Verify that we received an onStuck for the second target.
+        verify(magnetListener).onStuckToTarget(secondMagneticTarget)
+
+        // Fling towards the first target.
+        dispatchMotionEvents(
+                getMotionEvent(x = 300, y = 0, action = MotionEvent.ACTION_DOWN),
+                getMotionEvent(x = 400, y = 350),
+                getMotionEvent(x = 500, y = 650, action = MotionEvent.ACTION_UP))
+
+        // Verify that we received onStuck for the original target.
+        verify(magnetListener).onStuckToTarget(magneticTarget)
+    }
+
+    private fun getSecondMagneticTarget(): MagnetizedObject.MagneticTarget {
+        // The first target view is at bounds (400, 800, 600, 1000) and it has a center of
+        // (500, 900). We'll add a second one at bounds (0, 800, 200, 1000) with center (100, 900).
+        val secondTargetView = mock(View::class.java)
+        var secondTargetCenterX = 100
+        var secondTargetCenterY = 900
+
+        `when`(secondTargetView.context).thenReturn(context)
+        `when`(secondTargetView.width).thenReturn(targetSize)  // width = 200
+        `when`(secondTargetView.height).thenReturn(targetSize) // height = 200
+        doAnswer { invocation ->
+            (invocation.arguments[0] as IntArray).also { location ->
+                // Return the top left of the target.
+                location[0] = secondTargetCenterX - targetSize / 2 // x = 0
+                location[1] = secondTargetCenterY - targetSize / 2 // y = 800
+            }
+        }.`when`(secondTargetView).getLocationOnScreen(ArgumentMatchers.any())
+
+        return magnetizedObject.addTarget(secondTargetView, magneticFieldRadius)
+    }
+
+    /**
+     * Return a MotionEvent at the given coordinates, with the given action (or MOVE by default).
+     * The event's time fields will be incremented by 10ms each time this is called, so tha
+     * VelocityTracker works.
+     */
+    private fun getMotionEvent(
+        x: Int,
+        y: Int,
+        action: Int = MotionEvent.ACTION_MOVE
+    ): MotionEvent {
+        return MotionEvent.obtain(time, time, action, x.toFloat(), y.toFloat(), 0)
+                .also { time += timeStep }
+    }
+
+    /** Dispatch all of the provided events to the target view. */
+    private fun dispatchMotionEvents(vararg events: MotionEvent) {
+        events.forEach { magnetizedObject.maybeConsumeMotionEvent(it) }
+    }
+
+    /** Prevents Kotlin from being mad that eq() is nullable. */
+    private fun <T> eq(value: T): T = Mockito.eq(value) ?: value
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
index 20dcbb7..1ff9548 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/wakelock/KeepAwakeAnimationListenerTest.java
@@ -21,14 +21,12 @@
 import static org.mockito.Mockito.verify;
 
 import android.animation.Animator;
-import android.os.Looper;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.util.Assert;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -45,7 +43,7 @@
 
     @Before
     public void setup() {
-        Assert.sMainLooper = TestableLooper.get(this).getLooper();
+        allowTestableLooperAsMainThread();
         MockitoAnnotations.initMocks(this);
         KeepAwakeAnimationListener.sWakeLock = mWakeLock;
         mKeepAwakeAnimationListener = new KeepAwakeAnimationListener(getContext());
@@ -63,7 +61,10 @@
 
     @Test(expected = IllegalStateException.class)
     public void initThrows_onNonMainThread() {
-        Assert.sMainLooper = Looper.getMainLooper();
+        disallowTestableLooperAsMainThread();
+
+        // we are creating the KeepAwakeAnimationListener from the TestableLooper, not the main
+        // looper, so we expect an IllegalStateException:
         new KeepAwakeAnimationListener(getContext());
     }
 }
diff --git a/packages/Tethering/TEST_MAPPING b/packages/Tethering/TEST_MAPPING
new file mode 100644
index 0000000..73254cd
--- /dev/null
+++ b/packages/Tethering/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+  "postsubmit": [
+    {
+      "name": "TetheringTests"
+    }
+  ]
+}
diff --git a/packages/Tethering/common/TetheringLib/Android.bp b/packages/Tethering/common/TetheringLib/Android.bp
index cb0de7a..1a3d5b6 100644
--- a/packages/Tethering/common/TetheringLib/Android.bp
+++ b/packages/Tethering/common/TetheringLib/Android.bp
@@ -83,7 +83,6 @@
     name: "framework-tethering-stubs",
     srcs: [":framework-tethering-stubs-sources"],
     libs: ["framework-all"],
-    static_libs: ["tethering-aidl-interfaces-java"],
     sdk_version: "core_platform",
 }
 
diff --git a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
index df87ac9..a18f5da 100644
--- a/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
+++ b/packages/Tethering/common/TetheringLib/src/android/net/TetheringConstants.java
@@ -33,6 +33,9 @@
  */
 @SystemApi(client = MODULE_LIBRARIES)
 public class TetheringConstants {
+    /** An explicit private class to avoid exposing constructor.*/
+    private TetheringConstants() { }
+
     /**
      * Extra used for communicating with the TetherService. Includes the type of tethering to
      * enable if any.
diff --git a/packages/Tethering/src/android/net/ip/IpServer.java b/packages/Tethering/src/android/net/ip/IpServer.java
index b4d49c0..3acc766 100644
--- a/packages/Tethering/src/android/net/ip/IpServer.java
+++ b/packages/Tethering/src/android/net/ip/IpServer.java
@@ -40,12 +40,14 @@
 import android.net.dhcp.DhcpServingParamsParcelExt;
 import android.net.dhcp.IDhcpLeaseCallbacks;
 import android.net.dhcp.IDhcpServer;
+import android.net.ip.IpNeighborMonitor.NeighborEvent;
 import android.net.ip.RouterAdvertisementDaemon.RaParams;
 import android.net.shared.NetdUtils;
 import android.net.shared.RouteUtils;
 import android.net.util.InterfaceParams;
 import android.net.util.InterfaceSet;
 import android.net.util.SharedLog;
+import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
@@ -59,14 +61,17 @@
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
 
+import java.io.IOException;
 import java.net.Inet4Address;
 import java.net.Inet6Address;
 import java.net.InetAddress;
+import java.net.NetworkInterface;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Objects;
 import java.util.Random;
@@ -149,6 +154,12 @@
 
     /** Capture IpServer dependencies, for injection. */
     public abstract static class Dependencies {
+        /** Create an IpNeighborMonitor to be used by this IpServer */
+        public IpNeighborMonitor getIpNeighborMonitor(Handler handler, SharedLog log,
+                IpNeighborMonitor.NeighborEventConsumer consumer) {
+            return new IpNeighborMonitor(handler, log, consumer);
+        }
+
         /** Create a RouterAdvertisementDaemon instance to be used by IpServer.*/
         public RouterAdvertisementDaemon getRouterAdvertisementDaemon(InterfaceParams ifParams) {
             return new RouterAdvertisementDaemon(ifParams);
@@ -159,6 +170,15 @@
             return InterfaceParams.getByName(ifName);
         }
 
+        /** Get |ifName|'s interface index. */
+        public int getIfindex(String ifName) {
+            try {
+                return NetworkInterface.getByName(ifName).getIndex();
+            } catch (IOException | NullPointerException e) {
+                Log.e(TAG, "Can't determine interface index for interface " + ifName);
+                return 0;
+            }
+        }
         /** Create a DhcpServer instance to be used by IpServer. */
         public abstract void makeDhcpServer(String ifName, DhcpServingParamsParcel params,
                 DhcpServerCallbacks cb);
@@ -184,6 +204,8 @@
     public static final int CMD_TETHER_CONNECTION_CHANGED   = BASE_IPSERVER + 9;
     // new IPv6 tethering parameters need to be processed
     public static final int CMD_IPV6_TETHER_UPDATE          = BASE_IPSERVER + 10;
+    // new neighbor cache entry on our interface
+    public static final int CMD_NEIGHBOR_EVENT              = BASE_IPSERVER + 11;
 
     private final State mInitialState;
     private final State mLocalHotspotState;
@@ -223,6 +245,40 @@
     @NonNull
     private List<TetheredClient> mDhcpLeases = Collections.emptyList();
 
+    private int mLastIPv6UpstreamIfindex = 0;
+
+    private class MyNeighborEventConsumer implements IpNeighborMonitor.NeighborEventConsumer {
+        public void accept(NeighborEvent e) {
+            sendMessage(CMD_NEIGHBOR_EVENT, e);
+        }
+    }
+
+    static class Ipv6ForwardingRule {
+        public final int upstreamIfindex;
+        public final int downstreamIfindex;
+        public final Inet6Address address;
+        public final MacAddress srcMac;
+        public final MacAddress dstMac;
+
+        Ipv6ForwardingRule(int upstreamIfindex, int downstreamIfIndex, Inet6Address address,
+                MacAddress srcMac, MacAddress dstMac) {
+            this.upstreamIfindex = upstreamIfindex;
+            this.downstreamIfindex = downstreamIfIndex;
+            this.address = address;
+            this.srcMac = srcMac;
+            this.dstMac = dstMac;
+        }
+
+        public Ipv6ForwardingRule onNewUpstream(int newUpstreamIfindex) {
+            return new Ipv6ForwardingRule(newUpstreamIfindex, downstreamIfindex, address, srcMac,
+                    dstMac);
+        }
+    }
+    private final LinkedHashMap<Inet6Address, Ipv6ForwardingRule> mIpv6ForwardingRules =
+            new LinkedHashMap<>();
+
+    private final IpNeighborMonitor mIpNeighborMonitor;
+
     public IpServer(
             String ifaceName, Looper looper, int interfaceType, SharedLog log,
             INetd netd, Callback callback, boolean usingLegacyDhcp, Dependencies deps) {
@@ -240,6 +296,12 @@
         mLastError = TetheringManager.TETHER_ERROR_NO_ERROR;
         mServingMode = STATE_AVAILABLE;
 
+        mIpNeighborMonitor = mDeps.getIpNeighborMonitor(getHandler(), mLog,
+                new MyNeighborEventConsumer());
+        if (!mIpNeighborMonitor.start()) {
+            mLog.e("Failed to create IpNeighborMonitor on " + mIfaceName);
+        }
+
         mInitialState = new InitialState();
         mLocalHotspotState = new LocalHotspotState();
         mTetheredState = new TetheredState();
@@ -607,13 +669,21 @@
         }
 
         RaParams params = null;
+        int upstreamIfindex = 0;
 
         if (v6only != null) {
+            final String upstreamIface = v6only.getInterfaceName();
+
             params = new RaParams();
-            params.mtu = v6only.getMtu();
+            // We advertise an mtu lower by 16, which is the closest multiple of 8 >= 14,
+            // the ethernet header size.  This makes kernel ebpf tethering offload happy.
+            // This hack should be reverted once we have the kernel fixed up.
+            // Note: this will automatically clamp to at least 1280 (ipv6 minimum mtu)
+            // see RouterAdvertisementDaemon.java putMtu()
+            params.mtu = v6only.getMtu() - 16;
             params.hasDefaultRoute = v6only.hasIpv6DefaultRoute();
 
-            if (params.hasDefaultRoute) params.hopLimit = getHopLimit(v6only.getInterfaceName());
+            if (params.hasDefaultRoute) params.hopLimit = getHopLimit(upstreamIface);
 
             for (LinkAddress linkAddr : v6only.getLinkAddresses()) {
                 if (linkAddr.getPrefixLength() != RFC7421_PREFIX_LENGTH) continue;
@@ -627,12 +697,18 @@
                     params.dnses.add(dnsServer);
                 }
             }
+
+            upstreamIfindex = mDeps.getIfindex(upstreamIface);
         }
+
         // If v6only is null, we pass in null to setRaParams(), which handles
         // deprecation of any existing RA data.
 
         setRaParams(params);
         mLastIPv6LinkProperties = v6only;
+
+        updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, upstreamIfindex, null);
+        mLastIPv6UpstreamIfindex = upstreamIfindex;
     }
 
     private void configureLocalIPv6Routes(
@@ -727,6 +803,73 @@
         }
     }
 
+    private void addIpv6ForwardingRule(Ipv6ForwardingRule rule) {
+        try {
+            mNetd.tetherRuleAddDownstreamIpv6(mInterfaceParams.index, rule.upstreamIfindex,
+                    rule.address.getAddress(),  mInterfaceParams.macAddr.toByteArray(),
+                    rule.dstMac.toByteArray());
+            mIpv6ForwardingRules.put(rule.address, rule);
+        } catch (RemoteException | ServiceSpecificException e) {
+            Log.e(TAG, "Could not add IPv6 downstream rule: " + e);
+        }
+    }
+
+    private void removeIpv6ForwardingRule(Ipv6ForwardingRule rule, boolean removeFromMap) {
+        try {
+            mNetd.tetherRuleRemoveDownstreamIpv6(rule.upstreamIfindex, rule.address.getAddress());
+            if (removeFromMap) {
+                mIpv6ForwardingRules.remove(rule.address);
+            }
+        } catch (RemoteException | ServiceSpecificException e) {
+            Log.e(TAG, "Could not remove IPv6 downstream rule: " + e);
+        }
+    }
+
+    // Convenience method to replace a rule with the same rule on a new upstream interface.
+    // Allows replacing the rules in one iteration pass without ConcurrentModificationExceptions.
+    // Relies on the fact that rules are in a map indexed by IP address.
+    private void updateIpv6ForwardingRule(Ipv6ForwardingRule rule, int newIfindex) {
+        addIpv6ForwardingRule(rule.onNewUpstream(newIfindex));
+        removeIpv6ForwardingRule(rule, false /*removeFromMap*/);
+    }
+
+    // Handles all updates to IPv6 forwarding rules. These can currently change only if the upstream
+    // changes or if a neighbor event is received.
+    private void updateIpv6ForwardingRules(int prevUpstreamIfindex, int upstreamIfindex,
+            NeighborEvent e) {
+        // If the upstream interface has changed, remove all rules and re-add them with the new
+        // upstream interface.
+        if (prevUpstreamIfindex != upstreamIfindex) {
+            for (Ipv6ForwardingRule rule : mIpv6ForwardingRules.values()) {
+                updateIpv6ForwardingRule(rule, upstreamIfindex);
+            }
+        }
+
+        // If we're here to process a NeighborEvent, do so now.
+        if (e == null) return;
+        if (!(e.ip instanceof Inet6Address) || e.ip.isMulticastAddress()
+                || e.ip.isLoopbackAddress() || e.ip.isLinkLocalAddress()) {
+            return;
+        }
+
+        Ipv6ForwardingRule rule = new Ipv6ForwardingRule(mLastIPv6UpstreamIfindex,
+                mInterfaceParams.index, (Inet6Address) e.ip, mInterfaceParams.macAddr,
+                e.macAddr);
+        if (e.isValid()) {
+            addIpv6ForwardingRule(rule);
+        } else {
+            removeIpv6ForwardingRule(rule, true /*removeFromMap*/);
+        }
+    }
+
+    private void handleNeighborEvent(NeighborEvent e) {
+        if (mInterfaceParams != null
+                && mInterfaceParams.index == e.ifindex
+                && mInterfaceParams.hasMacAddress) {
+            updateIpv6ForwardingRules(mLastIPv6UpstreamIfindex, mLastIPv6UpstreamIfindex, e);
+        }
+    }
+
     private byte getHopLimit(String upstreamIface) {
         try {
             int upstreamHopLimit = Integer.parseUnsignedInt(
@@ -1014,6 +1157,9 @@
                         }
                     }
                     break;
+                case CMD_NEIGHBOR_EVENT:
+                    handleNeighborEvent((NeighborEvent) message.obj);
+                    break;
                 default:
                     return false;
             }
diff --git a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
index 6261def..72fe95b 100644
--- a/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
+++ b/packages/Tethering/src/com/android/server/connectivity/tethering/Tethering.java
@@ -314,9 +314,13 @@
 
         startStateMachineUpdaters(mHandler);
         startTrackDefaultNetwork();
-        getWifiManager().registerSoftApCallback(
-                mHandler::post /* executor */,
-                new TetheringSoftApCallback());
+
+        final WifiManager wifiManager = getWifiManager();
+        if (wifiManager != null) {
+            wifiManager.registerSoftApCallback(
+                  mHandler::post /* executor */,
+                  new TetheringSoftApCallback());
+        }
     }
 
     private void startStateMachineUpdaters(Handler handler) {
diff --git a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
index acedfab..33b3558 100644
--- a/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
+++ b/packages/Tethering/tests/unit/src/android/net/ip/IpServerTest.java
@@ -29,6 +29,11 @@
 import static android.net.ip.IpServer.STATE_LOCAL_ONLY;
 import static android.net.ip.IpServer.STATE_TETHERED;
 import static android.net.ip.IpServer.STATE_UNAVAILABLE;
+import static android.net.netlink.NetlinkConstants.RTM_DELNEIGH;
+import static android.net.netlink.NetlinkConstants.RTM_NEWNEIGH;
+import static android.net.netlink.StructNdMsg.NUD_FAILED;
+import static android.net.netlink.StructNdMsg.NUD_REACHABLE;
+import static android.net.netlink.StructNdMsg.NUD_STALE;
 import static android.net.shared.Inet4AddressUtils.intToInet4AddressHTH;
 
 import static org.junit.Assert.assertEquals;
@@ -41,6 +46,7 @@
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.inOrder;
 import static org.mockito.Mockito.never;
@@ -52,6 +58,7 @@
 import static org.mockito.Mockito.when;
 
 import android.net.INetd;
+import android.net.InetAddresses;
 import android.net.InterfaceConfigurationParcel;
 import android.net.IpPrefix;
 import android.net.LinkAddress;
@@ -61,6 +68,8 @@
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServer;
 import android.net.dhcp.IDhcpServerCallbacks;
+import android.net.ip.IpNeighborMonitor.NeighborEvent;
+import android.net.ip.IpNeighborMonitor.NeighborEventConsumer;
 import android.net.util.InterfaceParams;
 import android.net.util.InterfaceSet;
 import android.net.util.SharedLog;
@@ -81,6 +90,7 @@
 import org.mockito.MockitoAnnotations;
 
 import java.net.Inet4Address;
+import java.net.InetAddress;
 
 @RunWith(AndroidJUnit4.class)
 @SmallTest
@@ -88,6 +98,8 @@
     private static final String IFACE_NAME = "testnet1";
     private static final String UPSTREAM_IFACE = "upstream0";
     private static final String UPSTREAM_IFACE2 = "upstream1";
+    private static final int UPSTREAM_IFINDEX = 101;
+    private static final int UPSTREAM_IFINDEX2 = 102;
     private static final String BLUETOOTH_IFACE_ADDR = "192.168.42.1";
     private static final int BLUETOOTH_DHCP_PREFIX_LENGTH = 24;
     private static final int DHCP_LEASE_TIME_SECS = 3600;
@@ -102,6 +114,7 @@
     @Mock private SharedLog mSharedLog;
     @Mock private IDhcpServer mDhcpServer;
     @Mock private RouterAdvertisementDaemon mRaDaemon;
+    @Mock private IpNeighborMonitor mIpNeighborMonitor;
     @Mock private IpServer.Dependencies mDependencies;
 
     @Captor private ArgumentCaptor<DhcpServingParamsParcel> mDhcpParamsCaptor;
@@ -111,6 +124,7 @@
             ArgumentCaptor.forClass(LinkProperties.class);
     private IpServer mIpServer;
     private InterfaceConfigurationParcel mInterfaceConfiguration;
+    private NeighborEventConsumer mNeighborEventConsumer;
 
     private void initStateMachine(int interfaceType) throws Exception {
         initStateMachine(interfaceType, false /* usingLegacyDhcp */);
@@ -130,16 +144,28 @@
         }).when(mDependencies).makeDhcpServer(any(), mDhcpParamsCaptor.capture(), any());
         when(mDependencies.getRouterAdvertisementDaemon(any())).thenReturn(mRaDaemon);
         when(mDependencies.getInterfaceParams(IFACE_NAME)).thenReturn(TEST_IFACE_PARAMS);
+
+        when(mDependencies.getIfindex(eq(UPSTREAM_IFACE))).thenReturn(UPSTREAM_IFINDEX);
+        when(mDependencies.getIfindex(eq(UPSTREAM_IFACE2))).thenReturn(UPSTREAM_IFINDEX2);
+
         mInterfaceConfiguration = new InterfaceConfigurationParcel();
         mInterfaceConfiguration.flags = new String[0];
         if (interfaceType == TETHERING_BLUETOOTH) {
             mInterfaceConfiguration.ipv4Addr = BLUETOOTH_IFACE_ADDR;
             mInterfaceConfiguration.prefixLength = BLUETOOTH_DHCP_PREFIX_LENGTH;
         }
+
+        ArgumentCaptor<NeighborEventConsumer> neighborCaptor =
+                ArgumentCaptor.forClass(NeighborEventConsumer.class);
+        doReturn(mIpNeighborMonitor).when(mDependencies).getIpNeighborMonitor(any(), any(),
+                neighborCaptor.capture());
+
         mIpServer = new IpServer(
                 IFACE_NAME, mLooper.getLooper(), interfaceType, mSharedLog, mNetd,
                 mCallback, usingLegacyDhcp, mDependencies);
         mIpServer.start();
+        mNeighborEventConsumer = neighborCaptor.getValue();
+
         // Starting the state machine always puts us in a consistent state and notifies
         // the rest of the world that we've changed from an unknown to available state.
         mLooper.dispatchAll();
@@ -158,7 +184,9 @@
         initStateMachine(interfaceType, usingLegacyDhcp);
         dispatchCommand(IpServer.CMD_TETHER_REQUESTED, STATE_TETHERED);
         if (upstreamIface != null) {
-            dispatchTetherConnectionChanged(upstreamIface);
+            LinkProperties lp = new LinkProperties();
+            lp.setInterfaceName(upstreamIface);
+            dispatchTetherConnectionChanged(upstreamIface, lp);
         }
         reset(mNetd, mCallback);
     }
@@ -170,6 +198,8 @@
 
     @Test
     public void startsOutAvailable() {
+        when(mDependencies.getIpNeighborMonitor(any(), any(), any()))
+                .thenReturn(mIpNeighborMonitor);
         mIpServer = new IpServer(IFACE_NAME, mLooper.getLooper(), TETHERING_BLUETOOTH, mSharedLog,
                 mNetd, mCallback, false /* usingLegacyDhcp */, mDependencies);
         mIpServer.start();
@@ -467,6 +497,89 @@
         verify(mDependencies, never()).makeDhcpServer(any(), any(), any());
     }
 
+    private InetAddress addr(String addr) throws Exception {
+        return InetAddresses.parseNumericAddress(addr);
+    }
+
+    private void recvNewNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
+        mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_NEWNEIGH, ifindex, addr,
+                nudState, mac));
+        mLooper.dispatchAll();
+    }
+
+    private void recvDelNeigh(int ifindex, InetAddress addr, short nudState, MacAddress mac) {
+        mNeighborEventConsumer.accept(new NeighborEvent(0, RTM_DELNEIGH, ifindex, addr,
+                nudState, mac));
+        mLooper.dispatchAll();
+    }
+
+    @Test
+    public void addRemoveipv6ForwardingRules() throws Exception {
+        initTetheredStateMachine(TETHERING_WIFI, UPSTREAM_IFACE, false /* usingLegacyDhcp */);
+
+        final int myIfindex = TEST_IFACE_PARAMS.index;
+        final int notMyIfindex = myIfindex - 1;
+
+        final MacAddress myMac = TEST_IFACE_PARAMS.macAddr;
+        final InetAddress neighA = InetAddresses.parseNumericAddress("2001:db8::1");
+        final InetAddress neighB = InetAddresses.parseNumericAddress("2001:db8::2");
+        final InetAddress neighLL = InetAddresses.parseNumericAddress("fe80::1");
+        final InetAddress neighMC = InetAddresses.parseNumericAddress("ff02::1234");
+        final MacAddress macA = MacAddress.fromString("00:00:00:00:00:0a");
+        final MacAddress macB = MacAddress.fromString("11:22:33:00:00:0b");
+
+        reset(mNetd);
+
+        // Events on other interfaces are ignored.
+        recvNewNeigh(notMyIfindex, neighA, NUD_REACHABLE, macA);
+        verifyNoMoreInteractions(mNetd);
+
+        // Events on this interface are received and sent to netd.
+        recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
+        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
+                eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
+        reset(mNetd);
+
+        recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
+        verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX),
+                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+        reset(mNetd);
+
+        // Link-local and multicast neighbors are ignored.
+        recvNewNeigh(notMyIfindex, neighLL, NUD_REACHABLE, macA);
+        verifyNoMoreInteractions(mNetd);
+        recvNewNeigh(notMyIfindex, neighMC, NUD_REACHABLE, macA);
+        verifyNoMoreInteractions(mNetd);
+
+        // A neighbor that is no longer valid causes the rule to be removed.
+        recvNewNeigh(myIfindex, neighA, NUD_FAILED, macA);
+        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighA.getAddress()));
+        reset(mNetd);
+
+        // A neighbor that is deleted causes the rule to be removed.
+        recvDelNeigh(myIfindex, neighB, NUD_STALE, macB);
+        verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX), eq(neighB.getAddress()));
+        reset(mNetd);
+
+        // Upstream changes result in deleting and re-adding the rules.
+        recvNewNeigh(myIfindex, neighA, NUD_REACHABLE, macA);
+        recvNewNeigh(myIfindex, neighB, NUD_REACHABLE, macB);
+        reset(mNetd);
+
+        InOrder inOrder = inOrder(mNetd);
+        LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(UPSTREAM_IFACE2);
+        dispatchTetherConnectionChanged(UPSTREAM_IFACE2, lp);
+        inOrder.verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX2),
+                eq(neighA.getAddress()), eq(myMac.toByteArray()), eq(macA.toByteArray()));
+        inOrder.verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX),
+                    eq(neighA.getAddress()));
+        inOrder.verify(mNetd).tetherRuleAddDownstreamIpv6(eq(myIfindex), eq(UPSTREAM_IFINDEX2),
+                eq(neighB.getAddress()), eq(myMac.toByteArray()), eq(macB.toByteArray()));
+        inOrder.verify(mNetd).tetherRuleRemoveDownstreamIpv6(eq(UPSTREAM_IFINDEX),
+                eq(neighB.getAddress()));
+    }
+
     private void assertDhcpStarted(IpPrefix expectedPrefix) throws Exception {
         verify(mDependencies, times(1)).makeDhcpServer(eq(IFACE_NAME), any(), any());
         verify(mDhcpServer, timeout(MAKE_DHCPSERVER_TIMEOUT_MS).times(1)).startWithCallbacks(
@@ -508,13 +621,21 @@
      *
      * @see #dispatchCommand(int)
      * @param upstreamIface String name of upstream interface (or null)
+     * @param v6lp IPv6 LinkProperties of the upstream interface, or null for an IPv4-only upstream.
      */
-    private void dispatchTetherConnectionChanged(String upstreamIface) {
+    private void dispatchTetherConnectionChanged(String upstreamIface, LinkProperties v6lp) {
         mIpServer.sendMessage(IpServer.CMD_TETHER_CONNECTION_CHANGED,
                 new InterfaceSet(upstreamIface));
+        if (v6lp != null) {
+            mIpServer.sendMessage(IpServer.CMD_IPV6_TETHER_UPDATE, v6lp);
+        }
         mLooper.dispatchAll();
     }
 
+    private void dispatchTetherConnectionChanged(String upstreamIface) {
+        dispatchTetherConnectionChanged(upstreamIface, null);
+    }
+
     private void assertIPv4AddressAndDirectlyConnectedRoute(LinkProperties lp) {
         // Find the first IPv4 LinkAddress.
         LinkAddress addr4 = null;
diff --git a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
index 8e5aaf2..f2074bd 100644
--- a/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
+++ b/packages/Tethering/tests/unit/src/com/android/server/connectivity/tethering/TetheringTest.java
@@ -95,6 +95,7 @@
 import android.net.dhcp.DhcpServerCallbacks;
 import android.net.dhcp.DhcpServingParamsParcel;
 import android.net.dhcp.IDhcpServer;
+import android.net.ip.IpNeighborMonitor;
 import android.net.ip.IpServer;
 import android.net.ip.RouterAdvertisementDaemon;
 import android.net.util.InterfaceParams;
@@ -173,6 +174,7 @@
     @Mock private UpstreamNetworkMonitor mUpstreamNetworkMonitor;
     @Mock private IPv6TetheringCoordinator mIPv6TetheringCoordinator;
     @Mock private RouterAdvertisementDaemon mRouterAdvertisementDaemon;
+    @Mock private IpNeighborMonitor mIpNeighborMonitor;
     @Mock private IDhcpServer mDhcpServer;
     @Mock private INetd mNetd;
     @Mock private UserManager mUserManager;
@@ -278,6 +280,11 @@
                 }
             }).run();
         }
+
+        public IpNeighborMonitor getIpNeighborMonitor(Handler h, SharedLog l,
+                IpNeighborMonitor.NeighborEventConsumer c) {
+            return mIpNeighborMonitor;
+        }
     }
 
     private class MockTetheringConfiguration extends TetheringConfiguration {
diff --git a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
index fcb113e..210fdc6 100644
--- a/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
+++ b/packages/WallpaperCropper/src/com/android/photos/views/TiledImageRenderer.java
@@ -163,7 +163,7 @@
 
     private static boolean isHighResolution(Context context) {
         DisplayMetrics metrics = new DisplayMetrics();
-        context.getDisplay().getMetrics(metrics);
+        context.getDisplayNoVerify().getMetrics(metrics);
         return metrics.heightPixels > 2048 ||  metrics.widthPixels > 2048;
     }
 
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index eda3fb9..cff5504 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -252,6 +252,9 @@
     // Package: android
     NOTE_ID_WIFI_SIM_REQUIRED = 60;
 
+    // Inform the user a foreground service while-in-use permission is restricted.
+    NOTE_FOREGROUND_SERVICE_WHILE_IN_USE_PERMISSION = 61;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/Android.bp b/services/Android.bp
index 416f448..db6e21a 100644
--- a/services/Android.bp
+++ b/services/Android.bp
@@ -114,9 +114,10 @@
     name: "services-stubs.sources",
     srcs: [":services-all-sources"],
     installable: false,
-    // TODO: remove the --hide options below
     args: " --show-annotation android.annotation.SystemApi\\(client=android.annotation.SystemApi.Client.SYSTEM_SERVER\\)" +
         " --hide-annotation android.annotation.Hide" +
+        " --hide InternalClasses" + // com.android.* classes are okay in this interface
+        // TODO: remove the --hide options below
         " --hide-package com.google.android.startop.iorap" +
         " --hide ReferencesHidden" +
         " --hide DeprecationMismatch" +
@@ -127,6 +128,16 @@
             api_file: "api/current.txt",
             removed_api_file: "api/removed.txt",
         },
+        last_released: {
+            api_file: ":last-released-system-server-api",
+            removed_api_file: "api/removed.txt",
+            baseline_file: ":system-server-api-incompatibilities-with-last-released"
+        },
+        api_lint: {
+            enabled: true,
+            new_since: ":last-released-system-server-api",
+            baseline_file: "api/lint-baseline.txt",
+        },
     },
 }
 
diff --git a/services/accessibility/OWNERS b/services/accessibility/OWNERS
index 265674a..c6f42f7 100644
--- a/services/accessibility/OWNERS
+++ b/services/accessibility/OWNERS
@@ -1,3 +1,4 @@
 svetoslavganov@google.com
 pweaver@google.com
 rhedjao@google.com
+qasid@google.com
diff --git a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
index 6c8aaf4..0a527d4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
+++ b/services/accessibility/java/com/android/server/accessibility/AbstractAccessibilityServiceConnection.java
@@ -230,6 +230,10 @@
         /* This is exactly PendingIntent.getActivity, separated out for testability */
         PendingIntent getPendingIntentActivity(Context context, int requestCode, Intent intent,
                 int flags);
+
+        void setGestureDetectionPassthroughRegion(int displayId, Region region);
+
+        void setTouchExplorationPassthroughRegion(int displayId, Region region);
     }
 
     public AbstractAccessibilityServiceConnection(Context context, ComponentName componentName,
@@ -1736,4 +1740,14 @@
     public boolean isMultiFingerGesturesEnabled() {
         return mRequestMultiFingerGestures;
     }
+
+    @Override
+    public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+        mSystemSupport.setGestureDetectionPassthroughRegion(displayId, region);
+    }
+
+    @Override
+    public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+        mSystemSupport.setTouchExplorationPassthroughRegion(displayId, region);
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
index efddd86..020f225 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityInputFilter.java
@@ -17,6 +17,7 @@
 package com.android.server.accessibility;
 
 import android.content.Context;
+import android.graphics.Region;
 import android.os.PowerManager;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -726,4 +727,16 @@
             return shouldProcess;
         }
     }
+
+    public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+        if (region != null && mTouchExplorer.contains(displayId)) {
+            mTouchExplorer.get(displayId).setGestureDetectionPassthroughRegion(region);
+        }
+    }
+
+    public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+        if (region != null && mTouchExplorer.contains(displayId)) {
+            mTouchExplorer.get(displayId).setTouchExplorationPassthroughRegion(region);
+        }
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 055bb4c..60c3d78 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -2879,11 +2879,8 @@
         @Override
         public void onDisplayRemoved(int displayId) {
             synchronized (mLock) {
-                for (int i = 0; i < mDisplaysList.size(); i++) {
-                    if (mDisplaysList.get(i).getDisplayId() == displayId) {
-                        mDisplaysList.remove(i);
-                        break;
-                    }
+                if (!removeDisplayFromList(displayId)) {
+                    return;
                 }
                 if (mInputFilter != null) {
                     mInputFilter.onDisplayChanged();
@@ -2903,6 +2900,17 @@
             mA11yWindowManager.stopTrackingWindows(displayId);
         }
 
+        @GuardedBy("mLock")
+        private boolean removeDisplayFromList(int displayId) {
+            for (int i = 0; i < mDisplaysList.size(); i++) {
+                if (mDisplaysList.get(i).getDisplayId() == displayId) {
+                    mDisplaysList.remove(i);
+                    return true;
+                }
+            }
+            return false;
+        }
+
         @Override
         public void onDisplayChanged(int displayId) {
             /* do nothing */
@@ -2914,8 +2922,8 @@
             }
             // Private virtual displays are created by the ap and is not allowed to access by other
             // aps. We assume we could ignore them.
-            if ((display.getType() == Display.TYPE_VIRTUAL
-                    && (display.getFlags() & Display.FLAG_PRIVATE) != 0)) {
+            if (display.getType() == Display.TYPE_VIRTUAL
+                    && (display.getFlags() & Display.FLAG_PRIVATE) != 0) {
                 return false;
             }
             return true;
@@ -3058,4 +3066,40 @@
             }
         }
     }
+
+    @Override
+    public void setGestureDetectionPassthroughRegion(int displayId, Region region) {
+        mMainHandler.sendMessage(
+                obtainMessage(
+                        AccessibilityManagerService::setGestureDetectionPassthroughRegionInternal,
+                        this,
+                        displayId,
+                        region));
+    }
+
+    @Override
+    public void setTouchExplorationPassthroughRegion(int displayId, Region region) {
+        mMainHandler.sendMessage(
+                obtainMessage(
+                        AccessibilityManagerService::setTouchExplorationPassthroughRegionInternal,
+                        this,
+                        displayId,
+                        region));
+    }
+
+    private void setTouchExplorationPassthroughRegionInternal(int displayId, Region region) {
+        synchronized (mLock) {
+            if (mHasInputFilter && mInputFilter != null) {
+                mInputFilter.setTouchExplorationPassthroughRegion(displayId, region);
+            }
+        }
+    }
+
+    private void setGestureDetectionPassthroughRegionInternal(int displayId, Region region) {
+        synchronized (mLock) {
+            if (mHasInputFilter && mInputFilter != null) {
+                mInputFilter.setGestureDetectionPassthroughRegion(displayId, region);
+            }
+        }
+    }
 }
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
index 8c00581..446e882 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityWindowManager.java
@@ -43,6 +43,7 @@
 import android.view.accessibility.AccessibilityWindowInfo;
 import android.view.accessibility.IAccessibilityInteractionConnection;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.accessibility.AccessibilitySecurityPolicy.AccessibilityUserManager;
 import com.android.server.wm.WindowManagerInternal;
 
@@ -781,7 +782,9 @@
     /**
      * Wrapper of accessibility interaction connection for window.
      */
-    final class RemoteAccessibilityConnection implements IBinder.DeathRecipient {
+    // In order to avoid using DexmakerShareClassLoaderRule, make this class visible for testing.
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public final class RemoteAccessibilityConnection implements IBinder.DeathRecipient {
         private final int mUid;
         private final String mPackageName;
         private final int mWindowId;
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index 11dcfef..ef8d524 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -193,7 +193,8 @@
     /**
      * This method returns the list of available system actions.
      */
-    List<AccessibilityAction> getSystemActions() {
+    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+    public List<AccessibilityAction> getSystemActions() {
         List<AccessibilityAction> systemActions = new ArrayList<>();
         synchronized (mSystemActionLock) {
             for (Map.Entry<Integer, RemoteAction> entry : mRegisteredSystemActions.entrySet()) {
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
index 2cc11c5..61c6ef5 100644
--- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java
@@ -23,6 +23,7 @@
 import android.accessibilityservice.AccessibilityGestureEvent;
 import android.content.Context;
 import android.graphics.Point;
+import android.graphics.Region;
 import android.os.Handler;
 import android.util.Slog;
 import android.view.InputDevice;
@@ -120,6 +121,8 @@
     // Context in which this explorer operates.
     private final Context mContext;
 
+    private Region mGestureDetectionPassthroughRegion;
+    private Region mTouchExplorationPassthroughRegion;
 
 /**
      * Creates a new instance.
@@ -165,6 +168,8 @@
         } else {
             mGestureDetector = detector;
         }
+        mGestureDetectionPassthroughRegion = new Region();
+        mTouchExplorationPassthroughRegion = new Region();
     }
 
     @Override
@@ -230,10 +235,11 @@
         }
 
         mState.onReceivedMotionEvent(rawEvent);
-
-        if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
-            // Event was handled by the gesture detector.
-            return;
+        if (shouldPerformGestureDetection(event)) {
+            if (mGestureDetector.onMotionEvent(event, rawEvent, policyFlags)) {
+                // Event was handled by the gesture detector.
+                return;
+            }
         }
 
         if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
@@ -418,6 +424,21 @@
             mSendTouchExplorationEndDelayed.forceSendAndRemove();
             mSendTouchInteractionEndDelayed.forceSendAndRemove();
             mDispatcher.sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
+            if (mTouchExplorationPassthroughRegion.contains(
+                    (int) event.getX(), (int) event.getY())) {
+                // The touch exploration passthrough overrides the gesture detection passthrough in
+                // the event they overlap.
+                // Pass this entire gesture through to the system as-is.
+                mState.startDelegating();
+                event = MotionEvent.obtainNoHistory(event);
+                mDispatcher.sendMotionEvent(
+                        event, event.getAction(), rawEvent, ALL_POINTER_ID_BITS, policyFlags);
+                mSendHoverEnterAndMoveDelayed.cancel();
+            } else if (mGestureDetectionPassthroughRegion.contains(
+                    (int) event.getX(), (int) event.getY())) {
+                // Jump straight to touch exploration.
+                mSendHoverEnterAndMoveDelayed.forceSendAndRemove();
+            }
         } else {
             // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double tap.
             mSendTouchInteractionEndDelayed.cancel();
@@ -909,6 +930,29 @@
         mGestureDetector.setMultiFingerGesturesEnabled(enabled);
     }
 
+    public void setGestureDetectionPassthroughRegion(Region region) {
+        mGestureDetectionPassthroughRegion = region;
+    }
+
+    public void setTouchExplorationPassthroughRegion(Region region) {
+        mTouchExplorationPassthroughRegion = region;
+    }
+
+    private boolean shouldPerformGestureDetection(MotionEvent event) {
+        if (mState.isDelegating()) {
+            return false;
+        }
+        if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
+            final int x = (int) event.getX();
+            final int y = (int) event.getY();
+            if (mTouchExplorationPassthroughRegion.contains(x, y)
+                    || mGestureDetectionPassthroughRegion.contains(x, y)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
      * Class for delayed exiting from gesture detecting mode.
      */
@@ -1135,5 +1179,4 @@
                 + ", mTempPoint: " + mTempPoint
                 + " }";
     }
-
 }
diff --git a/services/api/current.txt b/services/api/current.txt
index 8a82e61..26a65f2 100644
--- a/services/api/current.txt
+++ b/services/api/current.txt
@@ -3,9 +3,9 @@
 
   public interface RuntimePermissionsPersistence {
     method @NonNull public static com.android.permission.persistence.RuntimePermissionsPersistence createInstance();
-    method public void delete(@NonNull android.os.UserHandle);
-    method @Nullable public com.android.permission.persistence.RuntimePermissionsState read(@NonNull android.os.UserHandle);
-    method public void write(@NonNull com.android.permission.persistence.RuntimePermissionsState, @NonNull android.os.UserHandle);
+    method public void deleteAsUser(@NonNull android.os.UserHandle);
+    method @Nullable public com.android.permission.persistence.RuntimePermissionsState readAsUser(@NonNull android.os.UserHandle);
+    method public void writeAsUser(@NonNull com.android.permission.persistence.RuntimePermissionsState, @NonNull android.os.UserHandle);
   }
 
   public final class RuntimePermissionsState {
@@ -30,9 +30,9 @@
 
   public interface RolesPersistence {
     method @NonNull public static com.android.role.persistence.RolesPersistence createInstance();
-    method public void delete(@NonNull android.os.UserHandle);
-    method @Nullable public com.android.role.persistence.RolesState read(@NonNull android.os.UserHandle);
-    method public void write(@NonNull com.android.role.persistence.RolesState, @NonNull android.os.UserHandle);
+    method public void deleteAsUser(@NonNull android.os.UserHandle);
+    method @Nullable public com.android.role.persistence.RolesState readAsUser(@NonNull android.os.UserHandle);
+    method public void writeAsUser(@NonNull com.android.role.persistence.RolesState, @NonNull android.os.UserHandle);
   }
 
   public final class RolesState {
diff --git a/services/api/lint-baseline.txt b/services/api/lint-baseline.txt
new file mode 100644
index 0000000..e985ddb
--- /dev/null
+++ b/services/api/lint-baseline.txt
@@ -0,0 +1,5 @@
+// Baseline format: 1.0
+ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder):
+    Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder)}
+ProtectedMember: com.android.server.SystemService#publishBinderService(String, android.os.IBinder, boolean):
+    Protected methods not allowed; must be public: method com.android.server.SystemService.publishBinderService(String,android.os.IBinder,boolean)}
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 7151d2b..a8a2791 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -281,7 +281,7 @@
     }
 
     private void computeMaximumWidgetBitmapMemory() {
-        Display display = mContext.getDisplay();
+        Display display = mContext.getDisplayNoVerify();
         Point size = new Point();
         display.getRealSize(size);
         // Cap memory usage at 1.5 times the size of the display
diff --git a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
index 1fc48d2..6daa106 100644
--- a/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
+++ b/services/autofill/java/com/android/server/autofill/InlineSuggestionSession.java
@@ -21,6 +21,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.autofill.AutofillId;
@@ -29,6 +30,7 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
 import com.android.internal.view.IInlineSuggestionsResponseCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 import com.android.server.inputmethod.InputMethodManagerInternal;
 
 import java.util.concurrent.CancellationException;
@@ -71,8 +73,10 @@
         synchronized (mLock) {
             cancelCurrentRequest();
             mPendingImeResponse = new CompletableFuture<>();
+            // TODO(b/146454892): pipe the uiExtras from the ExtServices.
             mInputMethodManagerInternal.onCreateInlineSuggestionsRequest(
-                    mUserId, mComponentName, currentViewId,
+                    mUserId,
+                    new InlineSuggestionsRequestInfo(mComponentName, currentViewId, new Bundle()),
                     new InlineSuggestionsRequestCallbackImpl(mPendingImeResponse));
         }
     }
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 697e5d7..317ce4c 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -1158,6 +1158,18 @@
             } catch (RemoteException e) {
                 Slog.e(TAG, "Error requesting to hide fill UI", e);
             }
+            try {
+                final InlineSuggestionSession.ImeResponse imeResponse =
+                        mInlineSuggestionSession.waitAndGetImeResponse();
+                if (imeResponse == null) {
+                    Log.w(TAG, "Session input method callback is not set yet");
+                    return;
+                }
+                imeResponse.getCallback().onInlineSuggestionsResponse(
+                        new InlineSuggestionsResponse(Collections.EMPTY_LIST));
+            } catch (RemoteException e) {
+                Slog.e(TAG, "RemoteException hiding inline suggestions");
+            }
         }
     }
 
@@ -2624,6 +2636,8 @@
                 mService.getServicePackageName(), mComponentName,
                 serviceLabel, serviceIcon, this, id, mCompatMode);
 
+        mService.logDatasetShown(id, mClientState);
+
         synchronized (mLock) {
             if (mUiShownTime == 0) {
                 // Log first time UI is shown.
diff --git a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
index 813fc8d..14bd7d7 100644
--- a/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
+++ b/services/autofill/java/com/android/server/autofill/ui/CustomScrollView.java
@@ -75,7 +75,7 @@
         final TypedValue typedValue = new TypedValue();
         final Point point = new Point();
         final Context context = getContext();
-        context.getDisplay().getSize(point);
+        context.getDisplayNoVerify().getSize(point);
         context.getTheme().resolveAttribute(R.attr.autofillSaveCustomSubtitleMaxHeight,
                 typedValue, true);
         final View child = getChildAt(0);
diff --git a/services/autofill/java/com/android/server/autofill/ui/FillUi.java b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
index 5dc43ef..344b92f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/FillUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/FillUi.java
@@ -165,7 +165,7 @@
         // In full screen we only initialize size once assuming screen size never changes
         if (mFullScreen) {
             final Point outPoint = mTempPoint;
-            mContext.getDisplay().getSize(outPoint);
+            mContext.getDisplayNoVerify().getSize(outPoint);
             // full with of screen and half height of screen
             mContentWidth = LayoutParams.MATCH_PARENT;
             mContentHeight = outPoint.y / 2;
@@ -559,7 +559,7 @@
     }
 
     private static void resolveMaxWindowSize(Context context, Point outPoint) {
-        context.getDisplay().getSize(outPoint);
+        context.getDisplayNoVerify().getSize(outPoint);
         final TypedValue typedValue = sTempTypedValue;
         context.getTheme().resolveAttribute(R.attr.autofillDatasetPickerMaxWidth,
                 typedValue, true);
diff --git a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
index a8886fc..17cdf61 100644
--- a/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
+++ b/services/autofill/java/com/android/server/autofill/ui/InlineSuggestionFactory.java
@@ -82,12 +82,17 @@
         if (sDebug) Slog.d(TAG, "createInlineSuggestionsResponse called");
         final BiConsumer<Dataset, Integer> onClickFactory;
         if (response.getAuthentication() != null) {
-            onClickFactory = (dataset, datasetIndex) -> client.authenticate(response.getRequestId(),
-                    datasetIndex, response.getAuthentication(), response.getClientState(),
-                    /* authenticateInline= */ true);
+            onClickFactory = (dataset, datasetIndex) -> {
+                client.requestHideFillUi(autofillId);
+                client.authenticate(response.getRequestId(),
+                        datasetIndex, response.getAuthentication(), response.getClientState(),
+                        /* authenticateInline= */ true);
+            };
         } else {
-            onClickFactory = (dataset, datasetIndex) ->
-                    client.fill(response.getRequestId(), datasetIndex, dataset);
+            onClickFactory = (dataset, datasetIndex) -> {
+                client.requestHideFillUi(autofillId);
+                client.fill(response.getRequestId(), datasetIndex, dataset);
+            };
         }
 
         final List<Dataset> datasetList = response.getDatasets();
diff --git a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
index 3c37f73..e434be6 100644
--- a/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
+++ b/services/backup/java/com/android/server/backup/restore/PerformUnifiedRestoreTask.java
@@ -76,9 +76,7 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
@@ -802,6 +800,7 @@
             final int size = in.getDataSize();
 
             if (excludedKeysForPackage != null && excludedKeysForPackage.contains(key)) {
+                Slog.i(TAG, "Skipping blocked key " + key);
                 in.skipEntityData();
                 continue;
             }
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 6fc6084..228d9be 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -113,6 +113,7 @@
         "android.hardware.broadcastradio-V2.0-java",
         "android.hardware.health-V1.0-java",
         "android.hardware.health-V2.0-java",
+        "android.hardware.health-V2.1-java",
         "android.hardware.light-java",
         "android.hardware.weaver-V1.0-java",
         "android.hardware.biometrics.face-V1.1-java",
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 63d0924..0f8d57e 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -29,8 +29,7 @@
 import android.content.pm.PackageManager.ComponentInfoFlags;
 import android.content.pm.PackageManager.PackageInfoFlags;
 import android.content.pm.PackageManager.ResolveInfoFlags;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedMainComponent;
 import android.os.Bundle;
 import android.os.PersistableBundle;
 import android.util.ArrayMap;
@@ -38,6 +37,8 @@
 import android.util.SparseArray;
 
 import com.android.server.pm.PackageList;
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.IOException;
 import java.lang.annotation.Retention;
@@ -69,6 +70,25 @@
     public static final int PACKAGE_COMPANION = 14;
     public static final int PACKAGE_RETAIL_DEMO = 15;
 
+    @IntDef(flag = true, prefix = "RESOLVE_", value = {
+            RESOLVE_NON_BROWSER_ONLY,
+            RESOLVE_NON_RESOLVER_ONLY
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface PrivateResolveFlags {}
+
+    /**
+     * Internal {@link #resolveIntent(Intent, String, int, int, int, boolean, int)} flag:
+     * only match components that contain a generic web intent filter.
+     */
+    public static final int RESOLVE_NON_BROWSER_ONLY = 0x00000001;
+
+    /**
+     * Internal {@link #resolveIntent(Intent, String, int, int, int, boolean, int)} flag: do not
+     * match to the resolver.
+     */
+    public static final int RESOLVE_NON_RESOLVER_ONLY = 0x00000002;
+
     @IntDef(value = {
             INTEGRITY_VERIFICATION_ALLOW,
             INTEGRITY_VERIFICATION_REJECT,
@@ -507,7 +527,8 @@
      * Resolves an activity intent, allowing instant apps to be resolved.
      */
     public abstract ResolveInfo resolveIntent(Intent intent, String resolvedType,
-            int flags, int userId, boolean resolveForStart, int filterCallingUid);
+            int flags, @PrivateResolveFlags int privateResolveFlags, int userId,
+            boolean resolveForStart, int filterCallingUid);
 
     /**
     * Resolves a service intent, allowing instant apps to be resolved.
@@ -566,9 +587,7 @@
      */
     public abstract @Nullable AndroidPackage getPackage(@NonNull String packageName);
 
-    // TODO(b/135203078): PackageSetting can't be referenced directly. Should move to a server side
-    //  internal PM which is aware of PS.
-    public abstract @Nullable Object getPackageSetting(String packageName);
+    public abstract @Nullable PackageSetting getPackageSetting(String packageName);
 
     /**
      * Returns a package for the given UID. If the UID is part of a shared user ID, one
@@ -605,18 +624,17 @@
      */
     public abstract void removePackageListObserver(@NonNull PackageListObserver observer);
 
-    // TODO(b/135203078): PackageSetting can't be referenced directly
     /**
      * Returns a package object for the disabled system package name.
      */
-    public abstract @Nullable Object getDisabledSystemPackage(@NonNull String packageName);
+    public abstract @Nullable PackageSetting getDisabledSystemPackage(@NonNull String packageName);
 
     /**
      * Returns the package name for the disabled system package.
      *
      * This is equivalent to
      * {@link #getDisabledSystemPackage(String)}
-     *     .{@link com.android.server.pm.PackageSetting#pkg}
+     *     .{@link PackageSetting#pkg}
      *     .{@link AndroidPackage#getPackageName()}
      */
     public abstract @Nullable String getDisabledSystemPackageName(@NonNull String packageName);
@@ -657,7 +675,7 @@
     /**
      * Returns whether or not access to the application should be filtered.
      *
-     * @see #filterAppAccess(android.content.pm.PackageParser.Package, int, int)
+     * @see #filterAppAccess(AndroidPackage, int, int)
      */
     public abstract boolean filterAppAccess(
             @NonNull String packageName, int callingUid, int userId);
@@ -743,21 +761,29 @@
             throws IOException;
 
     /** Returns {@code true} if the specified component is enabled and matches the given flags. */
-    public abstract boolean isEnabledAndMatches(
-            @NonNull ComponentParseUtils.ParsedComponent component, int flags, int userId);
+    public abstract boolean isEnabledAndMatches(@NonNull ParsedMainComponent component, int flags,
+            int userId);
 
     /** Returns {@code true} if the given user requires extra badging for icons. */
     public abstract boolean userNeedsBadging(int userId);
 
     /**
      * Perform the given action for each package.
-     * Note that packages lock will be held while performin the actions.
+     * Note that packages lock will be held while performing the actions.
      *
      * @param actionLocked action to be performed
      */
     public abstract void forEachPackage(Consumer<AndroidPackage> actionLocked);
 
     /**
+     * Perform the given action for each {@link PackageSetting}.
+     * Note that packages lock will be held while performing the actions.
+     *
+     * @param actionLocked action to be performed
+     */
+    public abstract void forEachPackageSetting(Consumer<PackageSetting> actionLocked);
+
+    /**
      * Perform the given action for each installed package for a user.
      * Note that packages lock will be held while performin the actions.
      */
@@ -925,4 +951,9 @@
      */
     public abstract void setIntegrityVerificationResult(int verificationId,
             @IntegrityVerificationResult int verificationResult);
+
+    /**
+     * Returns MIME types contained in {@code mimeGroup} from {@code packageName} package
+     */
+    public abstract List<String> getMimeGroup(String packageName, String mimeGroup);
 }
diff --git a/services/core/java/com/android/server/BatteryService.java b/services/core/java/com/android/server/BatteryService.java
index c8894e7..f1f5005 100644
--- a/services/core/java/com/android/server/BatteryService.java
+++ b/services/core/java/com/android/server/BatteryService.java
@@ -27,8 +27,10 @@
 import android.database.ContentObserver;
 import android.hardware.health.V1_0.HealthInfo;
 import android.hardware.health.V2_0.IHealth;
-import android.hardware.health.V2_0.IHealthInfoCallback;
 import android.hardware.health.V2_0.Result;
+import android.hardware.health.V2_1.BatteryCapacityLevel;
+import android.hardware.health.V2_1.Constants;
+import android.hardware.health.V2_1.IHealthInfoCallback;
 import android.hidl.manager.V1_0.IServiceManager;
 import android.hidl.manager.V1_0.IServiceNotification;
 import android.metrics.LogMaker;
@@ -145,6 +147,7 @@
 
     private HealthInfo mHealthInfo;
     private final HealthInfo mLastHealthInfo = new HealthInfo();
+    private android.hardware.health.V2_1.HealthInfo mHealthInfo2p1;
     private boolean mBatteryLevelCritical;
     private int mLastBatteryStatus;
     private int mLastBatteryHealth;
@@ -359,6 +362,9 @@
     }
 
     private boolean shouldShutdownLocked() {
+        if (mHealthInfo2p1.batteryCapacityLevel != BatteryCapacityLevel.UNSUPPORTED) {
+            return (mHealthInfo2p1.batteryCapacityLevel == BatteryCapacityLevel.CRITICAL);
+        }
         if (mHealthInfo.batteryLevel > 0) {
             return false;
         }
@@ -416,22 +422,23 @@
         }
     }
 
-    private void update(android.hardware.health.V2_0.HealthInfo info) {
+    private void update(android.hardware.health.V2_1.HealthInfo info) {
         traceBegin("HealthInfoUpdate");
 
         Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryChargeCounter",
-                info.legacy.batteryChargeCounter);
+                info.legacy.legacy.batteryChargeCounter);
         Trace.traceCounter(Trace.TRACE_TAG_POWER, "BatteryCurrent",
-                info.legacy.batteryCurrent);
+                info.legacy.legacy.batteryCurrent);
 
         synchronized (mLock) {
             if (!mUpdatesStopped) {
-                mHealthInfo = info.legacy;
+                mHealthInfo = info.legacy.legacy;
+                mHealthInfo2p1 = info;
                 // Process the new values.
                 processValuesLocked(false);
                 mLock.notifyAll(); // for any waiters on new info
             } else {
-                copy(mLastHealthInfo, info.legacy);
+                copy(mLastHealthInfo, info.legacy.legacy);
             }
         }
         traceEnd();
@@ -485,7 +492,8 @@
             mBatteryStats.setBatteryState(mHealthInfo.batteryStatus, mHealthInfo.batteryHealth,
                     mPlugType, mHealthInfo.batteryLevel, mHealthInfo.batteryTemperature,
                     mHealthInfo.batteryVoltage, mHealthInfo.batteryChargeCounter,
-                    mHealthInfo.batteryFullCharge);
+                    mHealthInfo.batteryFullCharge,
+                    mHealthInfo2p1.batteryChargeTimeToFullNowSeconds);
         } catch (RemoteException e) {
             // Should never happen.
         }
@@ -1123,8 +1131,21 @@
     private final class HealthHalCallback extends IHealthInfoCallback.Stub
             implements HealthServiceWrapper.Callback {
         @Override public void healthInfoChanged(android.hardware.health.V2_0.HealthInfo props) {
+            android.hardware.health.V2_1.HealthInfo propsLatest =
+                    new android.hardware.health.V2_1.HealthInfo();
+            propsLatest.legacy = props;
+
+            propsLatest.batteryCapacityLevel = BatteryCapacityLevel.UNSUPPORTED;
+            propsLatest.batteryChargeTimeToFullNowSeconds =
+                Constants.BATTERY_CHARGE_TIME_TO_FULL_NOW_SECONDS_UNSUPPORTED;
+
+            BatteryService.this.update(propsLatest);
+        }
+
+        @Override public void healthInfoChanged_2_1(android.hardware.health.V2_1.HealthInfo props) {
             BatteryService.this.update(props);
         }
+
         // on new service registered
         @Override public void onRegistration(IHealth oldService, IHealth newService,
                 String instance) {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 0f36260..e48ef5a 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -1534,7 +1534,8 @@
     }
 
     @Override
-    public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(int userId) {
+    public NetworkCapabilities[] getDefaultNetworkCapabilitiesForUser(
+                int userId, String callingPackageName) {
         // The basic principle is: if an app's traffic could possibly go over a
         // network, without the app doing anything multinetwork-specific,
         // (hence, by "default"), then include that network's capabilities in
@@ -1556,7 +1557,10 @@
         NetworkAgentInfo nai = getDefaultNetwork();
         NetworkCapabilities nc = getNetworkCapabilitiesInternal(nai);
         if (nc != null) {
-            result.put(nai.network, nc);
+            result.put(
+                    nai.network,
+                    maybeSanitizeLocationInfoForCaller(
+                            nc, Binder.getCallingUid(), callingPackageName));
         }
 
         synchronized (mVpns) {
@@ -1566,10 +1570,12 @@
                     Network[] networks = vpn.getUnderlyingNetworks();
                     if (networks != null) {
                         for (Network network : networks) {
-                            nai = getNetworkAgentInfoForNetwork(network);
-                            nc = getNetworkCapabilitiesInternal(nai);
+                            nc = getNetworkCapabilitiesInternal(network);
                             if (nc != null) {
-                                result.put(network, nc);
+                                result.put(
+                                        network,
+                                        maybeSanitizeLocationInfoForCaller(
+                                                nc, Binder.getCallingUid(), callingPackageName));
                             }
                         }
                     }
@@ -1636,20 +1642,26 @@
         }
     }
 
+    private NetworkCapabilities getNetworkCapabilitiesInternal(Network network) {
+        return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
+    }
+
     private NetworkCapabilities getNetworkCapabilitiesInternal(NetworkAgentInfo nai) {
         if (nai == null) return null;
         synchronized (nai) {
             if (nai.networkCapabilities == null) return null;
             return networkCapabilitiesRestrictedForCallerPermissions(
-                    nai.networkCapabilities,
-                    Binder.getCallingPid(), Binder.getCallingUid());
+                    nai.networkCapabilities, Binder.getCallingPid(), Binder.getCallingUid());
         }
     }
 
     @Override
-    public NetworkCapabilities getNetworkCapabilities(Network network) {
+    public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
+        mAppOpsManager.checkPackage(Binder.getCallingUid(), callingPackageName);
         enforceAccessPermission();
-        return getNetworkCapabilitiesInternal(getNetworkAgentInfoForNetwork(network));
+        return maybeSanitizeLocationInfoForCaller(
+                getNetworkCapabilitiesInternal(network),
+                Binder.getCallingUid(), callingPackageName);
     }
 
     @VisibleForTesting
@@ -1665,20 +1677,34 @@
         }
         newNc.setAdministratorUids(Collections.EMPTY_LIST);
 
-        maybeSanitizeLocationInfoForCaller(newNc, callerUid);
-
         return newNc;
     }
 
-    private void maybeSanitizeLocationInfoForCaller(
-            NetworkCapabilities nc, int callerUid) {
-        // TODO(b/142072839): Conditionally reset the owner UID if the following
-        // conditions are not met:
-        // 1. The destination app is the network owner
-        // 2. The destination app has the ACCESS_COARSE_LOCATION permission granted
-        // if target SDK<29 or otherwise has the ACCESS_FINE_LOCATION permission granted
-        // 3. The user's location toggle is on
-        nc.setOwnerUid(INVALID_UID);
+    @VisibleForTesting
+    @Nullable
+    NetworkCapabilities maybeSanitizeLocationInfoForCaller(
+            @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) {
+        if (nc == null) {
+            return null;
+        }
+        final NetworkCapabilities newNc = new NetworkCapabilities(nc);
+        if (callerUid != newNc.getOwnerUid()) {
+            newNc.setOwnerUid(INVALID_UID);
+            return newNc;
+        }
+
+        Binder.withCleanCallingIdentity(
+                () -> {
+                    if (!mLocationPermissionChecker.checkLocationPermission(
+                            callerPkgName, null /* featureId */, callerUid, null /* message */)) {
+                        // Caller does not have the requisite location permissions. Reset the
+                        // owner's UID in the NetworkCapabilities.
+                        newNc.setOwnerUid(INVALID_UID);
+                    }
+                }
+        );
+
+        return newNc;
     }
 
     private LinkProperties linkPropertiesRestrictedForCallerPermissions(
@@ -1753,7 +1779,7 @@
     public boolean isActiveNetworkMetered() {
         enforceAccessPermission();
 
-        final NetworkCapabilities caps = getNetworkCapabilities(getActiveNetwork());
+        final NetworkCapabilities caps = getNetworkCapabilitiesInternal(getActiveNetwork());
         if (caps != null) {
             return !caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED);
         } else {
@@ -3430,16 +3456,16 @@
             // there is hope for it to become one if it validated, then it is needed.
             ensureRunningOnConnectivityServiceThread();
             if (nri.request.isRequest() && nai.satisfies(nri.request) &&
-                    (nai.isSatisfyingRequest(nri.request.requestId) ||
-                    // Note that this catches two important cases:
-                    // 1. Unvalidated cellular will not be reaped when unvalidated WiFi
-                    //    is currently satisfying the request.  This is desirable when
-                    //    cellular ends up validating but WiFi does not.
-                    // 2. Unvalidated WiFi will not be reaped when validated cellular
-                    //    is currently satisfying the request.  This is desirable when
-                    //    WiFi ends up validating and out scoring cellular.
-                    nri.mSatisfier.getCurrentScore()
-                            < nai.getCurrentScoreAsValidated())) {
+                    (nai.isSatisfyingRequest(nri.request.requestId)
+                    // Note that canPossiblyBeat catches two important cases:
+                    // 1. Unvalidated slow networks will not be reaped when an unvalidated fast
+                    // network is currently satisfying the request. This is desirable for example
+                    // when cellular ends up validating but WiFi/Ethernet does not.
+                    // 2. Fast networks will not be reaped when a validated slow network is
+                    // currently satisfying the request. This is desirable for example when
+                    // Ethernet ends up validating and out scoring WiFi, or WiFi/Ethernet ends
+                    // up validating and out scoring cellular.
+                            || nai.canPossiblyBeat(nri.mSatisfier))) {
                 return false;
             }
         }
@@ -4791,7 +4817,7 @@
                 return false;
             }
 
-            return vpn.startAlwaysOnVpn();
+            return vpn.startAlwaysOnVpn(mKeyStore);
         }
     }
 
@@ -4806,7 +4832,7 @@
                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
                 return false;
             }
-            return vpn.isAlwaysOnPackageSupported(packageName);
+            return vpn.isAlwaysOnPackageSupported(packageName, mKeyStore);
         }
     }
 
@@ -4827,11 +4853,11 @@
                 Slog.w(TAG, "User " + userId + " has no Vpn configuration");
                 return false;
             }
-            if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist)) {
+            if (!vpn.setAlwaysOnPackage(packageName, lockdown, lockdownWhitelist, mKeyStore)) {
                 return false;
             }
             if (!startAlwaysOnVpn(userId)) {
-                vpn.setAlwaysOnPackage(null, false, null);
+                vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
                 return false;
             }
         }
@@ -5017,7 +5043,7 @@
                 loge("Starting user already has a VPN");
                 return;
             }
-            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId);
+            userVpn = new Vpn(mHandler.getLooper(), mContext, mNMS, userId, mKeyStore);
             mVpns.put(userId, userVpn);
             if (mUserManager.getUserInfo(userId).isPrimary() && LockdownVpnTracker.isEnabled()) {
                 updateLockdownVpn();
@@ -5088,7 +5114,7 @@
             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
                 Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
                         + userId);
-                vpn.startAlwaysOnVpn();
+                vpn.startAlwaysOnVpn(mKeyStore);
             }
         }
     }
@@ -5110,7 +5136,7 @@
             if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
                 Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
                         + userId);
-                vpn.setAlwaysOnPackage(null, false, null);
+                vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
             }
         }
     }
@@ -5330,8 +5356,8 @@
         }
 
         public String toString() {
-            return "uid/pid:" + mUid + "/" + mPid + " " + request +
-                    (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
+            return "uid/pid:" + mUid + "/" + mPid + " " + request
+                    + (mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
         }
     }
 
@@ -6408,8 +6434,13 @@
         }
         switch (notificationType) {
             case ConnectivityManager.CALLBACK_AVAILABLE: {
-                putParcelable(bundle, networkCapabilitiesRestrictedForCallerPermissions(
-                        networkAgent.networkCapabilities, nri.mPid, nri.mUid));
+                final NetworkCapabilities nc =
+                        networkCapabilitiesRestrictedForCallerPermissions(
+                                networkAgent.networkCapabilities, nri.mPid, nri.mUid);
+                putParcelable(
+                        bundle,
+                        maybeSanitizeLocationInfoForCaller(
+                                nc, nri.mUid, nri.request.getRequestorPackageName()));
                 putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
                         networkAgent.linkProperties, nri.mPid, nri.mUid));
                 // For this notification, arg1 contains the blocked status.
@@ -6422,9 +6453,13 @@
             }
             case ConnectivityManager.CALLBACK_CAP_CHANGED: {
                 // networkAgent can't be null as it has been accessed a few lines above.
-                final NetworkCapabilities nc = networkCapabilitiesRestrictedForCallerPermissions(
-                        networkAgent.networkCapabilities, nri.mPid, nri.mUid);
-                putParcelable(bundle, nc);
+                final NetworkCapabilities netCap =
+                        networkCapabilitiesRestrictedForCallerPermissions(
+                                networkAgent.networkCapabilities, nri.mPid, nri.mUid);
+                putParcelable(
+                        bundle,
+                        maybeSanitizeLocationInfoForCaller(
+                                netCap, nri.mUid, nri.request.getRequestorPackageName()));
                 break;
             }
             case ConnectivityManager.CALLBACK_IP_CHANGED: {
diff --git a/services/core/java/com/android/server/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index deb94bd..7ec2a34 100644
--- a/services/core/java/com/android/server/IntentResolver.java
+++ b/services/core/java/com/android/server/IntentResolver.java
@@ -16,6 +16,7 @@
 
 package com.android.server;
 
+import android.annotation.NonNull;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.net.Uri;
@@ -44,29 +45,30 @@
 /**
  * {@hide}
  */
-public abstract class IntentResolver<F extends IntentFilter, R extends Object> {
+public abstract class IntentResolver<F, R extends Object> {
     final private static String TAG = "IntentResolver";
     final private static boolean DEBUG = false;
     final private static boolean localLOGV = DEBUG || false;
     final private static boolean localVerificationLOGV = DEBUG || false;
 
     public void addFilter(F f) {
+        IntentFilter intentFilter = getIntentFilter(f);
         if (localLOGV) {
             Slog.v(TAG, "Adding filter: " + f);
-            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
+            intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
             Slog.v(TAG, "    Building Lookup Maps:");
         }
 
         mFilters.add(f);
-        int numS = register_intent_filter(f, f.schemesIterator(),
+        int numS = register_intent_filter(f, intentFilter.schemesIterator(),
                 mSchemeToFilter, "      Scheme: ");
         int numT = register_mime_types(f, "      Type: ");
         if (numS == 0 && numT == 0) {
-            register_intent_filter(f, f.actionsIterator(),
+            register_intent_filter(f, intentFilter.actionsIterator(),
                     mActionToFilter, "      Action: ");
         }
         if (numT != 0) {
-            register_intent_filter(f, f.actionsIterator(),
+            register_intent_filter(f, intentFilter.actionsIterator(),
                     mTypedActionToFilter, "      TypedAction: ");
         }
     }
@@ -153,7 +155,7 @@
                 if (cur == null) {
                     break;
                 }
-                if (filterEquals(cur, matching)) {
+                if (filterEquals(getIntentFilter(cur), matching)) {
                     if (res == null) {
                         res = new ArrayList<>();
                     }
@@ -178,7 +180,7 @@
         } else {
             ArrayList<F> res = null;
             for (F cur : mFilters) {
-                if (filterEquals(cur, matching)) {
+                if (filterEquals(getIntentFilter(cur), matching)) {
                     if (res == null) {
                         res = new ArrayList<>();
                     }
@@ -194,22 +196,23 @@
         mFilters.remove(f);
     }
 
-    void removeFilterInternal(F f) {
+    protected void removeFilterInternal(F f) {
+        IntentFilter intentFilter = getIntentFilter(f);
         if (localLOGV) {
             Slog.v(TAG, "Removing filter: " + f);
-            f.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
+            intentFilter.dump(new LogPrinter(Log.VERBOSE, TAG, Log.LOG_ID_SYSTEM), "      ");
             Slog.v(TAG, "    Cleaning Lookup Maps:");
         }
 
-        int numS = unregister_intent_filter(f, f.schemesIterator(),
+        int numS = unregister_intent_filter(f, intentFilter.schemesIterator(),
                 mSchemeToFilter, "      Scheme: ");
         int numT = unregister_mime_types(f, "      Type: ");
         if (numS == 0 && numT == 0) {
-            unregister_intent_filter(f, f.actionsIterator(),
+            unregister_intent_filter(f, intentFilter.actionsIterator(),
                     mActionToFilter, "      Action: ");
         }
         if (numT != 0) {
-            unregister_intent_filter(f, f.actionsIterator(),
+            unregister_intent_filter(f, intentFilter.actionsIterator(),
                     mTypedActionToFilter, "      TypedAction: ");
         }
     }
@@ -272,7 +275,7 @@
                         if (printer == null) {
                             printer = new PrintWriterPrinter(out);
                         }
-                        filter.dump(printer, fprefix + "  ");
+                        getIntentFilter(filter).dump(printer, fprefix + "  ");
                     }
                 }
             }
@@ -527,7 +530,7 @@
      * @see android.content.IntentFilter#getAutoVerify()
      */
     protected boolean isFilterVerified(F filter) {
-        return filter.isVerified();
+        return getIntentFilter(filter).isVerified();
     }
 
     /**
@@ -591,7 +594,7 @@
     }
 
     private final int register_mime_types(F filter, String prefix) {
-        final Iterator<String> i = filter.typesIterator();
+        final Iterator<String> i = getIntentFilter(filter).typesIterator();
         if (i == null) {
             return 0;
         }
@@ -622,7 +625,7 @@
     }
 
     private final int unregister_mime_types(F filter, String prefix) {
-        final Iterator<String> i = filter.typesIterator();
+        final Iterator<String> i = getIntentFilter(filter).typesIterator();
         if (i == null) {
             return 0;
         }
@@ -651,7 +654,7 @@
         return num;
     }
 
-    private final int register_intent_filter(F filter, Iterator<String> i,
+    protected final int register_intent_filter(F filter, Iterator<String> i,
             ArrayMap<String, F[]> dest, String prefix) {
         if (i == null) {
             return 0;
@@ -667,7 +670,7 @@
         return num;
     }
 
-    private final int unregister_intent_filter(F filter, Iterator<String> i,
+    protected final int unregister_intent_filter(F filter, Iterator<String> i,
             ArrayMap<String, F[]> dest, String prefix) {
         if (i == null) {
             return 0;
@@ -762,12 +765,14 @@
             }
 
             // Are we verified ?
-            if (filter.getAutoVerify()) {
+            IntentFilter intentFilter = getIntentFilter(filter);
+            if (intentFilter.getAutoVerify()) {
                 if (localVerificationLOGV || debug) {
                     Slog.v(TAG, "  Filter verified: " + isFilterVerified(filter));
-                    int authorities = filter.countDataAuthorities();
+                    int authorities = intentFilter.countDataAuthorities();
                     for (int z = 0; z < authorities; z++) {
-                        Slog.v(TAG, "   " + filter.getDataAuthority(z).getHost());
+                        Slog.v(TAG, "   " + intentFilter.getDataAuthority(z)
+                                .getHost());
                     }
                 }
             }
@@ -780,12 +785,12 @@
                 continue;
             }
 
-            match = filter.match(action, resolvedType, scheme, data, categories, TAG);
+            match = intentFilter.match(action, resolvedType, scheme, data, categories, TAG);
             if (match >= 0) {
                 if (debug) Slog.v(TAG, "  Filter matched!  match=0x" +
                         Integer.toHexString(match) + " hasDefault="
-                        + filter.hasCategory(Intent.CATEGORY_DEFAULT));
-                if (!defaultOnly || filter.hasCategory(Intent.CATEGORY_DEFAULT)) {
+                        + intentFilter.hasCategory(Intent.CATEGORY_DEFAULT));
+                if (!defaultOnly || intentFilter.hasCategory(Intent.CATEGORY_DEFAULT)) {
                     final R oneResult = newResult(filter, match, userId);
                     if (debug) Slog.v(TAG, "    Created result: " + oneResult);
                     if (oneResult != null) {
@@ -793,7 +798,7 @@
                         if (debug) {
                             dumpFilter(logPrintWriter, "    ", filter);
                             logPrintWriter.flush();
-                            filter.dump(logPrinter, "    ");
+                            intentFilter.dump(logPrinter, "    ");
                         }
                     }
                 } else {
@@ -836,7 +841,7 @@
     /**
      * All filters that have been registered.
      */
-    private final ArraySet<F> mFilters = new ArraySet<F>();
+    protected final ArraySet<F> mFilters = new ArraySet<F>();
 
     /**
      * All of the MIME types that have been registered, such as "image/jpeg",
@@ -875,4 +880,11 @@
      * All of the actions that have been registered and specified a MIME type.
      */
     private final ArrayMap<String, F[]> mTypedActionToFilter = new ArrayMap<String, F[]>();
+
+    /**
+     * Rather than refactoring the entire class, this allows the input {@link F} to be a type
+     * other than {@link IntentFilter}, transforming it whenever necessary. It is valid to use
+     * {@link IntentFilter} directly as {@link F} and just return {@param input}.
+     */
+    protected abstract IntentFilter getIntentFilter(@NonNull F input);
 }
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 207a6aa..d515332 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -194,8 +194,6 @@
     // time
     private static final int MAX_PROVIDER_SCHEDULING_JITTER_MS = 100;
 
-    private static final String FEATURE_ID = "LocationService";
-
     private static final LocationRequest DEFAULT_LOCATION_REQUEST = new LocationRequest();
 
     private final Object mLock = new Object();
@@ -215,11 +213,6 @@
     private PackageManager mPackageManager;
     private PowerManager mPowerManager;
 
-    // TODO: sharing a location fudger with mock providers can leak information as the mock provider
-    //   can be used to retrieve offset information. the fudger should likely be reset whenever mock
-    //   providers are added or removed
-    private LocationFudger mLocationFudger;
-
     private GeofenceManager mGeofenceManager;
     private GeocoderProxy mGeocodeProvider;
 
@@ -245,7 +238,7 @@
     private int mBatterySaverMode;
 
     private LocationManagerService(Context context) {
-        mContext = context.createFeatureContext(FEATURE_ID);
+        mContext = context;
         mHandler = FgThread.getHandler();
         mLocalService = new LocalService();
 
@@ -287,8 +280,6 @@
             mPackageManager = mContext.getPackageManager();
             mAppOps = mContext.getSystemService(AppOpsManager.class);
             mPowerManager = mContext.getSystemService(PowerManager.class);
-
-            mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
             mGeofenceManager = new GeofenceManager(mContext, mSettingsHelper);
 
             PowerManagerInternal localPowerManager =
@@ -665,6 +656,8 @@
 
         private final String mName;
 
+        private final LocationFudger mLocationFudger;
+
         // if the provider is enabled for a given user id - null or not present means unknown
         @GuardedBy("mLock")
         private final SparseArray<Boolean> mEnabled;
@@ -682,6 +675,7 @@
 
         private LocationProviderManager(String name) {
             mName = name;
+            mLocationFudger = new LocationFudger(mSettingsHelper.getCoarseLocationAccuracyM());
             mEnabled = new SparseArray<>(2);
             mLastLocation = new SparseArray<>(2);
             mLastCoarseLocation = new SparseArray<>(2);
@@ -706,7 +700,9 @@
             synchronized (mLock) {
                 mProvider.setMockProvider(provider);
 
-                // when removing a mock provider, also clear any mock last locations
+                // when removing a mock provider, also clear any mock last locations and reset the
+                // location fudger. the mock provider could have been used to infer the current
+                // location fudger offsets.
                 if (provider == null) {
                     for (int i = 0; i < mLastLocation.size(); i++) {
                         Location lastLocation = mLastLocation.valueAt(i);
@@ -721,6 +717,8 @@
                             mLastCoarseLocation.setValueAt(i, null);
                         }
                     }
+
+                    mLocationFudger.resetOffsets();
                 }
             }
         }
@@ -864,10 +862,6 @@
             }
         }
 
-        public void requestSetAllowed(boolean allowed) {
-            mProvider.requestSetAllowed(allowed);
-        }
-
         public void onUserStarted(int userId) {
             synchronized (mLock) {
                 // clear the user's enabled state in order to force a reevalution of whether the
@@ -2933,18 +2927,6 @@
     private class LocalService extends LocationManagerInternal {
 
         @Override
-        public void requestSetProviderAllowed(String provider, boolean allowed) {
-            Preconditions.checkArgument(provider != null, "invalid null provider");
-
-            synchronized (mLock) {
-                LocationProviderManager manager = getLocationProviderManager(provider);
-                if (manager != null) {
-                    manager.requestSetAllowed(allowed);
-                }
-            }
-        }
-
-        @Override
         public boolean isProviderEnabledForUser(@NonNull String provider, int userId) {
             synchronized (mLock) {
                 LocationProviderManager manager = getLocationProviderManager(provider);
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 6fb7b26..93859b3 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -103,7 +103,7 @@
     private static boolean PROP_PIN_CAMERA =
             DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_RUNTIME_NATIVE_BOOT,
                                     "pin_camera",
-                                    SystemProperties.getBoolean("pinner.pin_camera", true));
+                                    SystemProperties.getBoolean("pinner.pin_camera", false));
     // Pin using pinlist.meta when pinning apps.
     private static boolean PROP_PIN_PINLIST = SystemProperties.getBoolean(
             "pinner.use_pinlist", true);
diff --git a/services/core/java/com/android/server/SensorNotificationService.java b/services/core/java/com/android/server/SensorNotificationService.java
index 9082dca..7f5befa 100644
--- a/services/core/java/com/android/server/SensorNotificationService.java
+++ b/services/core/java/com/android/server/SensorNotificationService.java
@@ -16,8 +16,10 @@
 
 package com.android.server;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.GeomagneticField;
 import android.hardware.Sensor;
 import android.hardware.SensorAdditionalInfo;
@@ -29,7 +31,9 @@
 import android.location.LocationManager;
 import android.os.Bundle;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Slog;
 
 public class SensorNotificationService extends SystemService
@@ -48,8 +52,6 @@
 
     private static final long MILLIS_2010_1_1 = 1262358000000l;
 
-    private static final String FEATURE_ID = "SensorNotificationService";
-
     private Context mContext;
     private SensorManager mSensorManager;
     private LocationManager mLocationManager;
@@ -59,8 +61,8 @@
     private long mLocalGeomagneticFieldUpdateTime = -LOCATION_MIN_TIME;
 
     public SensorNotificationService(Context context) {
-        super(context.createFeatureContext(FEATURE_ID));
-        mContext = getContext();
+        super(context);
+        mContext = context;
     }
 
     public void onStart() {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 53dbb93..d86b223 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -2120,8 +2120,6 @@
 
     private void unmount(VolumeInfo vol) {
         try {
-            mVold.unmount(vol.id);
-            mStorageSessionController.onVolumeUnmount(vol);
             try {
                 if (vol.type == VolumeInfo.TYPE_PRIVATE) {
                     mInstaller.onPrivateVolumeRemoved(vol.getFsUuid());
@@ -2129,6 +2127,8 @@
             } catch (Installer.InstallerException e) {
                 Slog.e(TAG, "Failed unmount mirror data", e);
             }
+            mVold.unmount(vol.id);
+            mStorageSessionController.onVolumeUnmount(vol);
         } catch (Exception e) {
             Slog.wtf(TAG, e);
         }
@@ -4346,6 +4346,42 @@
             mPolicies.add(policy);
         }
 
+        /**
+         * Check if fuse is running in target user, if it's running then setup its obb directories.
+         * TODO: System server should store a list of active pids that obb is not mounted and use it.
+         */
+        @Override
+        public void prepareObbDirs(int userId, Set<String> packageList, String processName) {
+            String fuseRunningUsersList = SystemProperties.get("vold.fuse_running_users", "");
+            String[] fuseRunningUsers = fuseRunningUsersList.split(",");
+            boolean fuseReady = false;
+            String targetUserId = String.valueOf(userId);
+            for (String user : fuseRunningUsers) {
+                if (targetUserId.equals(user)) {
+                    fuseReady = true;
+                }
+            }
+            if (fuseReady) {
+                try {
+                    final IVold vold = IVold.Stub.asInterface(
+                            ServiceManager.getServiceOrThrow("vold"));
+                    for (String pkg : packageList) {
+                        final String obbDir =
+                                String.format("/storage/emulated/%d/Android/obb", userId);
+                        final String packageObbDir = String.format("%s/%s/", obbDir, pkg);
+
+                        // Create package obb dir if it doesn't exist.
+                        File file = new File(packageObbDir);
+                        if (!file.exists()) {
+                            vold.setupAppDir(packageObbDir, mPmInternal.getPackage(pkg).getUid());
+                        }
+                    }
+                } catch (ServiceManager.ServiceNotFoundException | RemoteException e) {
+                    Slog.e(TAG, "Unable to create obb directories for " + processName, e);
+                }
+            }
+        }
+
         @Override
         public void onExternalStoragePolicyChanged(int uid, String packageName) {
             final int mountMode = getExternalStorageMountMode(uid, packageName);
@@ -4409,6 +4445,25 @@
             }
         }
 
+        @Override
+        public void prepareAppDataAfterInstall(String packageName, int uid) {
+            int userId = UserHandle.getUserId(uid);
+            final Environment.UserEnvironment userEnv = new Environment.UserEnvironment(userId);
+
+            // The installer may have downloaded OBBs for this newly installed application;
+            // make sure the OBB dir for the application is setup correctly, if it exists.
+            File[] packageObbDirs = userEnv.buildExternalStorageAppObbDirs(packageName);
+            for (File packageObbDir : packageObbDirs) {
+                try {
+                    mVold.fixupAppDir(packageObbDir.getCanonicalPath() + "/", uid);
+                } catch (IOException e) {
+                    Log.e(TAG, "Failed to get canonical path for " + packageName);
+                } catch (RemoteException e) {
+                    Log.e(TAG, "Failed to fixup app dir for " + packageName);
+                }
+            }
+        }
+
         public boolean hasExternalStorage(int uid, String packageName) {
             // No need to check for system uid. This avoids a deadlock between
             // PackageManagerService and AppOpsService.
diff --git a/services/core/java/com/android/server/Watchdog.java b/services/core/java/com/android/server/Watchdog.java
index a1ccd84..8900eee 100644
--- a/services/core/java/com/android/server/Watchdog.java
+++ b/services/core/java/com/android/server/Watchdog.java
@@ -100,7 +100,7 @@
         "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
         "media.swcodec", // /apex/com.android.media.swcodec/bin/mediaswcodec
         "com.android.bluetooth",  // Bluetooth service
-        "/system/bin/statsd",  // Stats daemon
+        "/apex/com.android.os.statsd/bin/statsd",  // Stats daemon
     };
 
     public static final List<String> HAL_INTERFACES_OF_INTEREST = Arrays.asList(
diff --git a/services/core/java/com/android/server/adb/AdbDebuggingManager.java b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
index 1099413..f16e3ce 100644
--- a/services/core/java/com/android/server/adb/AdbDebuggingManager.java
+++ b/services/core/java/com/android/server/adb/AdbDebuggingManager.java
@@ -29,6 +29,7 @@
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.debug.AdbProtoEnums;
+import android.debug.AdbTransportType;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
 import android.net.Uri;
@@ -722,13 +723,21 @@
     }
 
     /**
-     * When {@code enabled} is {@code true}, this allows ADB debugging and starts the ADB hanler
-     * thread. When {@code enabled} is {@code false}, this disallows ADB debugging and shuts
-     * down the handler thread.
+     * When {@code enabled} is {@code true}, this allows ADB debugging and starts the ADB handler
+     * thread. When {@code enabled} is {@code false}, this disallows ADB debugging for the given
+     * @{code transportType}. See {@link IAdbTransport} for all available transport types.
+     * If all transport types are disabled, the ADB handler thread will shut down.
      */
-    public void setAdbEnabled(boolean enabled) {
-        mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MESSAGE_ADB_ENABLED
-                                          : AdbDebuggingHandler.MESSAGE_ADB_DISABLED);
+    public void setAdbEnabled(boolean enabled, byte transportType) {
+        if (transportType == AdbTransportType.USB) {
+            mHandler.sendEmptyMessage(enabled ? AdbDebuggingHandler.MESSAGE_ADB_ENABLED
+                                              : AdbDebuggingHandler.MESSAGE_ADB_DISABLED);
+        } else if (transportType == AdbTransportType.WIFI) {
+            // TODO(joshuaduong): Not implemented
+        } else {
+            throw new IllegalArgumentException(
+                    "setAdbEnabled called with unimplemented transport type=" + transportType);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/adb/AdbService.java b/services/core/java/com/android/server/adb/AdbService.java
index c125b1b..0d161b9 100644
--- a/services/core/java/com/android/server/adb/AdbService.java
+++ b/services/core/java/com/android/server/adb/AdbService.java
@@ -15,19 +15,23 @@
  */
 package com.android.server.adb;
 
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.database.ContentObserver;
 import android.debug.AdbManagerInternal;
+import android.debug.AdbTransportType;
 import android.debug.IAdbManager;
 import android.debug.IAdbTransport;
+import android.debug.PairDevice;
 import android.hardware.usb.UsbManager;
+import android.net.Uri;
 import android.os.Binder;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
 import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
@@ -38,7 +42,6 @@
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 
-
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.dump.DualDumpOutputStream;
@@ -50,6 +53,7 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Collections;
+import java.util.Map;
 
 /**
  * The Android Debug Bridge (ADB) service. This controls the availability of ADB and authorization
@@ -77,7 +81,8 @@
             if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
                 mAdbService.systemReady();
             } else if (phase == SystemService.PHASE_BOOT_COMPLETED) {
-                mAdbService.bootCompleted();
+                FgThread.getHandler().sendMessage(obtainMessage(
+                        AdbService::bootCompleted, mAdbService));
             }
         }
     }
@@ -94,8 +99,14 @@
         }
 
         @Override
-        public boolean isAdbEnabled() {
-            return mAdbEnabled;
+        public boolean isAdbEnabled(byte transportType) {
+            if (transportType == AdbTransportType.USB) {
+                return mIsAdbUsbEnabled;
+            } else if (transportType == AdbTransportType.WIFI) {
+                return mIsAdbWifiEnabled;
+            }
+            throw new IllegalArgumentException(
+                    "isAdbEnabled called with unimplemented transport type=" + transportType);
         }
 
         @Override
@@ -109,77 +120,70 @@
         }
     }
 
-    private final class AdbHandler extends Handler {
-        AdbHandler(Looper looper) {
-            super(looper);
-            try {
-                /*
-                 * Use the normal bootmode persistent prop to maintain state of adb across
-                 * all boot modes.
-                 */
-                mAdbEnabled = containsFunction(
-                        SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
-                        UsbManager.USB_FUNCTION_ADB);
+    private void initAdbState() {
+        try {
+            /*
+             * Use the normal bootmode persistent prop to maintain state of adb across
+             * all boot modes.
+             */
+            mIsAdbUsbEnabled = containsFunction(
+                    SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY, ""),
+                    UsbManager.USB_FUNCTION_ADB);
+            // TODO(joshuaduong): Read the adb wifi state from a persistent system
+            // property (persist.sys.adb.wifi).
+            mIsAdbWifiEnabled = false;
 
-                // register observer to listen for settings changes
-                mContentResolver.registerContentObserver(
-                        Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
-                        false, new AdbSettingsObserver());
-            } catch (Exception e) {
-                Slog.e(TAG, "Error initializing AdbHandler", e);
-            }
-        }
-
-        private boolean containsFunction(String functions, String function) {
-            int index = functions.indexOf(function);
-            if (index < 0) return false;
-            if (index > 0 && functions.charAt(index - 1) != ',') return false;
-            int charAfter = index + function.length();
-            if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
-            return true;
-        }
-
-        public void sendMessage(int what, boolean arg) {
-            removeMessages(what);
-            Message m = Message.obtain(this, what);
-            m.arg1 = (arg ? 1 : 0);
-            sendMessage(m);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_ENABLE_ADB:
-                    setAdbEnabled(msg.arg1 == 1);
-                    break;
-                case MSG_BOOT_COMPLETED:
-                    if (mDebuggingManager != null) {
-                        mDebuggingManager.setAdbEnabled(mAdbEnabled);
-                    }
-                    break;
-            }
+            // register observer to listen for settings changes
+            mObserver = new AdbSettingsObserver();
+            mContentResolver.registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
+                    false, mObserver);
+            mContentResolver.registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED),
+                    false, mObserver);
+        } catch (Exception e) {
+            Slog.e(TAG, "Error in initAdbState", e);
         }
     }
 
+    private static boolean containsFunction(String functions, String function) {
+        int index = functions.indexOf(function);
+        if (index < 0) return false;
+        if (index > 0 && functions.charAt(index - 1) != ',') return false;
+        int charAfter = index + function.length();
+        if (charAfter < functions.length() && functions.charAt(charAfter) != ',') return false;
+        return true;
+    }
+
     private class AdbSettingsObserver extends ContentObserver {
+        private final Uri mAdbUsbUri = Settings.Global.getUriFor(Settings.Global.ADB_ENABLED);
+        private final Uri mAdbWifiUri = Settings.Global.getUriFor(Settings.Global.ADB_WIFI_ENABLED);
+
         AdbSettingsObserver() {
             super(null);
         }
 
         @Override
-        public void onChange(boolean selfChange) {
-            boolean enable = (Settings.Global.getInt(mContentResolver,
-                    Settings.Global.ADB_ENABLED, 0) > 0);
-            mHandler.sendMessage(MSG_ENABLE_ADB, enable);
+        public void onChange(boolean selfChange, @NonNull Uri uri, @UserIdInt int userId) {
+            if (mAdbUsbUri.equals(uri)) {
+                boolean shouldEnable = (Settings.Global.getInt(mContentResolver,
+                        Settings.Global.ADB_ENABLED, 0) > 0);
+                FgThread.getHandler().sendMessage(obtainMessage(
+                        AdbService::setAdbEnabled, AdbService.this, shouldEnable,
+                            AdbTransportType.USB));
+            } else if (mAdbWifiUri.equals(uri)) {
+                boolean shouldEnable = (Settings.Global.getInt(mContentResolver,
+                        Settings.Global.ADB_WIFI_ENABLED, 0) > 0);
+                FgThread.getHandler().sendMessage(obtainMessage(
+                        AdbService::setAdbEnabled, AdbService.this, shouldEnable,
+                            AdbTransportType.WIFI));
+            }
         }
     }
 
     private static final String TAG = "AdbService";
     private static final boolean DEBUG = false;
 
-    private static final int MSG_ENABLE_ADB = 1;
-    private static final int MSG_BOOT_COMPLETED = 2;
-
     /**
      * The persistent property which stores whether adb is enabled or not.
      * May also contain vendor-specific default functions for testing purposes.
@@ -188,12 +192,14 @@
 
     private final Context mContext;
     private final ContentResolver mContentResolver;
-    private final AdbService.AdbHandler mHandler;
     private final ArrayMap<IBinder, IAdbTransport> mTransports = new ArrayMap<>();
 
-    private boolean mAdbEnabled;
+    private boolean mIsAdbUsbEnabled;
+    private boolean mIsAdbWifiEnabled;
     private AdbDebuggingManager mDebuggingManager;
 
+    private ContentObserver mObserver;
+
     private AdbService(Context context) {
         mContext = context;
         mContentResolver = context.getContentResolver();
@@ -204,8 +210,7 @@
             mDebuggingManager = new AdbDebuggingManager(context);
         }
 
-        mHandler = new AdbHandler(FgThread.get().getLooper());
-
+        initAdbState();
         LocalServices.addService(AdbManagerInternal.class, new AdbManagerInternalImpl());
     }
 
@@ -219,7 +224,9 @@
         // make sure the ADB_ENABLED setting value matches the current state
         try {
             Settings.Global.putInt(mContentResolver,
-                    Settings.Global.ADB_ENABLED, mAdbEnabled ? 1 : 0);
+                    Settings.Global.ADB_ENABLED, mIsAdbUsbEnabled ? 1 : 0);
+            Settings.Global.putInt(mContentResolver,
+                    Settings.Global.ADB_WIFI_ENABLED, mIsAdbWifiEnabled ? 1 : 0);
         } catch (SecurityException e) {
             // If UserManager.DISALLOW_DEBUGGING_FEATURES is on, that this setting can't be changed.
             Slog.d(TAG, "ADB_ENABLED is restricted.");
@@ -231,7 +238,10 @@
      */
     public void bootCompleted() {
         if (DEBUG) Slog.d(TAG, "boot completed");
-        mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
+        if (mDebuggingManager != null) {
+            mDebuggingManager.setAdbEnabled(mIsAdbUsbEnabled, AdbTransportType.USB);
+            mDebuggingManager.setAdbEnabled(mIsAdbWifiEnabled, AdbTransportType.WIFI);
+        }
     }
 
     @Override
@@ -285,24 +295,82 @@
                 PackageManager.FEATURE_CAMERA_ANY);
     }
 
-    private void setAdbEnabled(boolean enable) {
-        if (DEBUG) Slog.d(TAG, "setAdbEnabled(" + enable + "), mAdbEnabled=" + mAdbEnabled);
+    @Override
+    public void allowWirelessDebugging(boolean alwaysAllow, String bssid) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
 
-        if (enable == mAdbEnabled) {
+    @Override
+    public void denyWirelessDebugging() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
+
+    @Override
+    public Map<String, PairDevice> getPairedDevices() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+        return null;
+    }
+
+    @Override
+    public void unpairDevice(String fingerprint) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
+
+    @Override
+    public void enablePairingByPairingCode() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
+
+    @Override
+    public void enablePairingByQrCode(String serviceName, String password) {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
+
+    @Override
+    public void disablePairing() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+    }
+
+    @Override
+    public int getAdbWirelessPort() {
+        mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_DEBUGGING, null);
+        // TODO(joshuaduong): NOT IMPLEMENTED
+        return 0;
+    }
+
+    private void setAdbEnabled(boolean enable, byte transportType) {
+        if (DEBUG) {
+            Slog.d(TAG, "setAdbEnabled(" + enable + "), mIsAdbUsbEnabled=" + mIsAdbUsbEnabled
+                    + ", mIsAdbWifiEnabled=" + mIsAdbWifiEnabled + ", transportType="
+                        + transportType);
+        }
+
+        if (transportType == AdbTransportType.USB && enable != mIsAdbUsbEnabled) {
+            mIsAdbUsbEnabled = enable;
+        } else if (transportType == AdbTransportType.WIFI && enable != mIsAdbWifiEnabled) {
+            mIsAdbWifiEnabled = enable;
+        } else {
+            // No change
             return;
         }
-        mAdbEnabled = enable;
 
         for (IAdbTransport transport : mTransports.values()) {
             try {
-                transport.onAdbEnabled(enable);
+                transport.onAdbEnabled(enable, transportType);
             } catch (RemoteException e) {
                 Slog.w(TAG, "Unable to send onAdbEnabled to transport " + transport.toString());
             }
         }
 
         if (mDebuggingManager != null) {
-            mDebuggingManager.setAdbEnabled(enable);
+            mDebuggingManager.setAdbEnabled(enable, transportType);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 97b5eaa..2bcb28d 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -49,6 +49,7 @@
 import android.app.PendingIntent;
 import android.app.Service;
 import android.app.ServiceStartArgs;
+import android.app.admin.DevicePolicyEventLogger;
 import android.appwidget.AppWidgetManagerInternal;
 import android.content.ComponentName;
 import android.content.ComponentName.WithComponentName;
@@ -61,7 +62,6 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -79,6 +79,8 @@
 import android.os.TransactionTooLargeException;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.stats.devicepolicy.DevicePolicyEnums;
+import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.EventLog;
@@ -88,7 +90,6 @@
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
 import android.webkit.WebViewZygote;
-import android.widget.Toast;
 
 import com.android.internal.R;
 import com.android.internal.app.procstats.ServiceState;
@@ -187,6 +188,9 @@
 
     AppWidgetManagerInternal mAppWidgetManagerInternal;
 
+    // white listed packageName.
+    ArraySet<String> mWhiteListAllowWhileInUsePermissionInFgs = new ArraySet<>();
+
     final Runnable mLastAnrDumpClearer = new Runnable() {
         @Override public void run() {
             synchronized (mAm) {
@@ -389,6 +393,20 @@
         AppStateTracker ast = LocalServices.getService(AppStateTracker.class);
         ast.addListener(new ForcedStandbyListener());
         mAppWidgetManagerInternal = LocalServices.getService(AppWidgetManagerInternal.class);
+        setWhiteListAllowWhileInUsePermissionInFgs();
+    }
+
+    private void setWhiteListAllowWhileInUsePermissionInFgs() {
+        final String attentionServicePackageName =
+                mAm.mContext.getPackageManager().getAttentionServicePackageName();
+        if (!TextUtils.isEmpty(attentionServicePackageName)) {
+            mWhiteListAllowWhileInUsePermissionInFgs.add(attentionServicePackageName);
+        }
+        final String systemCaptionsServicePackageName =
+                mAm.mContext.getPackageManager().getSystemCaptionsServicePackageName();
+        if (!TextUtils.isEmpty(systemCaptionsServicePackageName)) {
+            mWhiteListAllowWhileInUsePermissionInFgs.add(systemCaptionsServicePackageName);
+        }
     }
 
     ServiceRecord getServiceByNameLocked(ComponentName name, int callingUser) {
@@ -1894,6 +1912,8 @@
                 requestServiceBindingLocked(s, b.intent, callerFg, false);
             }
 
+            maybeLogBindCrossProfileService(userId, callingPackage, callerApp.info.uid);
+
             getServiceMapLocked(s.userId).ensureNotStartingBackgroundLocked(s);
 
         } finally {
@@ -1903,6 +1923,21 @@
         return 1;
     }
 
+    private void maybeLogBindCrossProfileService(
+            int userId, String callingPackage, int callingUid) {
+        if (UserHandle.isCore(callingUid)) {
+            return;
+        }
+        final int callingUserId = UserHandle.getCallingUserId();
+        if (callingUserId == userId
+                || !mAm.mUserController.isSameProfileGroup(callingUserId, userId)) {
+            return;
+        }
+        DevicePolicyEventLogger.createEvent(DevicePolicyEnums.BIND_CROSS_PROFILE_SERVICE)
+                .setStrings(callingPackage)
+                .write();
+    }
+
     void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
         final long origId = Binder.clearCallingIdentity();
         try {
@@ -4634,6 +4669,12 @@
             return true;
         }
 
+        final boolean isWhiteListedPackage =
+                mWhiteListAllowWhileInUsePermissionInFgs.contains(callingPackage);
+        if (isWhiteListedPackage) {
+            return true;
+        }
+
         r.mInfoDenyWhileInUsePermissionInFgs =
                 "Background FGS start while-in-use permission restriction [callingPackage: "
                 + callingPackage
@@ -4644,20 +4685,35 @@
     }
 
     // TODO: remove this toast after feature development is done
-    private void showWhileInUsePermissionInFgsBlockedToastLocked(String callingPackage) {
-        final Resources res = mAm.mContext.getResources();
-        final String toastMsg = res.getString(
-                        R.string.allow_while_in_use_permission_in_fgs, callingPackage);
-        mAm.mUiHandler.post(() -> {
-            Toast.makeText(mAm.mContext, toastMsg, Toast.LENGTH_LONG).show();
-        });
+    private void showWhileInUsePermissionInFgsBlockedNotificationLocked(String callingPackage,
+            String detailInfo) {
+        final Context context = mAm.mContext;
+        final String title = "Foreground Service While-in-use Permission Restricted";
+        final String content = "App affected:" + callingPackage + ", please file a bug report";
+        Notification.Builder n =
+                new Notification.Builder(context,
+                        SystemNotificationChannels.ALERTS)
+                        .setSmallIcon(R.drawable.stat_sys_vitals)
+                        .setWhen(0)
+                        .setColor(context.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setTicker(title)
+                        .setContentTitle(title)
+                        .setContentText(content)
+                        .setStyle(new Notification.BigTextStyle().bigText(detailInfo));
+        final NotificationManager notificationManager =
+                (NotificationManager) context.getSystemService(context.NOTIFICATION_SERVICE);
+        notificationManager.notifyAsUser(null,
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICE_WHILE_IN_USE_PERMISSION,
+                n.build(), UserHandle.ALL);
     }
 
     // TODO: remove this toast after feature development is done
     // show a toast message to ask user to file a bugreport so we know how many apps are impacted by
     // the new background started foreground service while-in-use permission restriction.
-    void showWhileInUseDebugToastLocked(int uid, int op, int mode) {
-        StringBuilder sb = new StringBuilder();
+    void showWhileInUseDebugNotificationLocked(int uid, int op, int mode) {
+        StringBuilder packageNameBuilder = new StringBuilder();
+        StringBuilder detailInfoBuilder = new StringBuilder();
         for (int i = mAm.mProcessList.mLruProcesses.size() - 1; i >= 0; i--) {
             ProcessRecord pr = mAm.mProcessList.mLruProcesses.get(i);
             if (pr.uid != uid) {
@@ -4670,17 +4726,22 @@
                 }
                 if (!r.mAllowWhileInUsePermissionInFgs
                         && r.mInfoDenyWhileInUsePermissionInFgs != null) {
-                    Slog.wtf(TAG, r.mInfoDenyWhileInUsePermissionInFgs
-                            + " affected while-use-permission:" + AppOpsManager.opToPublicName(op));
-                    sb.append(r.mRecentCallingPackage + " ");
+                    final String msg = r.mInfoDenyWhileInUsePermissionInFgs
+                            + " affected while-in-use permission:"
+                            + AppOpsManager.opToPublicName(op);
+                    Slog.wtf(TAG, msg);
+                    packageNameBuilder.append(r.mRecentCallingPackage + " ");
+                    detailInfoBuilder.append(msg);
+                    detailInfoBuilder.append("\n");
                 }
             }
         }
 
-        final String callingPackageStr = sb.toString();
+        final String callingPackageStr = packageNameBuilder.toString();
         if (mAm.mConstants.mFlagForegroundServiceStartsLoggingEnabled
                 && !callingPackageStr.isEmpty()) {
-            showWhileInUsePermissionInFgsBlockedToastLocked(callingPackageStr);
+            showWhileInUsePermissionInFgsBlockedNotificationLocked(callingPackageStr,
+                    detailInfoBuilder.toString());
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerConstants.java b/services/core/java/com/android/server/am/ActivityManagerConstants.java
index fabe92db..8fbe923 100644
--- a/services/core/java/com/android/server/am/ActivityManagerConstants.java
+++ b/services/core/java/com/android/server/am/ActivityManagerConstants.java
@@ -19,12 +19,16 @@
 import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_POWER_QUICK;
 
 import android.app.ActivityThread;
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
+import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.provider.DeviceConfig.OnPropertiesChangedListener;
 import android.provider.DeviceConfig.Properties;
@@ -33,6 +37,7 @@
 import android.util.ArraySet;
 import android.util.KeyValueListParser;
 import android.util.Slog;
+import android.util.SparseArray;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -289,6 +294,12 @@
     // started, the restriction is on while-in-use permissions.)
     volatile boolean mFlagBackgroundFgsStartRestrictionEnabled = true;
 
+    /**
+     * UserId to Assistant ComponentName mapping.
+     * Per user Assistant ComponentName is from {@link android.provider.Settings.Secure#ASSISTANT}
+     */
+    SparseArray<ComponentName> mAssistants = new SparseArray<>();
+
     private final ActivityManagerService mService;
     private ContentResolver mResolver;
     private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -364,6 +375,8 @@
                 Settings.Global.getUriFor(
                         Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED);
 
+    private static final Uri ASSISTANT_URI = Settings.Secure.getUriFor(Settings.Secure.ASSISTANT);
+
     private static final Uri ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI =
             Settings.Global.getUriFor(Settings.Global.ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS);
 
@@ -430,6 +443,8 @@
         mResolver.registerContentObserver(ACTIVITY_STARTS_LOGGING_ENABLED_URI, false, this);
         mResolver.registerContentObserver(FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED_URI,
                 false, this);
+        mResolver.registerContentObserver(ASSISTANT_URI, false, this,
+                UserHandle.USER_ALL);
         if (mSystemServerAutomaticHeapDumpEnabled) {
             mResolver.registerContentObserver(ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI,
                     false, this);
@@ -445,6 +460,7 @@
         // The following read from Settings.
         updateActivityStartsLoggingEnabled();
         updateForegroundServiceStartsLoggingEnabled();
+        updateAssistant();
     }
 
     private void loadDeviceConfigConstants() {
@@ -476,6 +492,8 @@
             updateForegroundServiceStartsLoggingEnabled();
         } else if (ENABLE_AUTOMATIC_SYSTEM_SERVER_HEAP_DUMPS_URI.equals(uri)) {
             updateEnableAutomaticSystemServerHeapDumps();
+        } else if (ASSISTANT_URI.equals(uri)) {
+            updateAssistant();
         }
     }
 
@@ -573,6 +591,31 @@
                 Settings.Global.FOREGROUND_SERVICE_STARTS_LOGGING_ENABLED, 1) == 1;
     }
 
+    private void updateAssistant() {
+        final List<UserInfo> users =
+                mService.mContext.getSystemService(UserManager.class).getUsers();
+        SparseArray<ComponentName> componentNames = new SparseArray<>();
+        for (int i = 0; i < users.size(); i++) {
+            final int userId = users.get(i).id;
+            final String str = Settings.Secure.getStringForUser(mResolver,
+                    Settings.Secure.ASSISTANT, userId);
+            if (!TextUtils.isEmpty(str)) {
+                componentNames.put(userId, ComponentName.unflattenFromString(str));
+            }
+        }
+        synchronized (mService) {
+            for (int i = 0; i < mAssistants.size(); i++) {
+                mService.mServices.mWhiteListAllowWhileInUsePermissionInFgs.remove(
+                        mAssistants.valueAt(i).getPackageName());
+            }
+            mAssistants = componentNames;
+            for (int i = 0; i < mAssistants.size(); i++) {
+                mService.mServices.mWhiteListAllowWhileInUsePermissionInFgs.add(
+                        mAssistants.valueAt(i).getPackageName());
+            }
+        }
+    }
+
     private void updateBackgroundFgsStartsRestriction() {
         mFlagBackgroundFgsStartRestrictionEnabled = DeviceConfig.getBoolean(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -581,9 +624,6 @@
     }
 
     private void updateOomAdjUpdatePolicy() {
-
-
-
         OOMADJ_UPDATE_QUICK = DeviceConfig.getInt(
                 DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 KEY_OOMADJ_UPDATE_POLICY,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9082807..a529f24 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1045,6 +1045,11 @@
         }
 
         @Override
+        protected IntentFilter getIntentFilter(@NonNull BroadcastFilter input) {
+            return input;
+        }
+
+        @Override
         protected BroadcastFilter[] newArray(int size) {
             return new BroadcastFilter[size];
         }
@@ -7266,7 +7271,7 @@
 
         // Wait for the provider to be published...
         final long timeout =
-                SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_WAIT_TIMEOUT_MILLIS;
+                SystemClock.uptimeMillis() + ContentResolver.CONTENT_PROVIDER_READY_TIMEOUT_MILLIS;
         boolean timedOut = false;
         synchronized (cpr) {
             while (cpr.provider == null) {
@@ -14605,6 +14610,11 @@
             if (index < 0) {
                 ProcessList.remove(app.pid);
             }
+
+            // Remove provider publish timeout because we will start a new timeout when the
+            // restarted process is attaching (if the process contains launching providers).
+            mHandler.removeMessages(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG, app);
+
             mProcessList.addProcessNameLocked(app);
             app.pendingStart = false;
             mProcessList.startProcessLocked(app,
@@ -19333,7 +19343,8 @@
         @Override
         public void showWhileInUseDebugToast(int uid, int op, int mode) {
             synchronized (ActivityManagerService.this) {
-                ActivityManagerService.this.mServices.showWhileInUseDebugToastLocked(uid, op, mode);
+                ActivityManagerService.this.mServices.showWhileInUseDebugNotificationLocked(
+                        uid, op, mode);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index ed6ace3..119394f 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -1135,7 +1135,7 @@
     @Override
     public void setBatteryState(final int status, final int health, final int plugType,
             final int level, final int temp, final int volt, final int chargeUAh,
-            final int chargeFullUAh) {
+            final int chargeFullUAh, final long chargeTimeToFullSeconds) {
         enforceCallingPermission();
 
         // BatteryService calls us here and we may update external state. It would be wrong
@@ -1147,7 +1147,7 @@
                     // The battery state has not changed, so we don't need to sync external
                     // stats immediately.
                     mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
-                            chargeUAh, chargeFullUAh);
+                            chargeUAh, chargeFullUAh, chargeTimeToFullSeconds);
                     return;
                 }
             }
@@ -1160,7 +1160,7 @@
             mWorker.scheduleRunnable(() -> {
                 synchronized (mStats) {
                     mStats.setBatteryStateLocked(status, health, plugType, level, temp, volt,
-                            chargeUAh, chargeFullUAh);
+                            chargeUAh, chargeFullUAh, chargeTimeToFullSeconds);
                 }
             });
         });
diff --git a/services/core/java/com/android/server/am/CoreSettingsObserver.java b/services/core/java/com/android/server/am/CoreSettingsObserver.java
index a03f0bb..48ceba9 100644
--- a/services/core/java/com/android/server/am/CoreSettingsObserver.java
+++ b/services/core/java/com/android/server/am/CoreSettingsObserver.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import android.annotation.NonNull;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -32,6 +33,7 @@
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 /**
  * Helper class for watching a set of core settings which the framework
@@ -42,16 +44,20 @@
 final class CoreSettingsObserver extends ContentObserver {
     private static final String LOG_TAG = CoreSettingsObserver.class.getSimpleName();
 
-    private static class DeviceConfigEntry {
+    private static class DeviceConfigEntry<T> {
         String namespace;
         String flag;
         String coreSettingKey;
-        Class<?> type;
-        DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<?> type) {
+        Class<T> type;
+        T defaultValue;
+
+        DeviceConfigEntry(String namespace, String flag, String coreSettingKey, Class<T> type,
+                @NonNull T defaultValue) {
             this.namespace = namespace;
             this.flag = flag;
             this.coreSettingKey = coreSettingKey;
             this.type = type;
+            this.defaultValue = Objects.requireNonNull(defaultValue);
         }
     }
 
@@ -105,24 +111,34 @@
         sGlobalSettingToTypeMap.put(Settings.Global.GAME_DRIVER_SPHAL_LIBRARIES, String.class);
         // add other global settings here...
 
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
-                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_CONTROL,
-                WidgetFlags.KEY_ENABLE_CURSOR_CONTROL, boolean.class));
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE,
+                WidgetFlags.KEY_ENABLE_CURSOR_DRAG_FROM_ANYWHERE, boolean.class,
+                WidgetFlags.ENABLE_CURSOR_DRAG_FROM_ANYWHERE_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
+                DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES,
+                WidgetFlags.KEY_ENABLE_INSERTION_HANDLE_GESTURES, boolean.class,
+                WidgetFlags.ENABLE_INSERTION_HANDLE_GESTURES_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT,
-                WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class));
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                WidgetFlags.KEY_INSERTION_HANDLE_DELTA_HEIGHT, int.class,
+                WidgetFlags.INSERTION_HANDLE_DELTA_HEIGHT_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Integer>(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.INSERTION_HANDLE_OPACITY,
-                WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, int.class));
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                WidgetFlags.KEY_INSERTION_HANDLE_OPACITY, int.class,
+                WidgetFlags.INSERTION_HANDLE_OPACITY_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Boolean>(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.ENABLE_NEW_MAGNIFIER,
-                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, boolean.class));
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                WidgetFlags.KEY_ENABLE_NEW_MAGNIFIER, boolean.class,
+                WidgetFlags.ENABLE_NEW_MAGNIFIER_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Float>(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ZOOM_FACTOR,
-                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, float.class));
-        sDeviceConfigEntries.add(new DeviceConfigEntry(
+                WidgetFlags.KEY_MAGNIFIER_ZOOM_FACTOR, float.class,
+                WidgetFlags.MAGNIFIER_ZOOM_FACTOR_DEFAULT));
+        sDeviceConfigEntries.add(new DeviceConfigEntry<Float>(
                 DeviceConfig.NAMESPACE_WIDGET, WidgetFlags.MAGNIFIER_ASPECT_RATIO,
-                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class));
+                WidgetFlags.KEY_MAGNIFIER_ASPECT_RATIO, float.class,
+                WidgetFlags.MAGNIFIER_ASPECT_RATIO_DEFAULT));
         // add other device configs here...
     }
 
@@ -216,23 +232,29 @@
         }
     }
 
+    @SuppressWarnings("unchecked")
     private void populateSettingsFromDeviceConfig() {
-        for (DeviceConfigEntry entry : sDeviceConfigEntries) {
+        for (DeviceConfigEntry<?> entry : sDeviceConfigEntries) {
             if (entry.type == String.class) {
+                String defaultValue = ((DeviceConfigEntry<String>) entry).defaultValue;
                 mCoreSettings.putString(entry.coreSettingKey,
-                        DeviceConfig.getString(entry.namespace, entry.flag, ""));
+                        DeviceConfig.getString(entry.namespace, entry.flag, defaultValue));
             } else if (entry.type == int.class) {
+                int defaultValue = ((DeviceConfigEntry<Integer>) entry).defaultValue;
                 mCoreSettings.putInt(entry.coreSettingKey,
-                        DeviceConfig.getInt(entry.namespace, entry.flag, 0));
+                        DeviceConfig.getInt(entry.namespace, entry.flag, defaultValue));
             } else if (entry.type == float.class) {
+                float defaultValue = ((DeviceConfigEntry<Float>) entry).defaultValue;
                 mCoreSettings.putFloat(entry.coreSettingKey,
-                        DeviceConfig.getFloat(entry.namespace, entry.flag, 0));
+                        DeviceConfig.getFloat(entry.namespace, entry.flag, defaultValue));
             } else if (entry.type == long.class) {
+                long defaultValue = ((DeviceConfigEntry<Long>) entry).defaultValue;
                 mCoreSettings.putLong(entry.coreSettingKey,
-                        DeviceConfig.getLong(entry.namespace, entry.flag, 0));
+                        DeviceConfig.getLong(entry.namespace, entry.flag, defaultValue));
             } else if (entry.type == boolean.class) {
+                boolean defaultValue = ((DeviceConfigEntry<Boolean>) entry).defaultValue;
                 mCoreSettings.putInt(entry.coreSettingKey,
-                        DeviceConfig.getBoolean(entry.namespace, entry.flag, false) ? 1 : 0);
+                        DeviceConfig.getBoolean(entry.namespace, entry.flag, defaultValue) ? 1 : 0);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index a651d9d..c239feb1 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1128,6 +1128,7 @@
             app.setCurRawAdj(app.maxAdj);
             app.setHasForegroundActivities(false);
             app.setCurrentSchedulingGroup(ProcessList.SCHED_GROUP_DEFAULT);
+            app.curCapability = PROCESS_CAPABILITY_ALL;
             app.setCurProcState(ActivityManager.PROCESS_STATE_PERSISTENT);
             // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
@@ -1994,12 +1995,11 @@
         if (app.hasForegroundServices()) {
             capability |= capabilityFromFGS;
         } else if (!ActivityManager.isProcStateBackground(procState)) {
-            // procState higher than PROCESS_STATE_TRANSIENT_BACKGROUND implicitly has
+            // procState higher than PROCESS_STATE_BOUND_FOREGROUND_SERVICE implicitly has
             // camera/microphone capability
             if (procState == PROCESS_STATE_FOREGROUND_SERVICE && procStateFromFGSClient) {
                 // if the FGS state is passed down from client, do not grant implicit capabilities.
             } else {
-                //TODO: remove this line when enforcing the feature.
                 capability |= PROCESS_CAPABILITY_ALL_IMPLICIT;
             }
         }
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index ffa7d92..22559c4 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -80,11 +80,13 @@
 import android.os.DropBoxManager;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IVold;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.StrictMode;
 import android.os.SystemClock;
 import android.os.SystemProperties;
@@ -142,10 +144,14 @@
 public final class ProcessList {
     static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
 
-    // A device config to control the minimum target SDK to enable app data isolation
+    // A system property to control if app data isolation is enabled.
     static final String ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY =
             "persist.zygote.app_data_isolation";
 
+    // A system property to control if obb app data isolation is enabled in vold.
+    static final String ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY =
+            "persist.sys.vold_app_data_isolation_enabled";
+
     // A device config to control the minimum target SDK to enable app data isolation
     static final String ANDROID_APP_DATA_ISOLATION_MIN_SDK = "android_app_data_isolation_min_sdk";
 
@@ -339,6 +345,14 @@
     @EnabledAfter(targetSdkVersion = VersionCodes.Q)
     private static final long NATIVE_HEAP_POINTER_TAGGING = 135754954; // This is a bug id.
 
+    /**
+     * Apps have no access to the private data directories of any other app, even if the other
+     * app has made them world-readable.
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = VersionCodes.Q)
+    private static final long APP_DATA_DIRECTORY_ISOLATION = 143937733; // See b/143937733
+
     ActivityManagerService mService = null;
 
     // To kill process groups asynchronously
@@ -379,6 +393,8 @@
 
     private boolean mAppDataIsolationEnabled = false;
 
+    private boolean mVoldAppDataIsolationEnabled = false;
+
     private ArrayList<String> mAppDataIsolationWhitelistedApps;
 
     /**
@@ -691,6 +707,8 @@
         // want some apps enabled while some apps disabled
         mAppDataIsolationEnabled =
                 SystemProperties.getBoolean(ANDROID_APP_DATA_ISOLATION_ENABLED_PROPERTY, true);
+        mVoldAppDataIsolationEnabled = SystemProperties.getBoolean(
+                ANDROID_VOLD_APP_DATA_ISOLATION_ENABLED_PROPERTY, false);
         mAppDataIsolationWhitelistedApps = new ArrayList<>(
                 SystemConfig.getInstance().getAppDataIsolationWhitelistedApps());
 
@@ -2060,7 +2078,14 @@
         }
         final int minTargetSdk = DeviceConfig.getInt(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 ANDROID_APP_DATA_ISOLATION_MIN_SDK, Build.VERSION_CODES.R);
-        return app.info.targetSdkVersion >= minTargetSdk;
+        if (app.info.targetSdkVersion < minTargetSdk) {
+            return false;
+        }
+
+        // TODO(b/147266020): Remove non-standard gating above & switch to isChangeEnabled.
+        mPlatformCompat.reportChange(APP_DATA_DIRECTORY_ISOLATION, app.info);
+
+        return true;
     }
 
     private Map<String, Pair<String, Long>> getPackageAppDataInfoMap(PackageManagerInternal pmInt,
@@ -2113,6 +2138,13 @@
                         app.info.packageName, app.userId);
                 pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, sharedPackages.length == 0
                         ? new String[]{app.info.packageName} : sharedPackages, uid);
+
+                if (mVoldAppDataIsolationEnabled) {
+                    StorageManagerInternal storageManagerInternal = LocalServices.getService(
+                                StorageManagerInternal.class);
+                    storageManagerInternal.prepareObbDirs(UserHandle.getUserId(uid),
+                            pkgDataInfoMap.keySet(), app.processName);
+                }
             } else {
                 pkgDataInfoMap = null;
             }
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 5d8a0f6..4670d58 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -401,10 +401,10 @@
             pw.print(prefix); pw.print("hasStartedWhitelistingBgActivityStarts=");
             pw.println(mHasStartedWhitelistingBgActivityStarts);
         }
-        if (mAllowWhileInUsePermissionInFgs) {
-            pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs=");
-            pw.println(mAllowWhileInUsePermissionInFgs);
-        }
+        pw.print(prefix); pw.print("allowWhileInUsePermissionInFgs=");
+                pw.println(mAllowWhileInUsePermissionInFgs);
+        pw.print(prefix); pw.print("recentCallingPackage=");
+                pw.println(mRecentCallingPackage);
         if (delayed) {
             pw.print(prefix); pw.print("delayed="); pw.println(delayed);
         }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index a934f22..7462f7f 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -98,8 +98,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PermissionInfo;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils.ParsedFeature;
+import android.content.pm.parsing.component.ParsedFeature;
 import android.database.ContentObserver;
 import android.hardware.camera2.CameraDevice.CAMERA_AUDIO_RESTRICTION;
 import android.net.Uri;
@@ -156,6 +155,7 @@
 import com.android.server.LockGuard;
 import com.android.server.SystemServerInitThreadPool;
 import com.android.server.pm.PackageList;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import libcore.util.EmptyArray;
 
@@ -536,9 +536,8 @@
                                 // The FGS has the location capability, but due to FGS BG start
                                 // restriction it lost the capability, use temp location capability
                                 // to mark this case.
-                                // TODO change to MODE_IGNORED when enforcing the feature.
                                 maybeShowWhileInUseDebugToast(op, mode);
-                                return AppOpsManager.MODE_ALLOWED;
+                                return AppOpsManager.MODE_IGNORED;
                             } else {
                                 return AppOpsManager.MODE_IGNORED;
                             }
@@ -546,17 +545,15 @@
                             if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
                                 return AppOpsManager.MODE_ALLOWED;
                             } else {
-                                //TODO change to MODE_IGNORED when enforcing the feature.
                                 maybeShowWhileInUseDebugToast(op, mode);
-                                return AppOpsManager.MODE_ALLOWED;
+                                return AppOpsManager.MODE_IGNORED;
                             }
                         case OP_RECORD_AUDIO:
                             if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
                                 return AppOpsManager.MODE_ALLOWED;
                             } else {
-                                //TODO change to MODE_IGNORED when enforcing the feature.
                                 maybeShowWhileInUseDebugToast(op, mode);
-                                return AppOpsManager.MODE_ALLOWED;
+                                return AppOpsManager.MODE_IGNORED;
                             }
                         default:
                             return AppOpsManager.MODE_ALLOWED;
@@ -571,17 +568,15 @@
                         if ((capability & PROCESS_CAPABILITY_FOREGROUND_CAMERA) != 0) {
                             return AppOpsManager.MODE_ALLOWED;
                         } else {
-                            //TODO change to MODE_IGNORED when enforcing the feature.
                             maybeShowWhileInUseDebugToast(op, mode);
-                            return AppOpsManager.MODE_ALLOWED;
+                            return AppOpsManager.MODE_IGNORED;
                         }
                     case OP_RECORD_AUDIO:
                         if ((capability & PROCESS_CAPABILITY_FOREGROUND_MICROPHONE) != 0) {
                             return AppOpsManager.MODE_ALLOWED;
                         } else {
-                            //TODO change to MODE_IGNORED when enforcing the feature.
                             maybeShowWhileInUseDebugToast(op, mode);
-                            return AppOpsManager.MODE_ALLOWED;
+                            return AppOpsManager.MODE_IGNORED;
                         }
                     default:
                         return MODE_ALLOWED;
diff --git a/services/core/java/com/android/server/audio/AudioDeviceBroker.java b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
index 566b72d..b546120 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceBroker.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceBroker.java
@@ -24,7 +24,7 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioManager;
 import android.media.AudioRoutesInfo;
 import android.media.AudioSystem;
@@ -403,7 +403,7 @@
     }
 
     /*package*/ int setPreferredDeviceForStrategySync(int strategy,
-                                                      @NonNull AudioDevice device) {
+                                                      @NonNull AudioDeviceAttributes device) {
         return mDeviceInventory.setPreferredDeviceForStrategySync(strategy, device);
     }
 
@@ -554,7 +554,8 @@
         sendLMsgNoDelay(MSG_L_SCOCLIENT_DIED, SENDMSG_QUEUE, obj);
     }
 
-    /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy, AudioDevice device)
+    /*package*/ void postSaveSetPreferredDeviceForStrategy(int strategy,
+                                                           AudioDeviceAttributes device)
     {
         sendILMsgNoDelay(MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY, SENDMSG_QUEUE, strategy, device);
     }
@@ -915,7 +916,7 @@
                 } break;
                 case MSG_IL_SAVE_PREF_DEVICE_FOR_STRATEGY: {
                     final int strategy = msg.arg1;
-                    final AudioDevice device = (AudioDevice) msg.obj;
+                    final AudioDeviceAttributes device = (AudioDeviceAttributes) msg.obj;
                     mDeviceInventory.onSaveSetPreferredDevice(strategy, device);
                 } break;
                 case MSG_I_SAVE_REMOVE_PREF_DEVICE_FOR_STRATEGY: {
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e170db0..c17ed3e 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -24,7 +24,7 @@
 import android.bluetooth.BluetoothHearingAid;
 import android.bluetooth.BluetoothProfile;
 import android.content.Intent;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioDevicePort;
 import android.media.AudioFormat;
 import android.media.AudioManager;
@@ -77,7 +77,7 @@
     private final ArrayMap<Integer, String> mApmConnectedDevices = new ArrayMap<>();
 
     // List of preferred devices for strategies
-    private final ArrayMap<Integer, AudioDevice> mPreferredDevices = new ArrayMap<>();
+    private final ArrayMap<Integer, AudioDeviceAttributes> mPreferredDevices = new ArrayMap<>();
 
     // the wrapper for AudioSystem static methods, allows us to spy AudioSystem
     private final @NonNull AudioSystemAdapter mAudioSystem;
@@ -474,7 +474,7 @@
         }
     }
 
-    /*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDevice device) {
+    /*package*/ void onSaveSetPreferredDevice(int strategy, @NonNull AudioDeviceAttributes device) {
         mPreferredDevices.put(strategy, device);
         dispatchPreferredDevice(strategy, device);
     }
@@ -488,7 +488,7 @@
     //
 
     /*package*/ int setPreferredDeviceForStrategySync(int strategy,
-                                                      @NonNull AudioDevice device) {
+                                                      @NonNull AudioDeviceAttributes device) {
         final long identity = Binder.clearCallingIdentity();
         final int status = mAudioSystem.setPreferredDeviceForStrategy(strategy, device);
         Binder.restoreCallingIdentity(identity);
@@ -1112,7 +1112,7 @@
         }
     }
 
-    private void dispatchPreferredDevice(int strategy, @Nullable AudioDevice device) {
+    private void dispatchPreferredDevice(int strategy, @Nullable AudioDeviceAttributes device) {
         final int nbDispatchers = mPrefDevDispatchers.beginBroadcast();
         for (int i = 0; i < nbDispatchers; i++) {
             try {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index 4be74b5..f3d42ad 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -65,7 +65,7 @@
 import android.hidl.manager.V1_0.IServiceManager;
 import android.media.AudioAttributes;
 import android.media.AudioAttributes.AttributeSystemUsage;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioDeviceInfo;
 import android.media.AudioFocusInfo;
 import android.media.AudioFocusRequest;
@@ -1734,7 +1734,7 @@
     // IPC methods
     ///////////////////////////////////////////////////////////////////////////
     /** @see AudioManager#setPreferredDeviceForStrategy(AudioProductStrategy, AudioDeviceInfo) */
-    public int setPreferredDeviceForStrategy(int strategy, AudioDevice device) {
+    public int setPreferredDeviceForStrategy(int strategy, AudioDeviceAttributes device) {
         if (device == null) {
             return AudioSystem.ERROR;
         }
@@ -1743,7 +1743,7 @@
                 "setPreferredDeviceForStrategy u/pid:%d/%d strat:%d dev:%s",
                 Binder.getCallingUid(), Binder.getCallingPid(), strategy, device.toString());
         sDeviceLogger.log(new AudioEventLogger.StringEvent(logString).printLog(TAG));
-        if (device.getRole() == AudioDevice.ROLE_INPUT) {
+        if (device.getRole() == AudioDeviceAttributes.ROLE_INPUT) {
             Log.e(TAG, "Unsupported input routing in " + logString);
             return AudioSystem.ERROR;
         }
@@ -1771,9 +1771,9 @@
     }
 
     /** @see AudioManager#getPreferredDeviceForStrategy(AudioProductStrategy) */
-    public AudioDevice getPreferredDeviceForStrategy(int strategy) {
+    public AudioDeviceAttributes getPreferredDeviceForStrategy(int strategy) {
         enforceModifyAudioRoutingPermission();
-        AudioDevice[] devices = new AudioDevice[1];
+        AudioDeviceAttributes[] devices = new AudioDeviceAttributes[1];
         final long identity = Binder.clearCallingIdentity();
         final int status = AudioSystem.getPreferredDeviceForStrategy(strategy, devices);
         Binder.restoreCallingIdentity(identity);
@@ -1807,7 +1807,7 @@
     }
 
     /** @see AudioManager#getDevicesForAttributes(AudioAttributes) */
-    public @NonNull ArrayList<AudioDevice> getDevicesForAttributes(
+    public @NonNull ArrayList<AudioDeviceAttributes> getDevicesForAttributes(
             @NonNull AudioAttributes attributes) {
         Objects.requireNonNull(attributes);
         enforceModifyAudioRoutingPermission();
diff --git a/services/core/java/com/android/server/audio/AudioSystemAdapter.java b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
index a3086c0..9f8f9f8 100644
--- a/services/core/java/com/android/server/audio/AudioSystemAdapter.java
+++ b/services/core/java/com/android/server/audio/AudioSystemAdapter.java
@@ -17,7 +17,7 @@
 package com.android.server.audio;
 
 import android.annotation.NonNull;
-import android.media.AudioDevice;
+import android.media.AudioDeviceAttributes;
 import android.media.AudioSystem;
 import android.util.Log;
 
@@ -86,12 +86,12 @@
     }
 
     /**
-     * Same as {@link AudioSystem#setPreferredDeviceForStrategy(int, AudioDevice)}
+     * Same as {@link AudioSystem#setPreferredDeviceForStrategy(int, AudioDeviceAttributes)}
      * @param strategy
      * @param device
      * @return
      */
-    public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDevice device) {
+    public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDeviceAttributes device) {
         return AudioSystem.setPreferredDeviceForStrategy(strategy, device);
     }
 
@@ -138,7 +138,8 @@
         }
 
         @Override
-        public int setPreferredDeviceForStrategy(int strategy, @NonNull AudioDevice device) {
+        public int setPreferredDeviceForStrategy(int strategy,
+                                                 @NonNull AudioDeviceAttributes device) {
             return AudioSystem.AUDIO_STATUS_OK;
         }
 
diff --git a/services/core/java/com/android/server/biometrics/AuthService.java b/services/core/java/com/android/server/biometrics/AuthService.java
index 204f072..8ed221d 100644
--- a/services/core/java/com/android/server/biometrics/AuthService.java
+++ b/services/core/java/com/android/server/biometrics/AuthService.java
@@ -311,6 +311,7 @@
                 }
 
                 authenticator = new FingerprintAuthenticator(fingerprintService);
+                fingerprintService.initConfiguredStrength(config.mStrength);
                 break;
 
             case TYPE_FACE:
@@ -322,6 +323,7 @@
                 }
 
                 authenticator = new FaceAuthenticator(faceService);
+                faceService.initConfiguredStrength(config.mStrength);
                 break;
 
             case TYPE_IRIS:
@@ -333,6 +335,7 @@
                 }
 
                 authenticator = new IrisAuthenticator(irisService);
+                irisService.initConfiguredStrength(config.mStrength);
                 break;
 
             default:
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index 0e70994..74c70df 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -31,6 +31,7 @@
 import android.content.pm.UserInfo;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricConstants;
+import android.hardware.biometrics.BiometricManager;
 import android.hardware.biometrics.BiometricsProtoEnums;
 import android.hardware.biometrics.IBiometricNativeHandle;
 import android.hardware.biometrics.IBiometricService;
@@ -106,6 +107,7 @@
     private PerformanceStats mPerformanceStats;
     protected int mCurrentUserId = UserHandle.USER_NULL;
     protected long mHalDeviceId;
+    private int mOEMStrength; // Tracks the OEM configured biometric modality strength
     // Tracks if the current authentication makes use of CryptoObjects.
     protected boolean mIsCrypto;
     // Normal authentications are tracked by mPerformanceMap.
@@ -681,6 +683,20 @@
                 statsModality(), BiometricsProtoEnums.ISSUE_HAL_DEATH);
     }
 
+    protected void initConfiguredStrengthInternal(int strength) {
+        if (DEBUG) {
+            Slog.d(getTag(), "initConfiguredStrengthInternal(" + strength + ")");
+        }
+        mOEMStrength = strength;
+    }
+
+    protected boolean isStrongBiometric() {
+        // TODO(b/141025588): need to calculate actual strength when downgrading tiers
+        final int biometricBits = mOEMStrength
+                & BiometricManager.Authenticators.BIOMETRIC_MIN_STRENGTH;
+        return biometricBits == BiometricManager.Authenticators.BIOMETRIC_STRONG;
+    }
+
     protected ClientMonitor getCurrentClient() {
         return mCurrentClient;
     }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 31c3d4d..a87a455 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -740,6 +740,12 @@
             }
             return 0;
         }
+
+        @Override // Binder call
+        public void initConfiguredStrength(int strength) {
+            checkPermission(USE_BIOMETRIC_INTERNAL);
+            initConfiguredStrengthInternal(strength);
+        }
     }
 
     /**
@@ -809,7 +815,7 @@
             if (mFaceServiceReceiver != null) {
                 if (biometric == null || biometric instanceof Face) {
                     mFaceServiceReceiver.onAuthenticationSucceeded(deviceId, (Face) biometric,
-                            userId);
+                            userId, isStrongBiometric());
                 } else {
                     Slog.e(TAG, "onAuthenticationSucceeded received non-face biometric");
                 }
diff --git a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
index 0a61988..83aa9cf 100644
--- a/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/fingerprint/FingerprintService.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.MANAGE_FINGERPRINT;
 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
 import static android.Manifest.permission.USE_BIOMETRIC;
+import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.USE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 
@@ -462,6 +463,12 @@
             checkPermission(MANAGE_FINGERPRINT);
             mClientActiveCallbacks.remove(callback);
         }
+
+        @Override // Binder call
+        public void initConfiguredStrength(int strength) {
+            checkPermission(USE_BIOMETRIC_INTERNAL);
+            initConfiguredStrengthInternal(strength);
+        }
     }
 
     /**
@@ -526,8 +533,8 @@
                 throws RemoteException {
             if (mFingerprintServiceReceiver != null) {
                 if (biometric == null || biometric instanceof Fingerprint) {
-                    mFingerprintServiceReceiver
-                            .onAuthenticationSucceeded(deviceId, (Fingerprint) biometric, userId);
+                    mFingerprintServiceReceiver.onAuthenticationSucceeded(deviceId,
+                            (Fingerprint) biometric, userId, isStrongBiometric());
                 } else {
                     Slog.e(TAG, "onAuthenticationSucceeded received non-fingerprint biometric");
                 }
diff --git a/services/core/java/com/android/server/biometrics/iris/IrisService.java b/services/core/java/com/android/server/biometrics/iris/IrisService.java
index 2817315..903ae6b 100644
--- a/services/core/java/com/android/server/biometrics/iris/IrisService.java
+++ b/services/core/java/com/android/server/biometrics/iris/IrisService.java
@@ -16,9 +16,12 @@
 
 package com.android.server.biometrics.iris;
 
+import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
+
 import android.content.Context;
 import android.hardware.biometrics.BiometricAuthenticator;
 import android.hardware.biometrics.BiometricsProtoEnums;
+import android.hardware.iris.IIrisService;
 
 import com.android.server.biometrics.AuthenticationClient;
 import com.android.server.biometrics.BiometricServiceBase;
@@ -42,6 +45,17 @@
     private static final String TAG = "IrisService";
 
     /**
+     * Receives the incoming binder calls from IrisManager.
+     */
+    private final class IrisServiceWrapper extends IIrisService.Stub {
+        @Override // Binder call
+        public void initConfiguredStrength(int strength) {
+            checkPermission(USE_BIOMETRIC_INTERNAL);
+            initConfiguredStrengthInternal(strength);
+        }
+    }
+
+    /**
      * Initializes the system service.
      * <p>
      * Subclasses must define a single argument constructor that accepts the context
@@ -57,6 +71,7 @@
     @Override
     public void onStart() {
         super.onStart();
+        publishBinderService(Context.IRIS_SERVICE, new IrisServiceWrapper());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/compat/CompatConfig.java b/services/core/java/com/android/server/compat/CompatConfig.java
index 7f7c9c4..3f03e09 100644
--- a/services/core/java/com/android/server/compat/CompatConfig.java
+++ b/services/core/java/com/android/server/compat/CompatConfig.java
@@ -16,6 +16,7 @@
 
 package com.android.server.compat;
 
+import android.app.compat.ChangeIdStateCache;
 import android.compat.Compatibility.ChangeConfig;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
@@ -80,6 +81,7 @@
     void addChange(CompatChange change) {
         synchronized (mChanges) {
             mChanges.put(change.getId(), change);
+            invalidateCache();
         }
     }
 
@@ -172,6 +174,7 @@
                 addChange(c);
             }
             c.addPackageOverride(packageName, enabled);
+            invalidateCache();
         }
         return alreadyKnown;
     }
@@ -228,6 +231,7 @@
                 // Should never occur, since validator is in the same process.
                 throw new RuntimeException("Unable to call override validator!", e);
             }
+            invalidateCache();
         }
         return overrideExists;
     }
@@ -250,6 +254,7 @@
                 addOverride(changeId, packageName, false);
 
             }
+            invalidateCache();
         }
     }
 
@@ -279,6 +284,7 @@
                     throw new RuntimeException("Unable to call override validator!", e);
                 }
             }
+            invalidateCache();
         }
     }
 
@@ -406,4 +412,8 @@
     IOverrideValidator getOverrideValidator() {
         return mOverrideValidator;
     }
+
+    private void invalidateCache() {
+        ChangeIdStateCache.invalidate();
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 4612cfd..3860904 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -16,6 +16,8 @@
 
 package com.android.server.connectivity;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
 import static android.net.NetworkCapabilities.transportNamesOf;
 
 import android.annotation.NonNull;
@@ -475,24 +477,16 @@
         return networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_VPN);
     }
 
-    private int getCurrentScore(boolean pretendValidated) {
-        // TODO: We may want to refactor this into a NetworkScore class that takes a base score from
-        // the NetworkAgent and signals from the NetworkAgent and uses those signals to modify the
-        // score.  The NetworkScore class would provide a nice place to centralize score constants
-        // so they are not scattered about the transports.
-
+    /** Gets the current score */
+    public int getCurrentScore() {
         // If this network is explicitly selected and the user has decided to use it even if it's
-        // unvalidated, give it the maximum score. Also give it the maximum score if it's explicitly
-        // selected and we're trying to see what its score could be. This ensures that we don't tear
-        // down an explicitly selected network before the user gets a chance to prefer it when
-        // a higher-scoring network (e.g., Ethernet) is available.
-        if (networkAgentConfig.explicitlySelected
-                && (networkAgentConfig.acceptUnvalidated || pretendValidated)) {
+        // unvalidated, give it the maximum score.
+        if (networkAgentConfig.explicitlySelected && networkAgentConfig.acceptUnvalidated) {
             return ConnectivityConstants.EXPLICITLY_SELECTED_NETWORK_SCORE;
         }
 
         int score = mNetworkScore.getLegacyScore();
-        if (!lastValidated && !pretendValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
+        if (!lastValidated && !ignoreWifiUnvalidationPenalty() && !isVPN()) {
             score -= ConnectivityConstants.UNVALIDATED_SCORE_PENALTY;
         }
         if (score < 0) score = 0;
@@ -508,18 +502,6 @@
         return isWifi && !avoidBadWifi && everValidated;
     }
 
-    // Get the current score for this Network.  This may be modified from what the
-    // NetworkAgent sent, as it has modifiers applied to it.
-    public int getCurrentScore() {
-        return getCurrentScore(false);
-    }
-
-    // Get the current score for this Network as if it was validated.  This may be modified from
-    // what the NetworkAgent sent, as it has modifiers applied to it.
-    public int getCurrentScoreAsValidated() {
-        return getCurrentScore(true);
-    }
-
     public void setNetworkScore(@NonNull NetworkScore ns) {
         mNetworkScore = ns;
     }
@@ -629,6 +611,41 @@
         mLingering = false;
     }
 
+    /**
+     * Returns whether this NAI has any chance of ever beating this other agent.
+     *
+     * The chief use case of this is the decision to tear down this network. ConnectivityService
+     * tears down networks that don't satisfy any request, unless they have a chance to beat any
+     * existing satisfier.
+     *
+     * @param other the agent to beat
+     * @return whether this should be given more time to try and beat the other agent
+     * TODO : remove this and migrate to a ranker-based approach
+     */
+    public boolean canPossiblyBeat(@NonNull final NetworkAgentInfo other) {
+        // Any explicitly selected network should be held on.
+        if (networkAgentConfig.explicitlySelected) return true;
+        // An outscored exiting network should be torn down.
+        if (mNetworkScore.isExiting()) return false;
+        // If this network is validated it can be torn down as it can't hope to be better than
+        // it already is.
+        if (networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return false;
+        // If neither network is validated, keep both until at least one does.
+        if (!other.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED)) return true;
+        // If this network is not metered but the other is, it should be preferable if it validates.
+        if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)
+                && !other.networkCapabilities.hasCapability(NET_CAPABILITY_NOT_METERED)) {
+            return true;
+        }
+
+        // If the control comes here :
+        // • This network is neither exiting or explicitly selected
+        // • This network is not validated, but the other is
+        // • This network is metered, or both networks are unmetered
+        // Keep it if it's expected to be faster than the other., should it validate.
+        return mNetworkScore.probablyFasterThan(other.mNetworkScore);
+    }
+
     public void dumpLingerTimers(PrintWriter pw) {
         for (LingerTimer timer : mLingerTimers) { pw.println(timer); }
     }
diff --git a/services/core/java/com/android/server/connectivity/NetworkRanker.java b/services/core/java/com/android/server/connectivity/NetworkRanker.java
index c536ab2..80d46e0 100644
--- a/services/core/java/com/android/server/connectivity/NetworkRanker.java
+++ b/services/core/java/com/android/server/connectivity/NetworkRanker.java
@@ -16,6 +16,9 @@
 
 package com.android.server.connectivity;
 
+import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
+import static android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED;
+import static android.net.NetworkCapabilities.TRANSPORT_VPN;
 import static android.net.NetworkScore.POLICY_IGNORE_ON_WIFI;
 
 import static com.android.internal.util.FunctionalUtils.findFirst;
@@ -42,13 +45,20 @@
             @NonNull final Collection<NetworkAgentInfo> nais) {
         final ArrayList<NetworkAgentInfo> candidates = new ArrayList<>(nais);
         candidates.removeIf(nai -> !nai.satisfies(request));
-        // Enforce policy.
-        filterBadWifiAvoidancePolicy(candidates);
+
+        // Enforce policy. The order in which the policy is computed is essential, because each
+        // step may remove some of the candidates. For example, filterValidated drops non-validated
+        // networks in presence of validated networks for INTERNET requests, but the bad wifi
+        // avoidance policy takes priority over this, so it must be done before.
+        filterVpn(candidates);
+        filterExplicitlySelected(candidates);
+        filterBadWifiAvoidance(candidates);
+        filterValidated(request, candidates);
 
         NetworkAgentInfo bestNetwork = null;
         int bestScore = Integer.MIN_VALUE;
         for (final NetworkAgentInfo nai : candidates) {
-            final int score = nai.getCurrentScore();
+            final int score = nai.getNetworkScore().getLegacyScore();
             if (score > bestScore) {
                 bestNetwork = nai;
                 bestScore = score;
@@ -57,9 +67,27 @@
         return bestNetwork;
     }
 
-    // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI.
-    private void filterBadWifiAvoidancePolicy(
+    // If a network is a VPN it has priority.
+    private void filterVpn(@NonNull final ArrayList<NetworkAgentInfo> candidates) {
+        final NetworkAgentInfo vpn = findFirst(candidates,
+                nai -> nai.networkCapabilities.hasTransport(TRANSPORT_VPN));
+        if (null == vpn) return; // No VPN : this policy doesn't apply.
+        candidates.removeIf(nai -> !nai.networkCapabilities.hasTransport(TRANSPORT_VPN));
+    }
+
+    // If some network is explicitly selected and set to accept unvalidated connectivity, then
+    // drop all networks that are not explicitly selected.
+    private void filterExplicitlySelected(
             @NonNull final ArrayList<NetworkAgentInfo> candidates) {
+        final NetworkAgentInfo explicitlySelected = findFirst(candidates,
+                nai -> nai.networkAgentConfig.explicitlySelected
+                        && nai.networkAgentConfig.acceptUnvalidated);
+        if (null == explicitlySelected) return; // No explicitly selected network accepting unvalid
+        candidates.removeIf(nai -> !nai.networkAgentConfig.explicitlySelected);
+    }
+
+    // If some network with wifi transport is present, drop all networks with POLICY_IGNORE_ON_WIFI.
+    private void filterBadWifiAvoidance(@NonNull final ArrayList<NetworkAgentInfo> candidates) {
         final NetworkAgentInfo wifi = findFirst(candidates,
                 nai -> nai.networkCapabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                         && nai.everValidated
@@ -71,4 +99,16 @@
         if (null == wifi) return; // No wifi : this policy doesn't apply
         candidates.removeIf(nai -> nai.getNetworkScore().hasPolicy(POLICY_IGNORE_ON_WIFI));
     }
+
+    // If some network is validated and the request asks for INTERNET, drop all networks that are
+    // not validated.
+    private void filterValidated(@NonNull final NetworkRequest request,
+            @NonNull final ArrayList<NetworkAgentInfo> candidates) {
+        if (!request.hasCapability(NET_CAPABILITY_INTERNET)) return;
+        final NetworkAgentInfo validated = findFirst(candidates,
+                nai -> nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+        if (null == validated) return; // No validated network
+        candidates.removeIf(nai ->
+                !nai.networkCapabilities.hasCapability(NET_CAPABILITY_VALIDATED));
+    }
 }
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 77f4093..e484ca0 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -216,14 +216,14 @@
      * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This
      * only applies to {@link VpnService} connections.
      */
-    private boolean mAlwaysOn = false;
+    @VisibleForTesting protected boolean mAlwaysOn = false;
 
     /**
      * Whether to disable traffic outside of this VPN even when the VPN is not connected. System
      * apps can still bypass by choosing explicit networks. Has no effect if {@link mAlwaysOn} is
-     * not set.
+     * not set. Applies to all types of VPNs.
      */
-    private boolean mLockdown = false;
+    @VisibleForTesting protected boolean mLockdown = false;
 
     /**
      * Set of packages in addition to the VPN app itself that can access the network directly when
@@ -252,14 +252,14 @@
     private final int mUserHandle;
 
     public Vpn(Looper looper, Context context, INetworkManagementService netService,
-            @UserIdInt int userHandle) {
-        this(looper, context, netService, userHandle,
+            @UserIdInt int userHandle, @NonNull KeyStore keyStore) {
+        this(looper, context, netService, userHandle, keyStore,
                 new SystemServices(context), new Ikev2SessionCreator());
     }
 
     @VisibleForTesting
     protected Vpn(Looper looper, Context context, INetworkManagementService netService,
-            int userHandle, SystemServices systemServices,
+            int userHandle, @NonNull KeyStore keyStore, SystemServices systemServices,
             Ikev2SessionCreator ikev2SessionCreator) {
         mContext = context;
         mNetd = netService;
@@ -285,7 +285,7 @@
         mNetworkCapabilities.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN);
         updateCapabilities(null /* defaultNetwork */);
 
-        loadAlwaysOnPackage();
+        loadAlwaysOnPackage(keyStore);
     }
 
     /**
@@ -437,23 +437,36 @@
     /**
      * Checks if a VPN app supports always-on mode.
      *
-     * In order to support the always-on feature, an app has to
+     * <p>In order to support the always-on feature, an app has to either have an installed
+     * PlatformVpnProfile, or:
+     *
      * <ul>
-     *     <li>target {@link VERSION_CODES#N API 24} or above, and
-     *     <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
-     *         meta-data field.
+     *   <li>target {@link VERSION_CODES#N API 24} or above, and
+     *   <li>not opt out through the {@link VpnService#SERVICE_META_DATA_SUPPORTS_ALWAYS_ON}
+     *       meta-data field.
      * </ul>
      *
      * @param packageName the canonical package name of the VPN app
+     * @param keyStore the keystore instance to use for checking if the app has a Platform VPN
+     *     profile installed.
      * @return {@code true} if and only if the VPN app exists and supports always-on mode
      */
-    public boolean isAlwaysOnPackageSupported(String packageName) {
+    public boolean isAlwaysOnPackageSupported(String packageName, @NonNull KeyStore keyStore) {
         enforceSettingsPermission();
 
         if (packageName == null) {
             return false;
         }
 
+        final long oldId = Binder.clearCallingIdentity();
+        try {
+            if (getVpnProfilePrivileged(packageName, keyStore) != null) {
+                return true;
+            }
+        } finally {
+            Binder.restoreCallingIdentity(oldId);
+        }
+
         PackageManager pm = mContext.getPackageManager();
         ApplicationInfo appInfo = null;
         try {
@@ -485,27 +498,31 @@
     }
 
     /**
-     * Configures an always-on VPN connection through a specific application.
-     * This connection is automatically granted and persisted after a reboot.
+     * Configures an always-on VPN connection through a specific application. This connection is
+     * automatically granted and persisted after a reboot.
      *
-     * <p>The designated package should exist and declare a {@link VpnService} in its
-     *    manifest guarded by {@link android.Manifest.permission.BIND_VPN_SERVICE},
-     *    otherwise the call will fail.
+     * <p>The designated package should either have a PlatformVpnProfile installed, or declare a
+     * {@link VpnService} in its manifest guarded by {@link
+     * android.Manifest.permission.BIND_VPN_SERVICE}, otherwise the call will fail.
      *
      * <p>Note that this method does not check if the VPN app supports always-on mode. The check is
-     *    delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this
-     *    method in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}.
+     * delayed to {@link #startAlwaysOnVpn()}, which is always called immediately after this method
+     * in {@link android.net.IConnectivityManager#setAlwaysOnVpnPackage}.
      *
      * @param packageName the package to designate as always-on VPN supplier.
      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
      * @param lockdownWhitelist packages to be whitelisted from lockdown.
+     * @param keyStore the Keystore instance to use for checking of PlatformVpnProfile(s)
      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
      */
     public synchronized boolean setAlwaysOnPackage(
-            String packageName, boolean lockdown, List<String> lockdownWhitelist) {
+            @Nullable String packageName,
+            boolean lockdown,
+            @Nullable List<String> lockdownWhitelist,
+            @NonNull KeyStore keyStore) {
         enforceControlPermissionOrInternalCaller();
 
-        if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist)) {
+        if (setAlwaysOnPackageInternal(packageName, lockdown, lockdownWhitelist, keyStore)) {
             saveAlwaysOnPackage();
             return true;
         }
@@ -513,20 +530,22 @@
     }
 
     /**
-     * Configures an always-on VPN connection through a specific application, the same as
-     * {@link #setAlwaysOnPackage}.
+     * Configures an always-on VPN connection through a specific application, the same as {@link
+     * #setAlwaysOnPackage}.
      *
-     * Does not perform permission checks. Does not persist any of the changes to storage.
+     * <p>Does not perform permission checks. Does not persist any of the changes to storage.
      *
      * @param packageName the package to designate as always-on VPN supplier.
      * @param lockdown whether to prevent traffic outside of a VPN, for example while connecting.
      * @param lockdownWhitelist packages to be whitelisted from lockdown. This is only used if
-     *        {@code lockdown} is {@code true}. Packages must not contain commas.
+     *     {@code lockdown} is {@code true}. Packages must not contain commas.
+     * @param keyStore the system keystore instance to check for profiles
      * @return {@code true} if the package has been set as always-on, {@code false} otherwise.
      */
     @GuardedBy("this")
     private boolean setAlwaysOnPackageInternal(
-            String packageName, boolean lockdown, List<String> lockdownWhitelist) {
+            @Nullable String packageName, boolean lockdown,
+            @Nullable List<String> lockdownWhitelist, @NonNull KeyStore keyStore) {
         if (VpnConfig.LEGACY_VPN.equals(packageName)) {
             Log.w(TAG, "Not setting legacy VPN \"" + packageName + "\" as always-on.");
             return false;
@@ -542,11 +561,18 @@
         }
 
         if (packageName != null) {
-            // TODO: Give the minimum permission possible; if there is a Platform VPN profile, only
-            // grant ACTIVATE_PLATFORM_VPN.
-            // Pre-authorize new always-on VPN package. Grant the full ACTIVATE_VPN appop, allowing
-            // both VpnService and Platform VPNs.
-            if (!setPackageAuthorization(packageName, VpnManager.TYPE_VPN_SERVICE)) {
+            final VpnProfile profile;
+            final long oldId = Binder.clearCallingIdentity();
+            try {
+                profile = getVpnProfilePrivileged(packageName, keyStore);
+            } finally {
+                Binder.restoreCallingIdentity(oldId);
+            }
+
+            // Pre-authorize new always-on VPN package.
+            final int grantType =
+                    (profile == null) ? VpnManager.TYPE_VPN_SERVICE : VpnManager.TYPE_VPN_PLATFORM;
+            if (!setPackageAuthorization(packageName, grantType)) {
                 return false;
             }
             mAlwaysOn = true;
@@ -611,11 +637,9 @@
         }
     }
 
-    /**
-     * Load the always-on package and lockdown config from Settings.Secure
-     */
+    /** Load the always-on package and lockdown config from Settings. */
     @GuardedBy("this")
-    private void loadAlwaysOnPackage() {
+    private void loadAlwaysOnPackage(@NonNull KeyStore keyStore) {
         final long token = Binder.clearCallingIdentity();
         try {
             final String alwaysOnPackage = mSystemServices.settingsSecureGetStringForUser(
@@ -626,17 +650,21 @@
                     Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST, mUserHandle);
             final List<String> whitelistedPackages = TextUtils.isEmpty(whitelistString)
                     ? Collections.emptyList() : Arrays.asList(whitelistString.split(","));
-            setAlwaysOnPackageInternal(alwaysOnPackage, alwaysOnLockdown, whitelistedPackages);
+            setAlwaysOnPackageInternal(
+                    alwaysOnPackage, alwaysOnLockdown, whitelistedPackages, keyStore);
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
     /**
+     * Starts the currently selected always-on VPN
+     *
+     * @param keyStore the keyStore instance for looking up PlatformVpnProfile(s)
      * @return {@code true} if the service was started, the service was already connected, or there
-     *         was no always-on VPN to start. {@code false} otherwise.
+     *     was no always-on VPN to start. {@code false} otherwise.
      */
-    public boolean startAlwaysOnVpn() {
+    public boolean startAlwaysOnVpn(@NonNull KeyStore keyStore) {
         final String alwaysOnPackage;
         synchronized (this) {
             alwaysOnPackage = getAlwaysOnPackage();
@@ -645,8 +673,8 @@
                 return true;
             }
             // Remove always-on VPN if it's not supported.
-            if (!isAlwaysOnPackageSupported(alwaysOnPackage)) {
-                setAlwaysOnPackage(null, false, null);
+            if (!isAlwaysOnPackageSupported(alwaysOnPackage, keyStore)) {
+                setAlwaysOnPackage(null, false, null, keyStore);
                 return false;
             }
             // Skip if the service is already established. This isn't bulletproof: it's not bound
@@ -657,10 +685,25 @@
             }
         }
 
-        // Tell the OS that background services in this app need to be allowed for
-        // a short time, so we can bootstrap the VPN service.
         final long oldId = Binder.clearCallingIdentity();
         try {
+            // Prefer VPN profiles, if any exist.
+            VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage, keyStore);
+            if (profile != null) {
+                startVpnProfilePrivileged(profile, alwaysOnPackage,
+                        null /* keyStore for private key retrieval - unneeded */);
+
+                // If the above startVpnProfilePrivileged() call returns, the Ikev2VpnProfile was
+                // correctly parsed, and the VPN has started running in a different thread. The only
+                // other possibility is that the above call threw an exception, which will be
+                // caught below, and returns false (clearing the always-on VPN). Once started, the
+                // Platform VPN cannot permanently fail, and is resilient to temporary failures. It
+                // will continue retrying until shut down by the user, or always-on is toggled off.
+                return true;
+            }
+
+            // Tell the OS that background services in this app need to be allowed for
+            // a short time, so we can bootstrap the VPN service.
             DeviceIdleInternal idleController =
                     LocalServices.getService(DeviceIdleInternal.class);
             idleController.addPowerSaveTempWhitelistApp(Process.myUid(), alwaysOnPackage,
@@ -675,6 +718,9 @@
                 Log.e(TAG, "VpnService " + serviceIntent + " failed to start", e);
                 return false;
             }
+        } catch (Exception e) {
+            Log.e(TAG, "Error starting always-on VPN", e);
+            return false;
         } finally {
             Binder.restoreCallingIdentity(oldId);
         }
@@ -773,6 +819,7 @@
     }
 
     /** Prepare the VPN for the given package. Does not perform permission checks. */
+    @GuardedBy("this")
     private void prepareInternal(String newPackage) {
         long token = Binder.clearCallingIdentity();
         try {
@@ -1898,6 +1945,27 @@
         // Prepare arguments for racoon.
         String[] racoon = null;
         switch (profile.type) {
+            case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
+                // Secret key is still just the alias (not the actual private key). The private key
+                // is retrieved from the KeyStore during conversion of the VpnProfile to an
+                // Ikev2VpnProfile.
+                profile.ipsecSecret = Ikev2VpnProfile.PREFIX_KEYSTORE_ALIAS + privateKey;
+                profile.ipsecUserCert = userCert;
+                // Fallthrough
+            case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
+                profile.ipsecCaCert = caCert;
+
+                // Start VPN profile
+                startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore);
+                return;
+            case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
+                // Ikev2VpnProfiles expect a base64-encoded preshared key.
+                profile.ipsecSecret =
+                        Ikev2VpnProfile.encodeForIpsecSecret(profile.ipsecSecret.getBytes());
+
+                // Start VPN profile
+                startVpnProfilePrivileged(profile, VpnConfig.LEGACY_VPN, keyStore);
+                return;
             case VpnProfile.TYPE_L2TP_IPSEC_PSK:
                 racoon = new String[] {
                     iface, profile.server, "udppsk", profile.ipsecIdentifier,
@@ -2820,6 +2888,10 @@
         return isVpnProfilePreConsented(mContext, packageName);
     }
 
+    private boolean isCurrentIkev2VpnLocked(@NonNull String packageName) {
+        return isCurrentPreparedPackage(packageName) && mVpnRunner instanceof IkeV2VpnRunner;
+    }
+
     /**
      * Deletes an app-provisioned VPN profile.
      *
@@ -2836,6 +2908,17 @@
 
         Binder.withCleanCallingIdentity(
                 () -> {
+                    // If this profile is providing the current VPN, turn it off, disabling
+                    // always-on as well if enabled.
+                    if (isCurrentIkev2VpnLocked(packageName)) {
+                        if (mAlwaysOn) {
+                            // Will transitively call prepareInternal(VpnConfig.LEGACY_VPN).
+                            setAlwaysOnPackage(null, false, null, keyStore);
+                        } else {
+                            prepareInternal(VpnConfig.LEGACY_VPN);
+                        }
+                    }
+
                     keyStore.delete(getProfileNameForPackage(packageName), Process.SYSTEM_UID);
                 });
     }
@@ -2889,24 +2972,35 @@
                         throw new IllegalArgumentException("No profile found for " + packageName);
                     }
 
-                    startVpnProfilePrivileged(profile, packageName);
+                    startVpnProfilePrivileged(profile, packageName,
+                            null /* keyStore for private key retrieval - unneeded */);
                 });
     }
 
-    private void startVpnProfilePrivileged(
-            @NonNull VpnProfile profile, @NonNull String packageName) {
-        // Ensure that no other previous instance is running.
-        if (mVpnRunner != null) {
-            mVpnRunner.exit();
-            mVpnRunner = null;
-        }
+    private synchronized void startVpnProfilePrivileged(
+            @NonNull VpnProfile profile, @NonNull String packageName, @Nullable KeyStore keyStore) {
+        // Make sure VPN is prepared. This method can be called by user apps via startVpnProfile(),
+        // by the Setting app via startLegacyVpn(), or by ConnectivityService via
+        // startAlwaysOnVpn(), so this is the common place to prepare the VPN. This also has the
+        // nice property of ensuring there are no other VpnRunner instances running.
+        prepareInternal(packageName);
         updateState(DetailedState.CONNECTING, "startPlatformVpn");
 
         try {
             // Build basic config
             mConfig = new VpnConfig();
-            mConfig.user = packageName;
-            mConfig.isMetered = profile.isMetered;
+            if (VpnConfig.LEGACY_VPN.equals(packageName)) {
+                mConfig.legacy = true;
+                mConfig.session = profile.name;
+                mConfig.user = profile.key;
+
+                // TODO: Add support for configuring meteredness via Settings. Until then, use a
+                // safe default.
+                mConfig.isMetered = true;
+            } else {
+                mConfig.user = packageName;
+                mConfig.isMetered = profile.isMetered;
+            }
             mConfig.startTime = SystemClock.elapsedRealtime();
             mConfig.proxyInfo = profile.proxy;
 
@@ -2914,7 +3008,8 @@
                 case VpnProfile.TYPE_IKEV2_IPSEC_USER_PASS:
                 case VpnProfile.TYPE_IKEV2_IPSEC_PSK:
                 case VpnProfile.TYPE_IKEV2_IPSEC_RSA:
-                    mVpnRunner = new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile));
+                    mVpnRunner =
+                            new IkeV2VpnRunner(Ikev2VpnProfile.fromVpnProfile(profile, keyStore));
                     mVpnRunner.start();
                     break;
                 default:
@@ -2946,11 +3041,9 @@
 
         // To stop the VPN profile, the caller must be the current prepared package and must be
         // running an Ikev2VpnProfile.
-        if (!isCurrentPreparedPackage(packageName) && mVpnRunner instanceof IkeV2VpnRunner) {
-            return;
+        if (isCurrentIkev2VpnLocked(packageName)) {
+            prepareInternal(VpnConfig.LEGACY_VPN);
         }
-
-        prepareInternal(VpnConfig.LEGACY_VPN);
     }
 
     /**
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 6d130d9..4a1afb2 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -1216,7 +1216,7 @@
         for (SyncOperation op: ops) {
             if (op.isPeriodic && op.target.matchesSpec(target)) {
                 periodicSyncs.add(new PeriodicSync(op.target.account, op.target.provider,
-                        op.extras, op.periodMillis / 1000, op.flexMillis / 1000));
+                        op.getClonedExtras(), op.periodMillis / 1000, op.flexMillis / 1000));
             }
         }
 
@@ -1478,7 +1478,7 @@
             Slog.e(TAG, "Can't schedule null sync operation.");
             return;
         }
-        if (!syncOperation.ignoreBackoff()) {
+        if (!syncOperation.hasIgnoreBackoff()) {
             Pair<Long, Long> backoff = mSyncStorageEngine.getBackoff(syncOperation.target);
             if (backoff == null) {
                 Slog.e(TAG, "Couldn't find backoff values for "
@@ -1631,7 +1631,7 @@
             getSyncStorageEngine().markPending(syncOperation.target, true);
         }
 
-        if (syncOperation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING)) {
+        if (syncOperation.hasRequireCharging()) {
             b.setRequiresCharging(true);
         }
 
@@ -1686,7 +1686,7 @@
         List<SyncOperation> ops = getAllPendingSyncs();
         for (SyncOperation op: ops) {
             if (!op.isPeriodic && op.target.matchesSpec(info)
-                    && syncExtrasEquals(extras, op.extras, false)) {
+                    && op.areExtrasEqual(extras, /*includeSyncSettings=*/ false)) {
                 cancelJob(op, "cancelScheduledSyncOperation");
             }
         }
@@ -1704,15 +1704,9 @@
             Log.d(TAG, "encountered error(s) during the sync: " + syncResult + ", " + operation);
         }
 
-        // The SYNC_EXTRAS_IGNORE_BACKOFF only applies to the first attempt to sync a given
-        // request. Retries of the request will always honor the backoff, so clear the
-        // flag in case we retry this request.
-        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false)) {
-            operation.extras.remove(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
-        }
+        operation.enableBackoff();
 
-        if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false)
-                && !syncResult.syncAlreadyInProgress) {
+        if (operation.hasDoNotRetry() && !syncResult.syncAlreadyInProgress) {
             // syncAlreadyInProgress flag is set by AbstractThreadedSyncAdapter. The sync adapter
             // has no way of knowing that a sync error occured. So we DO retry if the error is
             // syncAlreadyInProgress.
@@ -1720,10 +1714,9 @@
                 Log.d(TAG, "not retrying sync operation because SYNC_EXTRAS_DO_NOT_RETRY was specified "
                         + operation);
             }
-        } else if (operation.extras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false)
-                && !syncResult.syncAlreadyInProgress) {
+        } else if (operation.isUpload() && !syncResult.syncAlreadyInProgress) {
             // If this was an upward sync then schedule a two-way sync immediately.
-            operation.extras.remove(ContentResolver.SYNC_EXTRAS_UPLOAD);
+            operation.enableTwoWaySync();
             if (isLoggable) {
                 Log.d(TAG, "retrying sync operation as a two-way sync because an upload-only sync "
                         + "encountered an error: " + operation);
@@ -3326,7 +3319,7 @@
             List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
-                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
+                        && op.areExtrasEqual(extras, /*includeSyncSettings=*/ true)) {
                     maybeUpdateSyncPeriodH(op, pollFrequencyMillis, flexMillis);
                     return;
                 }
@@ -3408,7 +3401,7 @@
             List<SyncOperation> ops = getAllPendingSyncs();
             for (SyncOperation op: ops) {
                 if (op.isPeriodic && op.target.matchesSpec(target)
-                        && syncExtrasEquals(op.extras, extras, true /* includeSyncSettings */)) {
+                        && op.areExtrasEqual(extras, /*includeSyncSettings=*/ true)) {
                     removePeriodicSyncInternalH(op, why);
                 }
             }
@@ -3559,16 +3552,18 @@
                 activeSyncContext.mIsLinkedToDeath = true;
                 syncAdapter.linkToDeath(activeSyncContext, 0);
 
-                mLogger.log("Sync start: account=" + syncOperation.target.account,
-                        " authority=", syncOperation.target.provider,
-                        " reason=", SyncOperation.reasonToString(null, syncOperation.reason),
-                        " extras=", SyncOperation.extrasToString(syncOperation.extras),
-                        " adapter=", activeSyncContext.mSyncAdapter);
+                if (mLogger.enabled()) {
+                    mLogger.log("Sync start: account=" + syncOperation.target.account,
+                            " authority=", syncOperation.target.provider,
+                            " reason=", SyncOperation.reasonToString(null, syncOperation.reason),
+                            " extras=", syncOperation.getExtrasAsString(),
+                            " adapter=", activeSyncContext.mSyncAdapter);
+                }
 
                 activeSyncContext.mSyncAdapter = ISyncAdapter.Stub.asInterface(syncAdapter);
                 activeSyncContext.mSyncAdapter
                         .startSync(activeSyncContext, syncOperation.target.provider,
-                                syncOperation.target.account, syncOperation.extras);
+                                syncOperation.target.account, syncOperation.getClonedExtras());
 
                 mLogger.log("Sync is running now...");
             } catch (RemoteException remoteExc) {
@@ -3602,9 +3597,8 @@
                         continue;
                     }
                     if (extras != null &&
-                            !syncExtrasEquals(activeSyncContext.mSyncOperation.extras,
-                                    extras,
-                                    false /* no config settings */)) {
+                            !activeSyncContext.mSyncOperation.areExtrasEqual(extras,
+                                    /*includeSyncSettings=*/ false)) {
                         continue;
                     }
                     SyncJobService.callJobFinished(activeSyncContext.mSyncOperation.jobId, false,
diff --git a/services/core/java/com/android/server/content/SyncOperation.java b/services/core/java/com/android/server/content/SyncOperation.java
index 2abc2e6..09b7828 100644
--- a/services/core/java/com/android/server/content/SyncOperation.java
+++ b/services/core/java/com/android/server/content/SyncOperation.java
@@ -74,7 +74,14 @@
     /** Where this sync was initiated. */
     public final int syncSource;
     public final boolean allowParallelSyncs;
-    public final Bundle extras;
+
+    /**
+     * Sync extras. Note, DO NOT modify this bundle directly. When changing the content, always
+     * create a copy, update it, set it in this field. This is to avoid concurrent modifications
+     * when other threads are reading it.
+     */
+    private volatile Bundle mImmutableExtras;
+
     public final boolean isPeriodic;
     /** jobId of the periodic SyncOperation that initiated this one */
     public final int sourcePeriodicId;
@@ -118,20 +125,21 @@
 
     public SyncOperation(SyncOperation op, long periodMillis, long flexMillis) {
         this(op.target, op.owningUid, op.owningPackage, op.reason, op.syncSource,
-                new Bundle(op.extras), op.allowParallelSyncs, op.isPeriodic, op.sourcePeriodicId,
+                op.mImmutableExtras, op.allowParallelSyncs, op.isPeriodic, op.sourcePeriodicId,
                 periodMillis, flexMillis, ContentResolver.SYNC_EXEMPTION_NONE);
     }
 
     public SyncOperation(SyncStorageEngine.EndPoint info, int owningUid, String owningPackage,
-                         int reason, int source, Bundle extras, boolean allowParallelSyncs,
-                         boolean isPeriodic, int sourcePeriodicId, long periodMillis,
-                         long flexMillis, @SyncExemption int syncExemptionFlag) {
+            int reason, int source, Bundle extras,
+            boolean allowParallelSyncs,
+            boolean isPeriodic, int sourcePeriodicId, long periodMillis,
+            long flexMillis, @SyncExemption int syncExemptionFlag) {
         this.target = info;
         this.owningUid = owningUid;
         this.owningPackage = owningPackage;
         this.reason = reason;
         this.syncSource = source;
-        this.extras = new Bundle(extras);
+        this.mImmutableExtras = new Bundle(extras);
         this.allowParallelSyncs = allowParallelSyncs;
         this.isPeriodic = isPeriodic;
         this.sourcePeriodicId = sourcePeriodicId;
@@ -148,7 +156,7 @@
             return null;
         }
         SyncOperation op = new SyncOperation(target, owningUid, owningPackage, reason, syncSource,
-                new Bundle(extras), allowParallelSyncs, false, jobId /* sourcePeriodicId */,
+                mImmutableExtras, allowParallelSyncs, false, jobId /* sourcePeriodicId */,
                 periodMillis, flexMillis, ContentResolver.SYNC_EXEMPTION_NONE);
         return op;
     }
@@ -160,7 +168,10 @@
         reason = other.reason;
         syncSource = other.syncSource;
         allowParallelSyncs = other.allowParallelSyncs;
-        extras = new Bundle(other.extras);
+
+        // Since we treat this field as immutable, it's okay to use a shallow copy here.
+        // No need to create a copy.
+        mImmutableExtras = other.mImmutableExtras;
         wakeLockName = other.wakeLockName();
         isPeriodic = other.isPeriodic;
         sourcePeriodicId = other.sourcePeriodicId;
@@ -173,7 +184,8 @@
     /**
      * All fields are stored in a corresponding key in the persistable bundle.
      *
-     * {@link #extras} is a Bundle and can contain parcelable objects. But only the type Account
+     * {@link #mImmutableExtras} is a Bundle and can contain parcelable objects.
+     * But only the type Account
      * is allowed {@link ContentResolver#validateSyncExtrasBundle(Bundle)} that can't be stored in
      * a PersistableBundle. For every value of type Account with key 'key', we store a
      * PersistableBundle containing account information at key 'ACCOUNT:key'. The Account object
@@ -188,7 +200,9 @@
         PersistableBundle jobInfoExtras = new PersistableBundle();
 
         PersistableBundle syncExtrasBundle = new PersistableBundle();
-        for (String key: extras.keySet()) {
+
+        final Bundle extras = mImmutableExtras;
+        for (String key : extras.keySet()) {
             Object value = extras.get(key);
             if (value instanceof Account) {
                 Account account = (Account) value;
@@ -327,7 +341,7 @@
 
     boolean matchesPeriodicOperation(SyncOperation other) {
         return target.matchesSpec(other.target)
-                && SyncManager.syncExtrasEquals(extras, other.extras, true)
+                && SyncManager.syncExtrasEquals(mImmutableExtras, other.mImmutableExtras, true)
                 && periodMillis == other.periodMillis && flexMillis == other.flexMillis;
     }
 
@@ -345,6 +359,7 @@
     }
 
     private String toKey() {
+        final Bundle extras = mImmutableExtras;
         StringBuilder sb = new StringBuilder();
         sb.append("provider: ").append(target.provider);
         sb.append(" account {name=" + target.account.name
@@ -372,6 +387,7 @@
 
     String dump(PackageManager pm, boolean shorter, SyncAdapterStateFetcher appStates,
             boolean logSafe) {
+        final Bundle extras = mImmutableExtras;
         StringBuilder sb = new StringBuilder();
         sb.append("JobId=").append(jobId)
                 .append(" ")
@@ -468,33 +484,67 @@
     }
 
     boolean isInitialization() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false);
     }
 
     boolean isExpedited() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_EXPEDITED, false);
     }
 
-    boolean ignoreBackoff() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
+    boolean isUpload() {
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_UPLOAD, false);
+    }
+
+    /**
+     * Disable SYNC_EXTRAS_UPLOAD, so it will be a two-way (normal) sync.
+     */
+    void enableTwoWaySync() {
+        removeExtra(ContentResolver.SYNC_EXTRAS_UPLOAD);
+    }
+
+    boolean hasIgnoreBackoff() {
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF, false);
+    }
+
+    /**
+     * Disable SYNC_EXTRAS_IGNORE_BACKOFF.
+     *
+     * The SYNC_EXTRAS_IGNORE_BACKOFF only applies to the first attempt to sync a given
+     * request. Retries of the request will always honor the backoff, so clear the
+     * flag in case we retry this request.
+     */
+    void enableBackoff() {
+        removeExtra(ContentResolver.SYNC_EXTRAS_IGNORE_BACKOFF);
+    }
+
+    boolean hasDoNotRetry() {
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_DO_NOT_RETRY, false);
     }
 
     boolean isNotAllowedOnMetered() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_DISALLOW_METERED, false);
     }
 
     boolean isManual() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_MANUAL, false);
     }
 
     boolean isIgnoreSettings() {
-        return extras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_IGNORE_SETTINGS, false);
+    }
+
+    boolean hasRequireCharging() {
+        return mImmutableExtras.getBoolean(ContentResolver.SYNC_EXTRAS_REQUIRE_CHARGING, false);
     }
 
     boolean isAppStandbyExempted() {
         return syncExemptionFlag != ContentResolver.SYNC_EXEMPTION_NONE;
     }
 
+    boolean areExtrasEqual(Bundle other, boolean includeSyncSettings) {
+        return SyncManager.syncExtrasEquals(mImmutableExtras, other, includeSyncSettings);
+    }
+
     static void extrasToStringBuilder(Bundle bundle, StringBuilder sb) {
         if (bundle == null) {
             sb.append("null");
@@ -507,7 +557,7 @@
         sb.append("]");
     }
 
-    static String extrasToString(Bundle bundle) {
+    private static String extrasToString(Bundle bundle) {
         final StringBuilder sb = new StringBuilder();
         extrasToStringBuilder(bundle, sb);
         return sb.toString();
@@ -531,4 +581,25 @@
         logArray[3] = target.account.name.hashCode();
         return logArray;
     }
+
+    /**
+     * Removes a sync extra. Note do not call it from multiple threads simultaneously.
+     */
+    private void removeExtra(String key) {
+        final Bundle b = mImmutableExtras;
+        if (!b.containsKey(key)) {
+            return;
+        }
+        final Bundle clone = new Bundle(b);
+        clone.remove(key);
+        mImmutableExtras = clone;
+    }
+
+    public Bundle getClonedExtras() {
+        return new Bundle(mImmutableExtras);
+    }
+
+    public String getExtrasAsString() {
+        return extrasToString(mImmutableExtras);
+    }
 }
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index afdcda9..8c510b7 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -137,7 +137,7 @@
     /**
      * String names for the sync source types.
      *
-     * KEEP THIS AND {@link SyncStatusInfo#SOURCE_COUNT} IN SYNC.
+     * KEEP THIS AND {@link SyncStatusInfo}.SOURCE_COUNT IN SYNC.
      */
     public static final String[] SOURCES = {
             "OTHER",
@@ -1117,7 +1117,7 @@
                 Slog.v(TAG, "setActiveSync: account="
                         + " auth=" + activeSyncContext.mSyncOperation.target
                         + " src=" + activeSyncContext.mSyncOperation.syncSource
-                        + " extras=" + activeSyncContext.mSyncOperation.extras);
+                        + " extras=" + activeSyncContext.mSyncOperation.getExtrasAsString());
             }
             final EndPoint info = activeSyncContext.mSyncOperation.target;
             AuthorityInfo authorityInfo = getOrCreateAuthorityLocked(
@@ -1179,7 +1179,7 @@
             item.eventTime = now;
             item.source = op.syncSource;
             item.reason = op.reason;
-            item.extras = op.extras;
+            item.extras = op.getClonedExtras();
             item.event = EVENT_START;
             item.syncExemptionFlag = op.syncExemptionFlag;
             mSyncHistory.add(0, item);
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index ac41434..18adc0b 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.server.display;
 
+import android.hardware.display.DeviceProductInfo;
 import android.hardware.display.DisplayViewport;
 import android.util.DisplayMetrics;
 import android.view.Display;
@@ -288,6 +289,13 @@
     public DisplayAddress address;
 
     /**
+     * Product-specific information about the display or the directly connected device on the
+     * display chain. For example, if the display is transitively connected, this field may contain
+     * product information about the intermediate device.
+     */
+    public DeviceProductInfo deviceProductInfo;
+
+    /**
      * Display state.
      */
     public int state = Display.STATE_ON;
@@ -360,6 +368,7 @@
                 || rotation != other.rotation
                 || type != other.type
                 || !Objects.equals(address, other.address)
+                || !Objects.equals(deviceProductInfo, other.deviceProductInfo)
                 || ownerUid != other.ownerUid
                 || !Objects.equals(ownerPackageName, other.ownerPackageName)) {
             diff |= DIFF_OTHER;
@@ -396,6 +405,7 @@
         rotation = other.rotation;
         type = other.type;
         address = other.address;
+        deviceProductInfo = other.deviceProductInfo;
         state = other.state;
         ownerUid = other.ownerUid;
         ownerPackageName = other.ownerPackageName;
@@ -429,6 +439,7 @@
         if (address != null) {
             sb.append(", address ").append(address);
         }
+        sb.append(", deviceProductInfo ").append(deviceProductInfo);
         sb.append(", state ").append(Display.stateToString(state));
         if (ownerUid != 0 || ownerPackageName != null) {
             sb.append(", owner ").append(ownerPackageName);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 8bbeabf..7cb8458 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -73,7 +73,7 @@
     private static final int GLOBAL_ID = -1;
 
     // The tolerance within which we consider something approximately equals.
-    private static final float EPSILON = 0.01f;
+    private static final float FLOAT_TOLERANCE = 0.01f;
 
     private final Object mLock = new Object();
     private final Context mContext;
@@ -267,8 +267,8 @@
             // Some refresh rates are calculated based on frame timings, so they aren't *exactly*
             // equal to expected refresh rate. Given that, we apply a bit of tolerance to this
             // comparison.
-            if (refreshRate < (minRefreshRate - EPSILON)
-                    || refreshRate > (maxRefreshRate + EPSILON)) {
+            if (refreshRate < (minRefreshRate - FLOAT_TOLERANCE)
+                    || refreshRate > (maxRefreshRate + FLOAT_TOLERANCE)) {
                 if (DEBUG) {
                     Slog.w(TAG, "Discarding mode " + mode.getModeId()
                             + ", outside refresh rate bounds"
@@ -487,12 +487,18 @@
         public RefreshRateRange() {}
 
         public RefreshRateRange(float min, float max) {
-            if (min < 0 || max < 0 || min > max) {
+            if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) {
                 Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : "
                         + min + " " + max);
                 this.min = this.max = 0;
                 return;
             }
+            if (min > max) {
+                // Min and max are within epsilon of each other, but in the wrong order.
+                float t = min;
+                min = max;
+                max = t;
+            }
             this.min = min;
             this.max = max;
         }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 4ebbdda..e578ac1 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -513,6 +513,7 @@
                 mInfo.densityDpi = (int) (mDisplayInfo.density * 160 + 0.5f);
                 mInfo.xDpi = config.xDpi;
                 mInfo.yDpi = config.yDpi;
+                mInfo.deviceProductInfo = mDisplayInfo.deviceProductInfo;
 
                 // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
@@ -891,8 +892,8 @@
             pw.println("mBacklight=" + mBacklight);
             pw.println("mAllmSupported=" + mAllmSupported);
             pw.println("mAllmRequested=" + mAllmRequested);
-            pw.println("mGameContentTypeSupported" + mGameContentTypeSupported);
-            pw.println("mGameContentTypeRequested" + mGameContentTypeRequested);
+            pw.println("mGameContentTypeSupported=" + mGameContentTypeSupported);
+            pw.println("mGameContentTypeRequested=" + mGameContentTypeRequested);
             pw.println("mDisplayInfo=" + mDisplayInfo);
             pw.println("mDisplayConfigs=");
             for (int i = 0; i < mDisplayConfigs.length; i++) {
@@ -902,14 +903,7 @@
             for (int i = 0; i < mSupportedModes.size(); i++) {
                 pw.println("  " + mSupportedModes.valueAt(i));
             }
-            pw.print("mSupportedColorModes=[");
-            for (int i = 0; i < mSupportedColorModes.size(); i++) {
-                if (i != 0) {
-                    pw.print(", ");
-                }
-                pw.print(mSupportedColorModes.get(i));
-            }
-            pw.println("]");
+            pw.print("mSupportedColorModes=" + mSupportedColorModes.toString());
         }
 
         private int findDisplayConfigIdLocked(int modeId) {
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 0c9445a..ac81a6c 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -269,6 +269,7 @@
 
             mBaseDisplayInfo.type = deviceInfo.type;
             mBaseDisplayInfo.address = deviceInfo.address;
+            mBaseDisplayInfo.deviceProductInfo = deviceInfo.deviceProductInfo;
             mBaseDisplayInfo.name = deviceInfo.name;
             mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
             mBaseDisplayInfo.appWidth = maskedWidth;
diff --git a/services/core/java/com/android/server/firewall/IntentFirewall.java b/services/core/java/com/android/server/firewall/IntentFirewall.java
index c2af29c..1139d28 100644
--- a/services/core/java/com/android/server/firewall/IntentFirewall.java
+++ b/services/core/java/com/android/server/firewall/IntentFirewall.java
@@ -16,6 +16,7 @@
 
 package com.android.server.firewall;
 
+import android.annotation.NonNull;
 import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Intent;
@@ -521,6 +522,11 @@
             return;
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(@NonNull FirewallIntentFilter input) {
+            return input;
+        }
+
         public void queryByComponent(ComponentName componentName, List<Rule> candidateRules) {
             Rule[] rules = mRulesByComponent.get(componentName);
             if (rules != null) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index 6174e54..b84d322 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -77,7 +77,7 @@
 
     private static final int NUM_LOGICAL_ADDRESS = 16;
 
-    private static final int MAX_CEC_MESSAGE_HISTORY = 200;
+    private static final int MAX_HDMI_MESSAGE_HISTORY = 250;
 
     // Predicate for whether the given logical address is remote device's one or not.
     private final Predicate<Integer> mRemoteDeviceAddressPredicate = new Predicate<Integer>() {
@@ -111,9 +111,9 @@
     // Stores the local CEC devices in the system. Device type is used for key.
     private final SparseArray<HdmiCecLocalDevice> mLocalDevices = new SparseArray<>();
 
-    // Stores recent CEC messages history for debugging purpose.
-    private final ArrayBlockingQueue<MessageHistoryRecord> mMessageHistory =
-            new ArrayBlockingQueue<>(MAX_CEC_MESSAGE_HISTORY);
+    // Stores recent CEC messages and HDMI Hotplug event history for debugging purpose.
+    private final ArrayBlockingQueue<Dumpable> mMessageHistory =
+            new ArrayBlockingQueue<>(MAX_HDMI_MESSAGE_HISTORY);
 
     private final NativeWrapper mNativeWrapperImpl;
 
@@ -618,7 +618,7 @@
     void sendCommand(final HdmiCecMessage cecMessage,
             final HdmiControlService.SendMessageCallback callback) {
         assertRunOnServiceThread();
-        addMessageToHistory(false /* isReceived */, cecMessage);
+        addCecMessageToHistory(false /* isReceived */, cecMessage);
         runOnIoThread(new Runnable() {
             @Override
             public void run() {
@@ -658,7 +658,7 @@
         assertRunOnServiceThread();
         HdmiCecMessage command = HdmiCecMessageBuilder.of(srcAddress, dstAddress, body);
         HdmiLogger.debug("[R]:" + command);
-        addMessageToHistory(true /* isReceived */, command);
+        addCecMessageToHistory(true /* isReceived */, command);
         onReceiveCommand(command);
     }
 
@@ -669,16 +669,26 @@
     private void handleHotplug(int port, boolean connected) {
         assertRunOnServiceThread();
         HdmiLogger.debug("Hotplug event:[port:%d, connected:%b]", port, connected);
+        addHotplugEventToHistory(port, connected);
         mService.onHotplug(port, connected);
     }
 
     @ServiceThreadOnly
-    private void addMessageToHistory(boolean isReceived, HdmiCecMessage message) {
+    private void addHotplugEventToHistory(int port, boolean connected) {
         assertRunOnServiceThread();
-        MessageHistoryRecord record = new MessageHistoryRecord(isReceived, message);
-        if (!mMessageHistory.offer(record)) {
+        addEventToHistory(new HotplugHistoryRecord(port, connected));
+    }
+
+    @ServiceThreadOnly
+    private void addCecMessageToHistory(boolean isReceived, HdmiCecMessage message) {
+        assertRunOnServiceThread();
+        addEventToHistory(new MessageHistoryRecord(isReceived, message));
+    }
+
+    private void addEventToHistory(Dumpable event) {
+        if (!mMessageHistory.offer(event)) {
             mMessageHistory.poll();
-            mMessageHistory.offer(record);
+            mMessageHistory.offer(event);
         }
     }
 
@@ -689,10 +699,11 @@
             mLocalDevices.valueAt(i).dump(pw);
             pw.decreaseIndent();
         }
+
         pw.println("CEC message history:");
         pw.increaseIndent();
         final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        for (MessageHistoryRecord record : mMessageHistory) {
+        for (Dumpable record : mMessageHistory) {
             record.dump(pw, sdf);
         }
         pw.decreaseIndent();
@@ -792,17 +803,27 @@
         }
     }
 
-    private final class MessageHistoryRecord {
-        private final long mTime;
+    private abstract static class Dumpable {
+        protected final long mTime;
+
+        Dumpable() {
+            mTime = System.currentTimeMillis();
+        }
+
+        abstract void dump(IndentingPrintWriter pw, SimpleDateFormat sdf);
+    }
+
+    private static final class MessageHistoryRecord extends Dumpable {
         private final boolean mIsReceived; // true if received message and false if sent message
         private final HdmiCecMessage mMessage;
 
-        public MessageHistoryRecord(boolean isReceived, HdmiCecMessage message) {
-            mTime = System.currentTimeMillis();
+        MessageHistoryRecord(boolean isReceived, HdmiCecMessage message) {
+            super();
             mIsReceived = isReceived;
             mMessage = message;
         }
 
+        @Override
         void dump(final IndentingPrintWriter pw, SimpleDateFormat sdf) {
             pw.print(mIsReceived ? "[R]" : "[S]");
             pw.print(" time=");
@@ -811,4 +832,26 @@
             pw.println(mMessage);
         }
     }
+
+    private static final class HotplugHistoryRecord extends Dumpable {
+        private final int mPort;
+        private final boolean mConnected;
+
+        HotplugHistoryRecord(int port, boolean connected) {
+            super();
+            mPort = port;
+            mConnected = connected;
+        }
+
+        @Override
+        void dump(final IndentingPrintWriter pw, SimpleDateFormat sdf) {
+            pw.print("[H]");
+            pw.print(" time=");
+            pw.print(sdf.format(new Date(mTime)));
+            pw.print(" hotplug port=");
+            pw.print(mPort);
+            pw.print(" connected=");
+            pw.println(mConnected);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index dde873b..e5a08d3 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -70,6 +70,9 @@
 
     private static final String TAG = "HdmiCecLocalDeviceAudioSystem";
 
+    private static final boolean WAKE_ON_HOTPLUG =
+            SystemProperties.getBoolean(Constants.PROPERTY_WAKE_ON_HOTPLUG, false);
+
     // Whether the System Audio Control feature is enabled or not. True by default.
     @GuardedBy("mLock")
     private boolean mSystemAudioControlFeatureEnabled;
@@ -318,7 +321,7 @@
     @ServiceThreadOnly
     void onHotplug(int portId, boolean connected) {
         assertRunOnServiceThread();
-        if (connected) {
+        if (WAKE_ON_HOTPLUG && connected) {
             mService.wakeUp();
         }
         if (mService.getPortInfo(portId).getType() == HdmiPortInfo.PORT_OUTPUT) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
index 9f76e1e..eac2d24 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerInternal.java
@@ -18,12 +18,11 @@
 
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
-import android.content.ComponentName;
-import android.view.autofill.AutofillId;
 import android.view.inputmethod.InlineSuggestionsRequest;
 import android.view.inputmethod.InputMethodInfo;
 
 import com.android.internal.view.IInlineSuggestionsRequestCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 import com.android.server.LocalServices;
 
 import java.util.Collections;
@@ -74,13 +73,11 @@
      * Called by the Autofill Frameworks to request an {@link InlineSuggestionsRequest} from
      * the input method.
      *
-     * @param componentName {@link ComponentName} of current app/activity.
-     * @param autofillId {@link AutofillId} of currently focused field.
+     * @param requestInfo information needed to create an {@link InlineSuggestionsRequest}.
      * @param cb {@link IInlineSuggestionsRequestCallback} used to pass back the request object.
      */
     public abstract void onCreateInlineSuggestionsRequest(@UserIdInt int userId,
-            ComponentName componentName, AutofillId autofillId,
-            IInlineSuggestionsRequestCallback cb);
+            InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb);
 
     /**
      * Force switch to the enabled input method by {@code imeId} for current user. If the input
@@ -124,7 +121,7 @@
 
                 @Override
                 public void onCreateInlineSuggestionsRequest(int userId,
-                        ComponentName componentName, AutofillId autofillId,
+                        InlineSuggestionsRequestInfo requestInfo,
                         IInlineSuggestionsRequestCallback cb) {
                 }
 
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 47622f3..87262a8 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -109,7 +109,6 @@
 import android.view.Window;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import android.view.autofill.AutofillId;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InlineSuggestionsRequest;
 import android.view.inputmethod.InputBinding;
@@ -150,6 +149,7 @@
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
 import com.android.internal.view.IInputSessionCallback;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 import com.android.internal.view.InputBindResult;
 import com.android.server.EventLogTags;
 import com.android.server.LocalServices;
@@ -1388,6 +1388,44 @@
         }
     }
 
+    private static final class UserSwitchHandlerTask implements Runnable {
+        final InputMethodManagerService mService;
+
+        @UserIdInt
+        final int mToUserId;
+
+        @Nullable
+        IInputMethodClient mClientToBeReset;
+
+        UserSwitchHandlerTask(InputMethodManagerService service, @UserIdInt int toUserId,
+                @Nullable IInputMethodClient clientToBeReset) {
+            mService = service;
+            mToUserId = toUserId;
+            mClientToBeReset = clientToBeReset;
+        }
+
+        @Override
+        public void run() {
+            synchronized (mService.mMethodMap) {
+                if (mService.mUserSwitchHandlerTask != this) {
+                    // This task was already canceled before it is handled here. So do nothing.
+                    return;
+                }
+                mService.switchUserOnHandlerLocked(mService.mUserSwitchHandlerTask.mToUserId,
+                        mClientToBeReset);
+                mService.mUserSwitchHandlerTask = null;
+            }
+        }
+    }
+
+    /**
+     * When non-{@code null}, this represents pending user-switch task, which is to be executed as
+     * a handler callback.  This needs to be set and unset only within the lock.
+     */
+    @Nullable
+    @GuardedBy("mMethodMap")
+    private UserSwitchHandlerTask mUserSwitchHandlerTask;
+
     public static final class Lifecycle extends SystemService {
         private InputMethodManagerService mService;
 
@@ -1406,8 +1444,9 @@
         @Override
         public void onSwitchUser(@UserIdInt int userHandle) {
             // Called on ActivityManager thread.
-            // TODO: Dispatch this to a worker thread as needed.
-            mService.onSwitchUser(userHandle);
+            synchronized (mService.mMethodMap) {
+                mService.scheduleSwitchUserTaskLocked(userHandle, null /* clientToBeReset */);
+            }
         }
 
         @Override
@@ -1447,10 +1486,20 @@
         }
     }
 
-    void onSwitchUser(@UserIdInt int userId) {
-        synchronized (mMethodMap) {
-            switchUserLocked(userId);
+    @GuardedBy("mMethodMap")
+    void scheduleSwitchUserTaskLocked(@UserIdInt int userId,
+            @Nullable IInputMethodClient clientToBeReset) {
+        if (mUserSwitchHandlerTask != null) {
+            if (mUserSwitchHandlerTask.mToUserId == userId) {
+                mUserSwitchHandlerTask.mClientToBeReset = clientToBeReset;
+                return;
+            }
+            mHandler.removeCallbacks(mUserSwitchHandlerTask);
         }
+        final UserSwitchHandlerTask task = new UserSwitchHandlerTask(this, userId,
+                clientToBeReset);
+        mUserSwitchHandlerTask = task;
+        mHandler.post(task);
     }
 
     public InputMethodManagerService(Context context) {
@@ -1538,7 +1587,8 @@
     }
 
     @GuardedBy("mMethodMap")
-    private void switchUserLocked(int newUserId) {
+    private void switchUserOnHandlerLocked(@UserIdInt int newUserId,
+            IInputMethodClient clientToBeReset) {
         if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
                 + " currentUserId=" + mSettings.getCurrentUserId());
 
@@ -1589,6 +1639,18 @@
                 + " selectedIme=" + mSettings.getSelectedInputMethod());
 
         mLastSwitchUserId = newUserId;
+
+        if (mIsInteractive && clientToBeReset != null) {
+            final ClientState cs = mClients.get(clientToBeReset.asBinder());
+            if (cs == null) {
+                // The client is already gone.
+                return;
+            }
+            try {
+                cs.client.scheduleStartInputIfNecessary(mInFullscreenMode);
+            } catch (RemoteException e) {
+            }
+        }
     }
 
     void updateCurrentProfileIds() {
@@ -1812,16 +1874,14 @@
 
     @GuardedBy("mMethodMap")
     private void onCreateInlineSuggestionsRequestLocked(@UserIdInt int userId,
-            ComponentName componentName, AutofillId autofillId,
-            IInlineSuggestionsRequestCallback callback) {
+            InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback callback) {
         final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
         try {
             if (userId == mSettings.getCurrentUserId() && imi != null
                     && imi.isInlineSuggestionsEnabled() && mCurMethod != null) {
                 executeOrSendMessage(mCurMethod,
-                        mCaller.obtainMessageOOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
-                                componentName, autofillId,
-                                new InlineSuggestionsRequestCallbackDecorator(callback,
+                        mCaller.obtainMessageOOO(MSG_INLINE_SUGGESTIONS_REQUEST, mCurMethod,
+                                requestInfo, new InlineSuggestionsRequestCallbackDecorator(callback,
                                         imi.getPackageName())));
             } else {
                 callback.onInlineSuggestionsUnsupported();
@@ -3074,6 +3134,22 @@
             return InputBindResult.NOT_IME_TARGET_WINDOW;
         }
 
+        if (mUserSwitchHandlerTask != null) {
+            // There is already an on-going pending user switch task.
+            final int nextUserId = mUserSwitchHandlerTask.mToUserId;
+            if (userId == nextUserId) {
+                scheduleSwitchUserTaskLocked(userId, cs.client);
+                return InputBindResult.USER_SWITCHING;
+            }
+            for (int profileId : mUserManager.getProfileIdsWithDisabled(nextUserId)) {
+                if (profileId == userId) {
+                    scheduleSwitchUserTaskLocked(userId, cs.client);
+                    return InputBindResult.USER_SWITCHING;
+                }
+            }
+            return InputBindResult.INVALID_USER;
+        }
+
         // cross-profile access is always allowed here to allow profile-switching.
         if (!mSettings.isCurrentProfile(userId)) {
             Slog.w(TAG, "A background user is requesting window. Hiding IME.");
@@ -3085,8 +3161,10 @@
         }
 
         if (userId != mSettings.getCurrentUserId()) {
-            switchUserLocked(userId);
+            scheduleSwitchUserTaskLocked(userId, cs.client);
+            return InputBindResult.USER_SWITCHING;
         }
+
         // Master feature flag that overrides other conditions and forces IME preRendering.
         if (DEBUG) {
             Slog.v(TAG, "IME PreRendering MASTER flag: "
@@ -3972,13 +4050,13 @@
             // ---------------------------------------------------------------
             case MSG_INLINE_SUGGESTIONS_REQUEST:
                 args = (SomeArgs) msg.obj;
-                final ComponentName componentName = (ComponentName) args.arg2;
-                final AutofillId autofillId = (AutofillId) args.arg3;
+                final InlineSuggestionsRequestInfo requestInfo =
+                        (InlineSuggestionsRequestInfo) args.arg2;
                 final IInlineSuggestionsRequestCallback callback =
-                        (IInlineSuggestionsRequestCallback) args.arg4;
+                        (IInlineSuggestionsRequestCallback) args.arg3;
                 try {
-                    ((IInputMethod) args.arg1).onCreateInlineSuggestionsRequest(componentName,
-                            autofillId, callback);
+                    ((IInputMethod) args.arg1).onCreateInlineSuggestionsRequest(requestInfo,
+                            callback);
                 } catch (RemoteException e) {
                     Slog.w(TAG, "RemoteException calling onCreateInlineSuggestionsRequest(): " + e);
                 }
@@ -4549,10 +4627,10 @@
     }
 
     private void onCreateInlineSuggestionsRequest(@UserIdInt int userId,
-            ComponentName componentName, AutofillId autofillId,
+            InlineSuggestionsRequestInfo requestInfo,
             IInlineSuggestionsRequestCallback callback) {
         synchronized (mMethodMap) {
-            onCreateInlineSuggestionsRequestLocked(userId, componentName, autofillId, callback);
+            onCreateInlineSuggestionsRequestLocked(userId, requestInfo, callback);
         }
     }
 
@@ -4620,9 +4698,9 @@
         }
 
         @Override
-        public void onCreateInlineSuggestionsRequest(int userId, ComponentName componentName,
-                AutofillId autofillId, IInlineSuggestionsRequestCallback cb) {
-            mService.onCreateInlineSuggestionsRequest(userId, componentName, autofillId, cb);
+        public void onCreateInlineSuggestionsRequest(int userId,
+                InlineSuggestionsRequestInfo requestInfo, IInlineSuggestionsRequestCallback cb) {
+            mService.onCreateInlineSuggestionsRequest(userId, requestInfo, cb);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 54af694..4904061 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -63,7 +63,6 @@
 import android.util.SparseArray;
 import android.view.InputChannel;
 import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
-import android.view.autofill.AutofillId;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputConnectionInspector.MissingMethodFlags;
 import android.view.inputmethod.InputMethodInfo;
@@ -88,6 +87,7 @@
 import com.android.internal.view.IInputMethodClient;
 import com.android.internal.view.IInputMethodManager;
 import com.android.internal.view.IInputMethodSession;
+import com.android.internal.view.InlineSuggestionsRequestInfo;
 import com.android.internal.view.InputBindResult;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -192,7 +192,7 @@
 
                         @Override
                         public void onCreateInlineSuggestionsRequest(int userId,
-                                ComponentName componentName, AutofillId autofillId,
+                                InlineSuggestionsRequestInfo requestInfo,
                                 IInlineSuggestionsRequestCallback cb) {
                             try {
                                 //TODO(b/137800469): support multi client IMEs.
diff --git a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
index b9a30bb..63054cf 100644
--- a/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
+++ b/services/core/java/com/android/server/integrity/AppIntegrityManagerServiceImpl.java
@@ -45,9 +45,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.Signature;
 import android.content.pm.SigningInfo;
-import android.content.pm.parsing.ApkParseUtils;
-import android.content.pm.parsing.PackageInfoUtils;
-import android.content.pm.parsing.ParsedPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -64,6 +62,9 @@
 import com.android.server.integrity.engine.RuleEvaluationEngine;
 import com.android.server.integrity.model.IntegrityCheckResult;
 import com.android.server.integrity.model.RuleMetadata;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
@@ -508,13 +509,13 @@
             throw new IllegalArgumentException("Installation path is null, package not found");
         }
 
-        PackageParser parser = new PackageParser();
+        PackageParser2 parser = new PackageParser2(null, false, null, null, null);
         try {
-            ParsedPackage pkg = parser.parseParsedPackage(installationPath, 0, false);
+            ParsedPackage pkg = parser.parsePackage(installationPath, 0, false);
             int flags = PackageManager.GET_SIGNING_CERTIFICATES | PackageManager.GET_META_DATA;
-            ApkParseUtils.collectCertificates(pkg, false);
+            pkg.setSigningDetails(ParsingPackageUtils.collectCertificates(pkg, false));
             return PackageInfoUtils.generate(pkg, null, flags, 0, 0, null, new PackageUserState(),
-                    UserHandle.getCallingUserId());
+                    UserHandle.getCallingUserId(), null);
         } catch (Exception e) {
             throw new IllegalArgumentException("Exception reading " + dataUri, e);
         }
diff --git a/services/core/java/com/android/server/integrity/engine/RuleLoader.java b/services/core/java/com/android/server/integrity/engine/RuleLoader.java
deleted file mode 100644
index 4ba2bfb..0000000
--- a/services/core/java/com/android/server/integrity/engine/RuleLoader.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.integrity.engine;
-
-import android.content.integrity.Rule;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A helper class for loading rules to the rule evaluation engine.
- *
- * <p>Expose fine-grained APIs for loading rules to be passed to the rule evaluation engine.
- *
- * <p>It supports:
- * <ul>
- *     <li>Loading rules based on some keys, such as PACKAGE_NAME and APP_CERT.</li>
- * </ul>
- *
- * <p>It does NOT support:
- * <ul>
- *     <li>Loading the list of all rules.</li>
- *     <li>Merging rules resulting from different APIs.</li>
- * </ul>
- */
-final class RuleLoader {
-
-    List<Rule> loadRulesByPackageName(String packageName) {
-        // TODO: Add logic based on rule storage.
-        return new ArrayList<>();
-    }
-
-    List<Rule> loadRulesByAppCertificate(String appCertificate) {
-        // TODO: Add logic based on rule storage.
-        return new ArrayList<>();
-    }
-
-    List<Rule> loadRulesByInstallerName(String installerName) {
-        // TODO: Add logic based on rule storage.
-        return new ArrayList<>();
-    }
-
-    List<Rule> loadRulesByInstallerCertificate(String installerCertificate) {
-        // TODO: Add logic based on rule storage.
-        return new ArrayList<>();
-    }
-}
diff --git a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
index 11e8d91..a290eb3 100644
--- a/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
+++ b/services/core/java/com/android/server/integrity/parser/RuleBinaryParser.java
@@ -68,8 +68,7 @@
     }
 
     private List<Rule> parseRules(
-            RandomAccessInputStream randomAccessInputStream,
-            List<RuleIndexRange> indexRanges)
+            RandomAccessInputStream randomAccessInputStream, List<RuleIndexRange> indexRanges)
             throws IOException {
 
         // Read the rule binary file format version.
@@ -96,8 +95,7 @@
     }
 
     private List<Rule> parseIndexedRules(
-            RandomAccessInputStream randomAccessInputStream,
-            List<RuleIndexRange> indexRanges)
+            RandomAccessInputStream randomAccessInputStream, List<RuleIndexRange> indexRanges)
             throws IOException {
         List<Rule> parsedRules = new ArrayList<>();
 
@@ -172,6 +170,7 @@
             case AtomicFormula.APP_CERTIFICATE:
             case AtomicFormula.INSTALLER_NAME:
             case AtomicFormula.INSTALLER_CERTIFICATE:
+            case AtomicFormula.STAMP_CERTIFICATE_HASH:
                 boolean isHashedValue = bitInputStream.getNext(IS_HASHED_BITS) == 1;
                 int valueSize = bitInputStream.getNext(VALUE_SIZE_BITS);
                 String stringValue = getStringValue(bitInputStream, valueSize, isHashedValue);
@@ -183,6 +182,7 @@
                 long longValue = (upper << 32) | lower;
                 return new AtomicFormula.LongAtomicFormula(key, operator, longValue);
             case AtomicFormula.PRE_INSTALLED:
+            case AtomicFormula.STAMP_TRUSTED:
                 boolean booleanValue = getBooleanValue(bitInputStream);
                 return new AtomicFormula.BooleanAtomicFormula(key, booleanValue);
             default:
diff --git a/services/core/java/com/android/server/location/AbstractLocationProvider.java b/services/core/java/com/android/server/location/AbstractLocationProvider.java
index 433ec43..e9d94a5 100644
--- a/services/core/java/com/android/server/location/AbstractLocationProvider.java
+++ b/services/core/java/com/android/server/location/AbstractLocationProvider.java
@@ -366,21 +366,6 @@
     protected abstract void onExtraCommand(int uid, int pid, String command, Bundle extras);
 
     /**
-     * Requests a provider to enable itself for the given user id.
-     */
-    public final void requestSetAllowed(boolean allowed) {
-        // all calls into the provider must be moved onto the provider thread to prevent deadlock
-        mExecutor.execute(
-                obtainRunnable(AbstractLocationProvider::onRequestSetAllowed, this, allowed)
-                        .recycleOnUse());
-    }
-
-    /**
-     * Always invoked on the provider executor.
-     */
-    protected abstract void onRequestSetAllowed(boolean allowed);
-
-    /**
      * Dumps debug or log information. May be invoked from any thread.
      */
     public abstract void dump(FileDescriptor fd, PrintWriter pw, String[] args);
diff --git a/services/core/java/com/android/server/location/ContextHubService.java b/services/core/java/com/android/server/location/ContextHubService.java
index e79eddf..48b2270 100644
--- a/services/core/java/com/android/server/location/ContextHubService.java
+++ b/services/core/java/com/android/server/location/ContextHubService.java
@@ -18,14 +18,16 @@
 
 import android.app.PendingIntent;
 import android.content.Context;
+import android.database.ContentObserver;
 import android.hardware.contexthub.V1_0.AsyncEventType;
 import android.hardware.contexthub.V1_0.ContextHub;
 import android.hardware.contexthub.V1_0.ContextHubMsg;
 import android.hardware.contexthub.V1_0.HubAppInfo;
-import android.hardware.contexthub.V1_0.IContexthub;
 import android.hardware.contexthub.V1_0.IContexthubCallback;
 import android.hardware.contexthub.V1_0.Result;
 import android.hardware.contexthub.V1_0.TransactionResult;
+import android.hardware.contexthub.V1_1.Setting;
+import android.hardware.contexthub.V1_1.SettingValue;
 import android.hardware.location.ContextHubInfo;
 import android.hardware.location.ContextHubMessage;
 import android.hardware.location.ContextHubTransaction;
@@ -40,8 +42,11 @@
 import android.hardware.location.NanoAppInstanceInfo;
 import android.hardware.location.NanoAppMessage;
 import android.hardware.location.NanoAppState;
+import android.location.LocationManager;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Log;
 import android.util.proto.ProtoOutputStream;
 
@@ -56,7 +61,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.NoSuchElementException;
 
 /**
  * @hide
@@ -92,7 +96,7 @@
             new RemoteCallbackList<>();
 
     // Proxy object to communicate with the Context Hub HAL
-    private final IContexthub mContextHubProxy;
+    private final IContextHubWrapper mContextHubWrapper;
 
     // The manager for transaction queue
     private final ContextHubTransactionManager mTransactionManager;
@@ -145,8 +149,8 @@
     public ContextHubService(Context context) {
         mContext = context;
 
-        mContextHubProxy = getContextHubProxy();
-        if (mContextHubProxy == null) {
+        mContextHubWrapper = getContextHubWrapper();
+        if (mContextHubWrapper == null) {
             mTransactionManager = null;
             mClientManager = null;
             mDefaultClientMap = Collections.emptyMap();
@@ -155,13 +159,13 @@
             return;
         }
 
-        mClientManager = new ContextHubClientManager(mContext, mContextHubProxy);
+        mClientManager = new ContextHubClientManager(mContext, mContextHubWrapper.getHub());
         mTransactionManager = new ContextHubTransactionManager(
-                mContextHubProxy, mClientManager, mNanoAppStateManager);
+                mContextHubWrapper.getHub(), mClientManager, mNanoAppStateManager);
 
         List<ContextHub> hubList;
         try {
-            hubList = mContextHubProxy.getHubs();
+            hubList = mContextHubWrapper.getHub().getHubs();
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException while getting Context Hub info", e);
             hubList = Collections.emptyList();
@@ -178,7 +182,7 @@
             defaultClientMap.put(contextHubId, client);
 
             try {
-                mContextHubProxy.registerCallback(
+                mContextHubWrapper.getHub().registerCallback(
                         contextHubId, new ContextHubServiceCallback(contextHubId));
             } catch (RemoteException e) {
                 Log.e(TAG, "RemoteException while registering service callback for hub (ID = "
@@ -190,6 +194,19 @@
             queryNanoAppsInternal(contextHubId);
         }
         mDefaultClientMap = Collections.unmodifiableMap(defaultClientMap);
+
+        if (mContextHubWrapper.supportsSettingNotifications()) {
+            sendLocationSettingUpdate();
+            mContext.getContentResolver().registerContentObserver(
+                    Settings.Secure.getUriFor(Settings.Secure.LOCATION_MODE),
+                    true /* notifyForDescendants */,
+                    new ContentObserver(null /* handler */) {
+                        @Override
+                        public void onChange(boolean selfChange) {
+                            sendLocationSettingUpdate();
+                        }
+                    }, UserHandle.USER_ALL);
+        }
     }
 
     /**
@@ -239,19 +256,15 @@
     }
 
     /**
-     * @return the IContexthub proxy interface
+     * @return the IContextHubWrapper interface
      */
-    private IContexthub getContextHubProxy() {
-        IContexthub proxy = null;
-        try {
-            proxy = IContexthub.getService(true /* retry */);
-        } catch (RemoteException e) {
-            Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e);
-        } catch (NoSuchElementException e) {
-            Log.i(TAG, "Context Hub HAL service not found");
+    private IContextHubWrapper getContextHubWrapper() {
+        IContextHubWrapper wrapper = IContextHubWrapper.maybeConnectTo1_1();
+        if (wrapper == null) {
+            wrapper = IContextHubWrapper.maybeConnectTo1_0();
         }
 
-        return proxy;
+        return wrapper;
     }
 
     @Override
@@ -355,7 +368,7 @@
     @Override
     public int loadNanoApp(int contextHubHandle, NanoApp nanoApp) throws RemoteException {
         checkPermissions();
-        if (mContextHubProxy == null) {
+        if (mContextHubWrapper == null) {
             return -1;
         }
         if (!isValidContextHubId(contextHubHandle)) {
@@ -382,7 +395,7 @@
     @Override
     public int unloadNanoApp(int nanoAppHandle) throws RemoteException {
         checkPermissions();
-        if (mContextHubProxy == null) {
+        if (mContextHubWrapper == null) {
             return -1;
         }
 
@@ -444,7 +457,7 @@
      * @throws IllegalStateException if the transaction queue is full
      */
     private int queryNanoAppsInternal(int contextHubId) {
-        if (mContextHubProxy == null) {
+        if (mContextHubWrapper == null) {
             return Result.UNKNOWN_FAILURE;
         }
 
@@ -461,7 +474,7 @@
     public int sendMessage(int contextHubHandle, int nanoAppHandle, ContextHubMessage msg)
             throws RemoteException {
         checkPermissions();
-        if (mContextHubProxy == null) {
+        if (mContextHubWrapper == null) {
             return -1;
         }
         if (msg == null) {
@@ -563,6 +576,8 @@
      */
     private void handleHubEventCallback(int contextHubId, int eventType) {
         if (eventType == AsyncEventType.RESTARTED) {
+            sendLocationSettingUpdate();
+
             mTransactionManager.onHubReset();
             queryNanoAppsInternal(contextHubId);
 
@@ -870,12 +885,12 @@
      * @param callback        the client transaction callback interface
      * @param transactionType the type of the transaction
      *
-     * @return {@code true} if mContextHubProxy and contextHubId is valid, {@code false} otherwise
+     * @return {@code true} if mContextHubWrapper and contextHubId is valid, {@code false} otherwise
      */
     private boolean checkHalProxyAndContextHubId(
             int contextHubId, IContextHubTransactionCallback callback,
             @ContextHubTransaction.Type int transactionType) {
-        if (mContextHubProxy == null) {
+        if (mContextHubWrapper == null) {
             try {
                 callback.onTransactionComplete(
                         ContextHubTransaction.RESULT_FAILED_HAL_UNAVAILABLE);
@@ -898,4 +913,15 @@
 
         return true;
     }
+
+    /**
+     * Obtains the latest location setting value and notifies the Contexthub.
+     */
+    private void sendLocationSettingUpdate() {
+        boolean enabled = mContext.getSystemService(LocationManager.class)
+                .isLocationEnabledForUser(UserHandle.CURRENT);
+
+        mContextHubWrapper.onSettingChanged(Setting.LOCATION,
+                enabled ? SettingValue.ENABLED : SettingValue.DISABLED);
+    }
 }
diff --git a/services/core/java/com/android/server/location/CountryDetectorBase.java b/services/core/java/com/android/server/location/CountryDetectorBase.java
index b158388..8326ef9 100644
--- a/services/core/java/com/android/server/location/CountryDetectorBase.java
+++ b/services/core/java/com/android/server/location/CountryDetectorBase.java
@@ -31,15 +31,13 @@
  * @hide
  */
 public abstract class CountryDetectorBase {
-    private static final String FEATURE_ID = "CountryDetector";
-
     protected final Handler mHandler;
     protected final Context mContext;
     protected CountryListener mListener;
     protected Country mDetectedCountry;
 
-    public CountryDetectorBase(Context context) {
-        mContext = context.createFeatureContext(FEATURE_ID);
+    public CountryDetectorBase(Context ctx) {
+        mContext = ctx;
         mHandler = new Handler();
     }
 
@@ -47,7 +45,7 @@
      * Start detecting the country that the user is in.
      *
      * @return the country if it is available immediately, otherwise null should
-     * be returned.
+     *         be returned.
      */
     public abstract Country detectCountry();
 
diff --git a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
index 09af655..bc50ebc 100644
--- a/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
+++ b/services/core/java/com/android/server/location/GnssAntennaInfoProvider.java
@@ -20,7 +20,6 @@
 import android.location.GnssAntennaInfo;
 import android.location.IGnssAntennaInfoListener;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -100,41 +99,10 @@
 
     @Override
     protected ListenerOperation<IGnssAntennaInfoListener> getHandlerOperation(int result) {
-        int status;
-        switch (result) {
-            case RESULT_SUCCESS:
-                status = GnssAntennaInfo.Callback.STATUS_READY;
-                break;
-            case RESULT_NOT_AVAILABLE:
-            case RESULT_NOT_SUPPORTED:
-            case RESULT_INTERNAL_ERROR:
-                status = GnssAntennaInfo.Callback.STATUS_NOT_SUPPORTED;
-                break;
-            case RESULT_GPS_LOCATION_DISABLED:
-                status = GnssAntennaInfo.Callback.STATUS_LOCATION_DISABLED;
-                break;
-            case RESULT_UNKNOWN:
-                return null;
-            default:
-                Log.v(TAG, "Unhandled addListener result: " + result);
-                return null;
-        }
-        return new StatusChangedOperation(status);
-    }
-
-    private static class StatusChangedOperation
-            implements ListenerOperation<IGnssAntennaInfoListener> {
-        private final int mStatus;
-
-        StatusChangedOperation(int status) {
-            mStatus = status;
-        }
-
-        @Override
-        public void execute(IGnssAntennaInfoListener listener,
-                CallerIdentity callerIdentity) throws RemoteException {
-            listener.onStatusChanged(mStatus);
-        }
+        return (IGnssAntennaInfoListener listener,
+                CallerIdentity callerIdentity) -> {
+                // Do nothing, as GnssAntennaInfo.Callback does not have an onStatusChanged method.
+        };
     }
 
     /** Handle Gnss Antenna Info report. */
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 36136f4..685fb9e 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1229,11 +1229,6 @@
         }
     }
 
-    @Override
-    protected void onRequestSetAllowed(boolean allowed) {
-        // do nothing - the gnss provider is always allowed
-    }
-
     private void deleteAidingData(Bundle extras) {
         int flags;
 
@@ -2244,6 +2239,7 @@
         if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
             s.append("MEASUREMENT_CORRECTIONS ");
         }
+        if (hasCapability(GPS_CAPABILITY_ANTENNA_INFO)) s.append("ANTENNA_INFO ");
         s.append(")\n");
         if (hasCapability(GPS_CAPABILITY_MEASUREMENT_CORRECTIONS)) {
             s.append("SubHal=MEASUREMENT_CORRECTIONS[");
diff --git a/services/core/java/com/android/server/location/IContextHubWrapper.java b/services/core/java/com/android/server/location/IContextHubWrapper.java
new file mode 100644
index 0000000..79fa5c7
--- /dev/null
+++ b/services/core/java/com/android/server/location/IContextHubWrapper.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.location;
+
+import android.annotation.Nullable;
+import android.hardware.contexthub.V1_1.Setting;
+import android.hardware.contexthub.V1_1.SettingValue;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.NoSuchElementException;
+
+/**
+ * @hide
+ */
+public abstract class IContextHubWrapper {
+    private static final String TAG = "IContextHubWrapper";
+
+    /**
+     * Attempts to connect to the Contexthub HAL 1.0 service, if it exists.
+     *
+     * @return A valid IContextHubWrapper if the connection was successful, null otherwise.
+     */
+    @Nullable
+    public static IContextHubWrapper maybeConnectTo1_0() {
+        android.hardware.contexthub.V1_0.IContexthub proxy = null;
+        try {
+            proxy = android.hardware.contexthub.V1_0.IContexthub.getService(true /* retry */);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e);
+        } catch (NoSuchElementException e) {
+            Log.i(TAG, "Context Hub HAL service not found");
+        }
+
+        ContextHubWrapperV1_0 wrapper = null;
+        if (proxy != null) {
+            wrapper = new ContextHubWrapperV1_0(proxy);
+        }
+
+        return wrapper;
+    }
+
+    /**
+     * Attempts to connect to the Contexthub HAL 1.1 service, if it exists.
+     *
+     * @return A valid IContextHubWrapper if the connection was successful, null otherwise.
+     */
+    @Nullable
+    public static IContextHubWrapper maybeConnectTo1_1() {
+        android.hardware.contexthub.V1_1.IContexthub proxy = null;
+        try {
+            proxy = android.hardware.contexthub.V1_1.IContexthub.getService(true /* retry */);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException while attaching to Context Hub HAL proxy", e);
+        } catch (NoSuchElementException e) {
+            Log.i(TAG, "Context Hub HAL service not found");
+        }
+
+        ContextHubWrapperV1_1 wrapper = null;
+        if (proxy != null) {
+            wrapper = new ContextHubWrapperV1_1(proxy);
+        }
+
+        return wrapper;
+    }
+
+    /**
+     * @return A valid instance of Contexthub HAL 1.0.
+     */
+    public abstract android.hardware.contexthub.V1_0.IContexthub getHub();
+
+    /**
+     * @return True if this version of the Contexthub HAL supports setting notifications.
+     */
+    public abstract boolean supportsSettingNotifications();
+
+    /**
+     * Notifies the Contexthub implementation of a user setting change.
+     *
+     * @param setting The user setting that has changed. MUST be one of the values from the
+     *     {@link Setting} enum
+     * @param newValue The value of the user setting that changed. MUST be one of the values
+     *     from the {@link SettingValue} enum.
+     */
+    public abstract void onSettingChanged(byte setting, byte newValue);
+
+    private static class ContextHubWrapperV1_0 extends IContextHubWrapper {
+        private android.hardware.contexthub.V1_0.IContexthub mHub;
+
+        ContextHubWrapperV1_0(android.hardware.contexthub.V1_0.IContexthub hub) {
+            mHub = hub;
+        }
+
+        public android.hardware.contexthub.V1_0.IContexthub getHub() {
+            return mHub;
+        }
+
+        public boolean supportsSettingNotifications() {
+            return false;
+        }
+
+        public void onSettingChanged(byte setting, byte newValue) {}
+    }
+
+    private static class ContextHubWrapperV1_1 extends IContextHubWrapper {
+        private android.hardware.contexthub.V1_1.IContexthub mHub;
+
+        ContextHubWrapperV1_1(android.hardware.contexthub.V1_1.IContexthub hub) {
+            mHub = hub;
+        }
+
+        public android.hardware.contexthub.V1_0.IContexthub getHub() {
+            return mHub;
+        }
+
+        public boolean supportsSettingNotifications() {
+            return true;
+        }
+
+        public void onSettingChanged(byte setting, byte newValue) {
+            try {
+                mHub.onSettingChanged(setting, newValue);
+            } catch  (RemoteException e) {
+                Log.e(TAG, "Failed to send setting change to Contexthub", e);
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/location/LocationFudger.java b/services/core/java/com/android/server/location/LocationFudger.java
index a069e7a..1f458ed 100644
--- a/services/core/java/com/android/server/location/LocationFudger.java
+++ b/services/core/java/com/android/server/location/LocationFudger.java
@@ -87,6 +87,13 @@
         mRandom = random;
         mAccuracyM = Math.max(accuracyM, MIN_ACCURACY_M);
 
+        resetOffsets();
+    }
+
+    /**
+     * Resets the random offsets completely.
+     */
+    public void resetOffsets() {
         mLatitudeOffsetM = nextRandomOffset();
         mLongitudeOffsetM = nextRandomOffset();
         mNextUpdateRealtimeMs = mClock.millis() + OFFSET_UPDATE_INTERVAL_MS;
diff --git a/services/core/java/com/android/server/location/LocationProviderProxy.java b/services/core/java/com/android/server/location/LocationProviderProxy.java
index 96ffaa6..87208a7 100644
--- a/services/core/java/com/android/server/location/LocationProviderProxy.java
+++ b/services/core/java/com/android/server/location/LocationProviderProxy.java
@@ -205,14 +205,6 @@
     }
 
     @Override
-    public void onRequestSetAllowed(boolean allowed) {
-        mServiceWatcher.runOnBinder(binder -> {
-            ILocationProvider service = ILocationProvider.Stub.asInterface(binder);
-            service.requestSetAllowed(allowed);
-        });
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         mServiceWatcher.dump(fd, pw, args);
     }
diff --git a/services/core/java/com/android/server/location/MockProvider.java b/services/core/java/com/android/server/location/MockProvider.java
index b45b660..5ec06ca 100644
--- a/services/core/java/com/android/server/location/MockProvider.java
+++ b/services/core/java/com/android/server/location/MockProvider.java
@@ -64,11 +64,6 @@
     protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
 
     @Override
-    protected void onRequestSetAllowed(boolean allowed) {
-        setAllowed(allowed);
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("last mock location=" + mLocation);
     }
diff --git a/services/core/java/com/android/server/location/MockableLocationProvider.java b/services/core/java/com/android/server/location/MockableLocationProvider.java
index f43669e..0f358e9 100644
--- a/services/core/java/com/android/server/location/MockableLocationProvider.java
+++ b/services/core/java/com/android/server/location/MockableLocationProvider.java
@@ -224,15 +224,6 @@
         }
     }
 
-    @Override
-    protected void onRequestSetAllowed(boolean allowed) {
-        synchronized (mOwnerLock) {
-            if (mProvider != null) {
-                mProvider.onRequestSetAllowed(allowed);
-            }
-        }
-    }
-
     /**
      * Dumps the current provider implementation.
      */
diff --git a/services/core/java/com/android/server/location/PassiveProvider.java b/services/core/java/com/android/server/location/PassiveProvider.java
index 54dffff..1ba38cc 100644
--- a/services/core/java/com/android/server/location/PassiveProvider.java
+++ b/services/core/java/com/android/server/location/PassiveProvider.java
@@ -79,10 +79,5 @@
     protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
 
     @Override
-    protected void onRequestSetAllowed(boolean allowed) {
-        // do nothing - the passive provider is always allowed
-    }
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {}
 }
diff --git a/services/core/java/com/android/server/location/gnss/GnssManagerService.java b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
index 1039cf6..b57c261 100644
--- a/services/core/java/com/android/server/location/gnss/GnssManagerService.java
+++ b/services/core/java/com/android/server/location/gnss/GnssManagerService.java
@@ -216,9 +216,6 @@
      * {@link android.location.GnssCapabilities}.
      */
     public long getGnssCapabilities(String packageName) {
-        mContext.enforceCallingPermission(Manifest.permission.LOCATION_HARDWARE, null);
-        mContext.enforceCallingPermission(Manifest.permission.ACCESS_FINE_LOCATION, null);
-
         if (!checkLocationAppOp(packageName)) {
             return GnssCapabilities.INVALID_CAPABILITIES;
         }
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 1f4048f..15dfab9 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -17,6 +17,7 @@
 package com.android.server.locksettings;
 
 import static android.Manifest.permission.ACCESS_KEYGUARD_SECURE_STORAGE;
+import static android.Manifest.permission.MANAGE_BIOMETRIC;
 import static android.Manifest.permission.READ_CONTACTS;
 import static android.content.Context.KEYGUARD_SERVICE;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -178,6 +179,7 @@
 public class LockSettingsService extends ILockSettings.Stub {
     private static final String TAG = "LockSettingsService";
     private static final String PERMISSION = ACCESS_KEYGUARD_SECURE_STORAGE;
+    private static final String BIOMETRIC_PERMISSION = MANAGE_BIOMETRIC;
     private static final boolean DEBUG = false;
 
     private static final int PROFILE_KEY_IV_SIZE = 12;
@@ -1050,6 +1052,10 @@
         }
     }
 
+    private final void checkBiometricPermission() {
+        mContext.enforceCallingOrSelfPermission(BIOMETRIC_PERMISSION, "LockSettingsBiometric");
+    }
+
     @Override
     public boolean hasSecureLockScreen() {
         return mHasSecureLockScreen;
@@ -2304,6 +2310,18 @@
     }
 
     @Override
+    public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
+        checkBiometricPermission();
+        mStrongAuth.reportSuccessfulBiometricUnlock(isStrongBiometric, userId);
+    }
+
+    @Override
+    public void scheduleNonStrongBiometricIdleTimeout(int userId) {
+        checkBiometricPermission();
+        mStrongAuth.scheduleNonStrongBiometricIdleTimeout(userId);
+    }
+
+    @Override
     public void userPresent(int userId) {
         checkWritePermission(userId);
         mStrongAuth.reportUnlock(userId);
@@ -3191,6 +3209,12 @@
         mStorage.dump(pw);
         pw.println();
         pw.decreaseIndent();
+
+        pw.println("StrongAuth:");
+        pw.increaseIndent();
+        mStrongAuth.dump(pw);
+        pw.println();
+        pw.decreaseIndent();
     }
 
     /**
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
index 91cf53e..fbee6f4 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsStrongAuth.java
@@ -17,6 +17,7 @@
 package com.android.server.locksettings;
 
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_NOT_REQUIRED;
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT;
 import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_TIMEOUT;
 
 import android.app.AlarmManager;
@@ -32,8 +33,10 @@
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.Slog;
+import android.util.SparseBooleanArray;
 import android.util.SparseIntArray;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker;
 
 /**
@@ -42,6 +45,7 @@
 public class LockSettingsStrongAuth {
 
     private static final String TAG = "LockSettings";
+    private static final boolean DEBUG = false;
 
     private static final int MSG_REQUIRE_STRONG_AUTH = 1;
     private static final int MSG_REGISTER_TRACKER = 2;
@@ -49,15 +53,40 @@
     private static final int MSG_REMOVE_USER = 4;
     private static final int MSG_SCHEDULE_STRONG_AUTH_TIMEOUT = 5;
     private static final int MSG_NO_LONGER_REQUIRE_STRONG_AUTH = 6;
+    private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT = 7;
+    private static final int MSG_STRONG_BIOMETRIC_UNLOCK = 8;
+    private static final int MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT = 9;
 
     private static final String STRONG_AUTH_TIMEOUT_ALARM_TAG =
             "LockSettingsStrongAuth.timeoutForUser";
+    private static final String NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG =
+            "LockSettingsPrimaryAuth.nonStrongBiometricTimeoutForUser";
+    private static final String NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG =
+            "LockSettingsPrimaryAuth.nonStrongBiometricIdleTimeoutForUser";
+
+    /**
+     * Default and maximum timeout in milliseconds after which unlocking with weak auth times out,
+     * i.e. the user has to use a strong authentication method like password, PIN or pattern.
+     */
+    public static final long DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS = 24 * 60 * 60 * 1000; // 24h
+    public static final long DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS =
+            4 * 60 * 60 * 1000; // 4h
 
     private final RemoteCallbackList<IStrongAuthTracker> mTrackers = new RemoteCallbackList<>();
     private final SparseIntArray mStrongAuthForUser = new SparseIntArray();
+    private final SparseBooleanArray mIsNonStrongBiometricAllowedForUser = new SparseBooleanArray();
     private final ArrayMap<Integer, StrongAuthTimeoutAlarmListener>
             mStrongAuthTimeoutAlarmListenerForUser = new ArrayMap<>();
+    // Track non-strong biometric timeout
+    private final ArrayMap<Integer, NonStrongBiometricTimeoutAlarmListener>
+            mNonStrongBiometricTimeoutAlarmListener = new ArrayMap<>();
+    // Track non-strong biometric idle timeout
+    private final ArrayMap<Integer, NonStrongBiometricIdleTimeoutAlarmListener>
+            mNonStrongBiometricIdleTimeoutAlarmListener = new ArrayMap<>();
+
     private final int mDefaultStrongAuthFlags;
+    private final boolean mDefaultIsNonStrongBiometricAllowed = true;
+
     private final Context mContext;
 
     private AlarmManager mAlarmManager;
@@ -80,6 +109,17 @@
                 Slog.e(TAG, "Exception while adding StrongAuthTracker.", e);
             }
         }
+
+        for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
+            int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
+            boolean value = mIsNonStrongBiometricAllowedForUser.valueAt(i);
+            try {
+                tracker.onIsNonStrongBiometricAllowedChanged(value, key);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Exception while adding StrongAuthTracker: "
+                        + "IsNonStrongBiometricAllowedChanged.", e);
+            }
+        }
     }
 
     private void handleRemoveStrongAuthTracker(IStrongAuthTracker tracker) {
@@ -134,6 +174,13 @@
             mStrongAuthForUser.removeAt(index);
             notifyStrongAuthTrackers(mDefaultStrongAuthFlags, userId);
         }
+
+        index = mIsNonStrongBiometricAllowedForUser.indexOfKey(userId);
+        if (index >= 0) {
+            mIsNonStrongBiometricAllowedForUser.removeAt(index);
+            notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(
+                    mDefaultIsNonStrongBiometricAllowed, userId);
+        }
     }
 
     private void handleScheduleStrongAuthTimeout(int userId) {
@@ -151,6 +198,125 @@
         // schedule a new alarm listener for the user
         mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when, STRONG_AUTH_TIMEOUT_ALARM_TAG,
                 alarm, mHandler);
+
+        // cancel current non-strong biometric alarm listener for the user (if there was one)
+        cancelNonStrongBiometricAlarmListener(userId);
+        // cancel current non-strong biometric idle alarm listener for the user (if there was one)
+        cancelNonStrongBiometricIdleAlarmListener(userId);
+        // re-allow unlock with non-strong biometrics
+        setIsNonStrongBiometricAllowed(true, userId);
+    }
+
+    private void handleScheduleNonStrongBiometricTimeout(int userId) {
+        if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricTimeout for userId=" + userId);
+        long when = SystemClock.elapsedRealtime() + DEFAULT_NON_STRONG_BIOMETRIC_TIMEOUT_MS;
+        NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
+                .get(userId);
+        if (alarm != null) {
+            // Unlock with non-strong biometric will not affect the existing non-strong biometric
+            // timeout alarm
+            if (DEBUG) {
+                Slog.d(TAG, "There is an existing alarm for non-strong biometric"
+                        + " fallback timeout, so do not re-schedule");
+            }
+        } else {
+            if (DEBUG) {
+                Slog.d(TAG, "Schedule a new alarm for non-strong biometric fallback timeout");
+            }
+            alarm = new NonStrongBiometricTimeoutAlarmListener(userId);
+            mNonStrongBiometricTimeoutAlarmListener.put(userId, alarm);
+            // schedule a new alarm listener for the user
+            mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when,
+                    NON_STRONG_BIOMETRIC_TIMEOUT_ALARM_TAG, alarm, mHandler);
+        }
+
+        // cancel current non-strong biometric idle alarm listener for the user (if there was one)
+        cancelNonStrongBiometricIdleAlarmListener(userId);
+    }
+
+    private void handleStrongBiometricUnlock(int userId) {
+        if (DEBUG) Slog.d(TAG, "handleStrongBiometricUnlock for userId=" + userId);
+        // cancel current non-strong biometric alarm listener for the user (if there was one)
+        cancelNonStrongBiometricAlarmListener(userId);
+        // cancel current non-strong biometric idle alarm listener for the user (if there was one)
+        cancelNonStrongBiometricIdleAlarmListener(userId);
+        // re-allow unlock with non-strong biometrics
+        setIsNonStrongBiometricAllowed(true, userId);
+    }
+
+    private void cancelNonStrongBiometricAlarmListener(int userId) {
+        if (DEBUG) Slog.d(TAG, "cancelNonStrongBiometricAlarmListener for userId=" + userId);
+        NonStrongBiometricTimeoutAlarmListener alarm = mNonStrongBiometricTimeoutAlarmListener
+                .get(userId);
+        if (alarm != null) {
+            if (DEBUG) Slog.d(TAG, "Cancel alarm for non-strong biometric fallback timeout");
+            mAlarmManager.cancel(alarm);
+            // need to remove the alarm when cancelled by primary auth or strong biometric
+            mNonStrongBiometricTimeoutAlarmListener.remove(userId);
+        }
+    }
+
+    private void cancelNonStrongBiometricIdleAlarmListener(int userId) {
+        if (DEBUG) Slog.d(TAG, "cancelNonStrongBiometricIdleAlarmListener for userId=" + userId);
+        // cancel idle alarm listener by any unlocks (i.e. primary auth, strong biometric,
+        // non-strong biometric)
+        NonStrongBiometricIdleTimeoutAlarmListener alarm =
+                mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
+        if (alarm != null) {
+            if (DEBUG) Slog.d(TAG, "Cancel alarm for non-strong biometric idle timeout");
+            mAlarmManager.cancel(alarm);
+        }
+    }
+
+    private void setIsNonStrongBiometricAllowed(boolean allowed, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "setIsNonStrongBiometricAllowed for allowed=" + allowed
+                    + ", userId=" + userId);
+        }
+        if (userId == UserHandle.USER_ALL) {
+            for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
+                int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
+                setIsNonStrongBiometricAllowedOneUser(allowed, key);
+            }
+        } else {
+            setIsNonStrongBiometricAllowedOneUser(allowed, userId);
+        }
+    }
+
+    private void setIsNonStrongBiometricAllowedOneUser(boolean allowed, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "setIsNonStrongBiometricAllowedOneUser for allowed=" + allowed
+                    + ", userId=" + userId);
+        }
+        boolean oldValue = mIsNonStrongBiometricAllowedForUser.get(userId,
+                mDefaultIsNonStrongBiometricAllowed);
+        if (allowed != oldValue) {
+            if (DEBUG) {
+                Slog.d(TAG, "mIsNonStrongBiometricAllowedForUser value changed:"
+                        + " oldValue=" + oldValue + ", allowed=" + allowed);
+            }
+            mIsNonStrongBiometricAllowedForUser.put(userId, allowed);
+            notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(allowed, userId);
+        }
+    }
+
+    private void handleScheduleNonStrongBiometricIdleTimeout(int userId) {
+        if (DEBUG) Slog.d(TAG, "handleScheduleNonStrongBiometricIdleTimeout for userId=" + userId);
+        long when = SystemClock.elapsedRealtime() + DEFAULT_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_MS;
+        // cancel current alarm listener for the user (if there was one)
+        NonStrongBiometricIdleTimeoutAlarmListener alarm =
+                mNonStrongBiometricIdleTimeoutAlarmListener.get(userId);
+        if (alarm != null) {
+            if (DEBUG) Slog.d(TAG, "Cancel existing alarm for non-strong biometric idle timeout");
+            mAlarmManager.cancel(alarm);
+        } else {
+            alarm = new NonStrongBiometricIdleTimeoutAlarmListener(userId);
+            mNonStrongBiometricIdleTimeoutAlarmListener.put(userId, alarm);
+        }
+        // schedule a new alarm listener for the user
+        if (DEBUG) Slog.d(TAG, "Schedule a new alarm for non-strong biometric idle timeout");
+        mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, when,
+                NON_STRONG_BIOMETRIC_IDLE_TIMEOUT_ALARM_TAG, alarm, mHandler);
     }
 
     private void notifyStrongAuthTrackers(int strongAuthReason, int userId) {
@@ -170,6 +336,29 @@
         }
     }
 
+    private void notifyStrongAuthTrackersForIsNonStrongBiometricAllowed(boolean allowed,
+            int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "notifyStrongAuthTrackersForIsNonStrongBiometricAllowed"
+                    + " for allowed=" + allowed + ", userId=" + userId);
+        }
+        int i = mTrackers.beginBroadcast();
+        try {
+            while (i > 0) {
+                i--;
+                try {
+                    mTrackers.getBroadcastItem(i).onIsNonStrongBiometricAllowedChanged(
+                            allowed, userId);
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Exception while notifying StrongAuthTracker: "
+                            + "IsNonStrongBiometricAllowedChanged.", e);
+                }
+            }
+        } finally {
+            mTrackers.finishBroadcast();
+        }
+    }
+
     public void registerStrongAuthTracker(IStrongAuthTracker tracker) {
         mHandler.obtainMessage(MSG_REGISTER_TRACKER, tracker).sendToTarget();
     }
@@ -207,11 +396,45 @@
         requireStrongAuth(STRONG_AUTH_NOT_REQUIRED, userId);
     }
 
+    /**
+     * Report successful unlocking with primary auth
+     */
     public void reportSuccessfulStrongAuthUnlock(int userId) {
         final int argNotUsed = 0;
         mHandler.obtainMessage(MSG_SCHEDULE_STRONG_AUTH_TIMEOUT, userId, argNotUsed).sendToTarget();
     }
 
+    /**
+     * Report successful unlocking with biometric
+     */
+    public void reportSuccessfulBiometricUnlock(boolean isStrongBiometric, int userId) {
+        if (DEBUG) {
+            Slog.d(TAG, "reportSuccessfulBiometricUnlock for isStrongBiometric="
+                    + isStrongBiometric + ", userId=" + userId);
+        }
+        final int argNotUsed = 0;
+        if (isStrongBiometric) { // unlock with strong biometric
+            mHandler.obtainMessage(MSG_STRONG_BIOMETRIC_UNLOCK, userId, argNotUsed)
+                    .sendToTarget();
+        } else { // unlock with non-strong biometric (i.e. weak or convenience)
+            mHandler.obtainMessage(MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT, userId, argNotUsed)
+                    .sendToTarget();
+        }
+    }
+
+    /**
+     * Schedule idle timeout for non-strong biometric (i.e. weak or convenience)
+     */
+    public void scheduleNonStrongBiometricIdleTimeout(int userId) {
+        if (DEBUG) Slog.d(TAG, "scheduleNonStrongBiometricIdleTimeout for userId=" + userId);
+        final int argNotUsed = 0;
+        mHandler.obtainMessage(MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT, userId, argNotUsed)
+                .sendToTarget();
+    }
+
+    /**
+     * Alarm of fallback timeout for primary auth
+     */
     private class StrongAuthTimeoutAlarmListener implements OnAlarmListener {
 
         private final int mUserId;
@@ -226,6 +449,41 @@
         }
     }
 
+    /**
+     * Alarm of fallback timeout for non-strong biometric (i.e. weak or convenience)
+     */
+    private class NonStrongBiometricTimeoutAlarmListener implements OnAlarmListener {
+
+        private final int mUserId;
+
+        NonStrongBiometricTimeoutAlarmListener(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onAlarm() {
+            requireStrongAuth(STRONG_AUTH_REQUIRED_AFTER_NON_STRONG_BIOMETRICS_TIMEOUT, mUserId);
+        }
+    }
+
+    /**
+     * Alarm of idle timeout for non-strong biometric (i.e. weak or convenience biometric)
+     */
+    private class NonStrongBiometricIdleTimeoutAlarmListener implements OnAlarmListener {
+
+        private final int mUserId;
+
+        NonStrongBiometricIdleTimeoutAlarmListener(int userId) {
+            mUserId = userId;
+        }
+
+        @Override
+        public void onAlarm() {
+            // disallow unlock with non-strong biometrics
+            setIsNonStrongBiometricAllowed(false, mUserId);
+        }
+    }
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
@@ -248,8 +506,38 @@
                 case MSG_NO_LONGER_REQUIRE_STRONG_AUTH:
                     handleNoLongerRequireStrongAuth(msg.arg1, msg.arg2);
                     break;
+                case MSG_SCHEDULE_NON_STRONG_BIOMETRIC_TIMEOUT:
+                    handleScheduleNonStrongBiometricTimeout(msg.arg1);
+                    break;
+                case MSG_STRONG_BIOMETRIC_UNLOCK:
+                    handleStrongBiometricUnlock(msg.arg1);
+                    break;
+                case MSG_SCHEDULE_NON_STRONG_BIOMETRIC_IDLE_TIMEOUT:
+                    handleScheduleNonStrongBiometricIdleTimeout(msg.arg1);
+                    break;
             }
         }
     };
 
+    public void dump(IndentingPrintWriter pw) {
+        pw.println("PrimaryAuthFlags state:");
+        pw.increaseIndent();
+        for (int i = 0; i < mStrongAuthForUser.size(); i++) {
+            final int key = mStrongAuthForUser.keyAt(i);
+            final int value = mStrongAuthForUser.valueAt(i);
+            pw.println("userId=" + key + ", primaryAuthFlags=" + Integer.toHexString(value));
+        }
+        pw.println();
+        pw.decreaseIndent();
+
+        pw.println("NonStrongBiometricAllowed state:");
+        pw.increaseIndent();
+        for (int i = 0; i < mIsNonStrongBiometricAllowedForUser.size(); i++) {
+            final int key = mIsNonStrongBiometricAllowedForUser.keyAt(i);
+            final boolean value = mIsNonStrongBiometricAllowedForUser.valueAt(i);
+            pw.println("userId=" + key + ", allowed=" + value);
+        }
+        pw.println();
+        pw.decreaseIndent();
+    }
 }
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index 9b1824f..f144405 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -53,15 +53,15 @@
 
     public abstract void requestCreateSession(String packageName, String routeId, long requestId,
             @Nullable Bundle sessionHints);
-    public abstract void releaseSession(String sessionId);
+    public abstract void releaseSession(String sessionId, long requestId);
     public abstract void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference);
 
-    public abstract void selectRoute(String sessionId, String routeId);
-    public abstract void deselectRoute(String sessionId, String routeId);
-    public abstract void transferToRoute(String sessionId, String routeId);
+    public abstract void selectRoute(String sessionId, String routeId, long requestId);
+    public abstract void deselectRoute(String sessionId, String routeId, long requestId);
+    public abstract void transferToRoute(String sessionId, String routeId, long requestId);
 
-    public abstract void setRouteVolume(String routeId, int volume);
-    public abstract void setSessionVolume(String sessionId, int volume);
+    public abstract void setRouteVolume(String routeId, int volume, long requestId);
+    public abstract void setSessionVolume(String sessionId, int volume, long requestId);
 
     @NonNull
     public String getUniqueId() {
@@ -116,5 +116,6 @@
                 @NonNull RoutingSessionInfo sessionInfo);
         void onSessionReleased(@NonNull MediaRoute2Provider provider,
                 @NonNull RoutingSessionInfo sessionInfo);
+        void onRequestFailed(@NonNull MediaRoute2Provider provider, long requestId, int reason);
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index 60934e0..e64776c 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -87,9 +87,9 @@
     }
 
     @Override
-    public void releaseSession(String sessionId) {
+    public void releaseSession(String sessionId, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.releaseSession(sessionId);
+            mActiveConnection.releaseSession(sessionId, requestId);
             updateBinding();
         }
     }
@@ -103,38 +103,38 @@
     }
 
     @Override
-    public void selectRoute(String sessionId, String routeId) {
+    public void selectRoute(String sessionId, String routeId, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.selectRoute(sessionId, routeId);
+            mActiveConnection.selectRoute(sessionId, routeId, requestId);
         }
     }
 
     @Override
-    public void deselectRoute(String sessionId, String routeId) {
+    public void deselectRoute(String sessionId, String routeId, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.deselectRoute(sessionId, routeId);
+            mActiveConnection.deselectRoute(sessionId, routeId, requestId);
         }
     }
 
     @Override
-    public void transferToRoute(String sessionId, String routeId) {
+    public void transferToRoute(String sessionId, String routeId, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.transferToRoute(sessionId, routeId);
+            mActiveConnection.transferToRoute(sessionId, routeId, requestId);
         }
     }
 
     @Override
-    public void setRouteVolume(String routeId, int volume) {
+    public void setRouteVolume(String routeId, int volume, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.setRouteVolume(routeId, volume);
+            mActiveConnection.setRouteVolume(routeId, volume, requestId);
             updateBinding();
         }
     }
 
     @Override
-    public void setSessionVolume(String sessionId, int volume) {
+    public void setSessionVolume(String sessionId, int volume, long requestId) {
         if (mConnectionReady) {
-            mActiveConnection.setSessionVolume(sessionId, volume);
+            mActiveConnection.setSessionVolume(sessionId, volume, requestId);
             updateBinding();
         }
     }
@@ -333,8 +333,8 @@
             return;
         }
 
-        if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
-            Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_UNKNOWN");
+        if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
+            Slog.w(TAG, "onSessionCreationFailed: Ignoring requestId REQUEST_ID_NONE");
             return;
         }
 
@@ -406,6 +406,19 @@
         mCallback.onSessionReleased(this, sessionInfo);
     }
 
+    private void onRequestFailed(Connection connection, long requestId, int reason) {
+        if (mActiveConnection != connection) {
+            return;
+        }
+
+        if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
+            Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
+            return;
+        }
+
+        mCallback.onRequestFailed(this, requestId, reason);
+    }
+
     private void disconnect() {
         if (mActiveConnection != null) {
             mConnectionReady = false;
@@ -461,9 +474,9 @@
             }
         }
 
-        public void releaseSession(String sessionId) {
+        public void releaseSession(String sessionId, long requestId) {
             try {
-                mService.releaseSession(sessionId);
+                mService.releaseSession(sessionId, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "releaseSession: Failed to deliver request.");
             }
@@ -477,41 +490,41 @@
             }
         }
 
-        public void selectRoute(String sessionId, String routeId) {
+        public void selectRoute(String sessionId, String routeId, long requestId) {
             try {
-                mService.selectRoute(sessionId, routeId);
+                mService.selectRoute(sessionId, routeId, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "selectRoute: Failed to deliver request.", ex);
             }
         }
 
-        public void deselectRoute(String sessionId, String routeId) {
+        public void deselectRoute(String sessionId, String routeId, long requestId) {
             try {
-                mService.deselectRoute(sessionId, routeId);
+                mService.deselectRoute(sessionId, routeId, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "deselectRoute: Failed to deliver request.", ex);
             }
         }
 
-        public void transferToRoute(String sessionId, String routeId) {
+        public void transferToRoute(String sessionId, String routeId, long requestId) {
             try {
-                mService.transferToRoute(sessionId, routeId);
+                mService.transferToRoute(sessionId, routeId, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "transferToRoute: Failed to deliver request.", ex);
             }
         }
 
-        public void setRouteVolume(String routeId, int volume) {
+        public void setRouteVolume(String routeId, int volume, long requestId) {
             try {
-                mService.setRouteVolume(routeId, volume);
+                mService.setRouteVolume(routeId, volume, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "setRouteVolume: Failed to deliver request.", ex);
             }
         }
 
-        public void setSessionVolume(String sessionId, int volume) {
+        public void setSessionVolume(String sessionId, int volume, long requestId) {
             try {
-                mService.setSessionVolume(sessionId, volume);
+                mService.setSessionVolume(sessionId, volume, requestId);
             } catch (RemoteException ex) {
                 Slog.e(TAG, "setSessionVolume: Failed to deliver request.", ex);
             }
@@ -541,6 +554,10 @@
         void postSessionReleased(RoutingSessionInfo sessionInfo) {
             mHandler.post(() -> onSessionReleased(Connection.this, sessionInfo));
         }
+
+        void postSessionReleased(long requestId, int reason) {
+            mHandler.post(() -> onRequestFailed(Connection.this, requestId, reason));
+        }
     }
 
     private static final class ServiceCallbackStub extends
@@ -594,5 +611,13 @@
                 connection.postSessionReleased(sessionInfo);
             }
         }
+
+        @Override
+        public void notifyRequestFailed(long requestId, int reason) {
+            Connection connection = mConnectionRef.get();
+            if (connection != null) {
+                connection.postSessionReleased(requestId, reason);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 3588916..e78a35c 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -16,6 +16,7 @@
 
 package com.android.server.media;
 
+import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
 import static android.media.MediaRouter2Utils.getOriginalId;
 import static android.media.MediaRouter2Utils.getProviderId;
 
@@ -30,7 +31,6 @@
 import android.media.IMediaRouter2Manager;
 import android.media.MediaRoute2Info;
 import android.media.MediaRoute2ProviderInfo;
-import android.media.MediaRoute2ProviderService;
 import android.media.RouteDiscoveryPreference;
 import android.media.RoutingSessionInfo;
 import android.os.Binder;
@@ -70,6 +70,12 @@
     private static final String TAG = "MR2ServiceImpl";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
+    /**
+     * TODO: Change this with the real request ID from MediaRouter2 when
+     * MediaRouter2 needs to get notified for the failures.
+     */
+    private static final long DUMMY_REQUEST_ID = -1;
+
     private final Context mContext;
     private final Object mLock = new Object();
     final AtomicInteger mNextRouterOrManagerId = new AtomicInteger(1);
@@ -365,14 +371,14 @@
     }
 
     public void setRouteVolumeWithManager(IMediaRouter2Manager manager,
-            MediaRoute2Info route, int volume) {
+            MediaRoute2Info route, int volume, int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         Objects.requireNonNull(route, "route must not be null");
 
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                setRouteVolumeWithManagerLocked(manager, route, volume);
+                setRouteVolumeWithManagerLocked(manager, route, volume, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -397,7 +403,7 @@
     }
 
     public void selectRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId,
-            MediaRoute2Info route) {
+            MediaRoute2Info route, int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         if (TextUtils.isEmpty(uniqueSessionId)) {
             throw new IllegalArgumentException("uniqueSessionId must not be empty");
@@ -407,7 +413,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                selectRouteWithManagerLocked(manager, uniqueSessionId, route);
+                selectRouteWithManagerLocked(manager, uniqueSessionId, route, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -415,7 +421,7 @@
     }
 
     public void deselectRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId,
-            MediaRoute2Info route) {
+            MediaRoute2Info route, int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         if (TextUtils.isEmpty(uniqueSessionId)) {
             throw new IllegalArgumentException("uniqueSessionId must not be empty");
@@ -425,7 +431,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                deselectRouteWithManagerLocked(manager, uniqueSessionId, route);
+                deselectRouteWithManagerLocked(manager, uniqueSessionId, route, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -433,7 +439,7 @@
     }
 
     public void transferToRouteWithManager(IMediaRouter2Manager manager, String uniqueSessionId,
-            MediaRoute2Info route) {
+            MediaRoute2Info route, int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         if (TextUtils.isEmpty(uniqueSessionId)) {
             throw new IllegalArgumentException("uniqueSessionId must not be empty");
@@ -443,7 +449,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                transferToRouteWithManagerLocked(manager, uniqueSessionId, route);
+                transferToRouteWithManagerLocked(manager, uniqueSessionId, route, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -451,7 +457,7 @@
     }
 
     public void setSessionVolumeWithManager(IMediaRouter2Manager manager,
-            String uniqueSessionId, int volume) {
+            String uniqueSessionId, int volume, int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         if (TextUtils.isEmpty(uniqueSessionId)) {
             throw new IllegalArgumentException("uniqueSessionId must not be empty");
@@ -460,14 +466,15 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                setSessionVolumeWithManagerLocked(manager, uniqueSessionId, volume);
+                setSessionVolumeWithManagerLocked(manager, uniqueSessionId, volume, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
     }
 
-    public void releaseSessionWithManager(IMediaRouter2Manager manager, String uniqueSessionId) {
+    public void releaseSessionWithManager(IMediaRouter2Manager manager, String uniqueSessionId,
+            int requestId) {
         Objects.requireNonNull(manager, "manager must not be null");
         if (TextUtils.isEmpty(uniqueSessionId)) {
             throw new IllegalArgumentException("uniqueSessionId must not be empty");
@@ -476,7 +483,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mLock) {
-                releaseSessionWithManagerLocked(manager, uniqueSessionId);
+                releaseSessionWithManagerLocked(manager, uniqueSessionId, requestId);
             }
         } finally {
             Binder.restoreCallingIdentity(token);
@@ -572,7 +579,7 @@
                 obtainMessage(UserHandler::notifyPreferredFeaturesChangedToManagers,
                         routerRecord.mUserRecord.mHandler, routerRecord));
         routerRecord.mUserRecord.mHandler.sendMessage(
-                obtainMessage(UserHandler::updateDiscoveryPreference,
+                obtainMessage(UserHandler::updateDiscoveryPreferenceOnHandler,
                         routerRecord.mUserRecord.mHandler));
     }
 
@@ -584,7 +591,7 @@
         if (routerRecord != null) {
             routerRecord.mUserRecord.mHandler.sendMessage(
                     obtainMessage(UserHandler::setRouteVolumeOnHandler,
-                            routerRecord.mUserRecord.mHandler, route, volume));
+                            routerRecord.mUserRecord.mHandler, route, volume, DUMMY_REQUEST_ID));
         }
     }
 
@@ -615,7 +622,8 @@
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::selectRouteOnHandler,
-                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        DUMMY_REQUEST_ID));
     }
 
     private void deselectRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
@@ -629,7 +637,8 @@
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::deselectRouteOnHandler,
-                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        DUMMY_REQUEST_ID));
     }
 
     private void transferToRouteWithRouter2Locked(@NonNull IMediaRouter2 router,
@@ -643,7 +652,8 @@
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::transferToRouteOnHandler,
-                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        DUMMY_REQUEST_ID));
     }
 
     private void setSessionVolumeWithRouter2Locked(@NonNull IMediaRouter2 router,
@@ -657,7 +667,8 @@
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::setSessionVolumeOnHandler,
-                        routerRecord.mUserRecord.mHandler, uniqueSessionId, volume));
+                        routerRecord.mUserRecord.mHandler, uniqueSessionId, volume,
+                        DUMMY_REQUEST_ID));
     }
 
     private void releaseSessionWithRouter2Locked(@NonNull IMediaRouter2 router,
@@ -671,7 +682,8 @@
 
         routerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::releaseSessionOnHandler,
-                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId));
+                        routerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId,
+                        DUMMY_REQUEST_ID));
     }
 
     ////////////////////////////////////////////////////////////
@@ -744,16 +756,18 @@
     }
 
     private void setRouteVolumeWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull MediaRoute2Info route, int volume) {
+            @NonNull MediaRoute2Info route, int volume, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
         if (managerRecord == null) {
             return;
         }
+
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::setRouteVolumeOnHandler,
-                        managerRecord.mUserRecord.mHandler, route, volume));
+                        managerRecord.mUserRecord.mHandler, route, volume, uniqueRequestId));
     }
 
     private void requestCreateSessionWithManagerLocked(@NonNull IMediaRouter2Manager manager,
@@ -778,7 +792,7 @@
     }
 
     private void selectRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
@@ -790,13 +804,15 @@
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::selectRouteOnHandler,
-                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        uniqueRequestId));
     }
 
     private void deselectRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
@@ -808,13 +824,15 @@
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::deselectRouteOnHandler,
-                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        uniqueRequestId));
     }
 
     private void transferToRouteWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+            @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
@@ -826,13 +844,15 @@
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
 
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::transferToRouteOnHandler,
-                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route));
+                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId, route,
+                        uniqueRequestId));
     }
 
     private void setSessionVolumeWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull String uniqueSessionId, int volume) {
+            @NonNull String uniqueSessionId, int volume, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
@@ -840,13 +860,15 @@
             return;
         }
 
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::setSessionVolumeOnHandler,
-                        managerRecord.mUserRecord.mHandler, uniqueSessionId, volume));
+                        managerRecord.mUserRecord.mHandler, uniqueSessionId, volume,
+                        uniqueRequestId));
     }
 
     private void releaseSessionWithManagerLocked(@NonNull IMediaRouter2Manager manager,
-            @NonNull String uniqueSessionId) {
+            @NonNull String uniqueSessionId, int requestId) {
         final IBinder binder = manager.asBinder();
         ManagerRecord managerRecord = mAllManagerRecords.get(binder);
 
@@ -856,10 +878,15 @@
 
         RouterRecord routerRecord = managerRecord.mUserRecord.mHandler
                 .findRouterforSessionLocked(uniqueSessionId);
+        if (routerRecord == null) {
+            return;
+        }
 
+        long uniqueRequestId = toUniqueRequestId(managerRecord.mManagerId, requestId);
         managerRecord.mUserRecord.mHandler.sendMessage(
                 obtainMessage(UserHandler::releaseSessionOnHandler,
-                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId));
+                        managerRecord.mUserRecord.mHandler, routerRecord, uniqueSessionId,
+                        uniqueRequestId));
     }
 
     ////////////////////////////////////////////////////////////
@@ -1100,6 +1127,13 @@
                     this, provider, sessionInfo));
         }
 
+        @Override
+        public void onRequestFailed(@NonNull MediaRoute2Provider provider, long requestId,
+                int reason) {
+            sendMessage(PooledLambda.obtainMessage(UserHandler::onRequestFailedOnHandler,
+                    this, provider, requestId, reason));
+        }
+
         @Nullable
         public RouterRecord findRouterforSessionLocked(@NonNull String uniqueSessionId) {
             return mSessionToRouterMap.get(uniqueSessionId);
@@ -1195,7 +1229,7 @@
             if (provider == null) {
                 Slog.w(TAG, "Ignoring session creation request since no provider found for"
                         + " given route=" + route);
-                notifySessionCreationFailed(routerRecord, toOriginalRequestId(requestId));
+                notifySessionCreationFailedToRouter(routerRecord, toOriginalRequestId(requestId));
                 return;
             }
 
@@ -1210,7 +1244,7 @@
 
         // routerRecord can be null if the session is system's.
         private void selectRouteOnHandler(@Nullable RouterRecord routerRecord,
-                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) {
             if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route,
                     "selecting")) {
                 return;
@@ -1222,12 +1256,12 @@
             if (provider == null) {
                 return;
             }
-            provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId());
+            provider.selectRoute(getOriginalId(uniqueSessionId), route.getOriginalId(), requestId);
         }
 
         // routerRecord can be null if the session is system's.
         private void deselectRouteOnHandler(@Nullable RouterRecord routerRecord,
-                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) {
             if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route,
                     "deselecting")) {
                 return;
@@ -1239,12 +1273,13 @@
             if (provider == null) {
                 return;
             }
-            provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId());
+            provider.deselectRoute(getOriginalId(uniqueSessionId), route.getOriginalId(),
+                    requestId);
         }
 
         // routerRecord can be null if the session is system's.
         private void transferToRouteOnHandler(@Nullable RouterRecord routerRecord,
-                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route) {
+                @NonNull String uniqueSessionId, @NonNull MediaRoute2Info route, long requestId) {
             if (!checkArgumentsForSessionControl(routerRecord, uniqueSessionId, route,
                     "transferring to")) {
                 return;
@@ -1256,7 +1291,8 @@
             if (provider == null) {
                 return;
             }
-            provider.transferToRoute(getOriginalId(uniqueSessionId), route.getOriginalId());
+            provider.transferToRoute(getOriginalId(uniqueSessionId), route.getOriginalId(),
+                    requestId);
         }
 
         private boolean checkArgumentsForSessionControl(@Nullable RouterRecord routerRecord,
@@ -1299,7 +1335,7 @@
         }
 
         private void releaseSessionOnHandler(@NonNull RouterRecord routerRecord,
-                @NonNull String uniqueSessionId) {
+                @NonNull String uniqueSessionId, long uniqueRequestId) {
             final RouterRecord matchingRecord = mSessionToRouterMap.get(uniqueSessionId);
             if (matchingRecord != routerRecord) {
                 Slog.w(TAG, "Ignoring releasing session from non-matching router."
@@ -1329,14 +1365,14 @@
                 return;
             }
 
-            provider.releaseSession(sessionId);
+            provider.releaseSession(sessionId, uniqueRequestId);
         }
 
         private void onSessionCreatedOnHandler(@NonNull MediaRoute2Provider provider,
                 @NonNull RoutingSessionInfo sessionInfo, long requestId) {
             notifySessionCreatedToManagers(getManagers(), sessionInfo);
 
-            if (requestId == MediaRoute2ProviderService.REQUEST_ID_UNKNOWN) {
+            if (requestId == REQUEST_ID_NONE) {
                 // The session is created without any matching request.
                 return;
             }
@@ -1362,7 +1398,7 @@
 
             if (sessionInfo == null) {
                 // Failed
-                notifySessionCreationFailed(matchingRequest.mRouterRecord,
+                notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord,
                         toOriginalRequestId(requestId));
                 return;
             }
@@ -1374,13 +1410,13 @@
                 Slog.w(TAG, "Created session doesn't match the original request."
                         + " originalRouteId=" + originalRouteId
                         + ", requestId=" + requestId + ", sessionInfo=" + sessionInfo);
-                notifySessionCreationFailed(matchingRequest.mRouterRecord,
+                notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord,
                         toOriginalRequestId(requestId));
                 return;
             }
 
             // Succeeded
-            notifySessionCreated(matchingRequest.mRouterRecord,
+            notifySessionCreatedToRouter(matchingRequest.mRouterRecord,
                     sessionInfo, toOriginalRequestId(requestId));
             mSessionToRouterMap.put(sessionInfo.getId(), routerRecord);
         }
@@ -1405,7 +1441,7 @@
             }
 
             mSessionCreationRequests.remove(matchingRequest);
-            notifySessionCreationFailed(matchingRequest.mRouterRecord,
+            notifySessionCreationFailedToRouter(matchingRequest.mRouterRecord,
                     toOriginalRequestId(requestId));
         }
 
@@ -1429,7 +1465,7 @@
                 Slog.w(TAG, "No matching router found for session=" + sessionInfo);
                 return;
             }
-            notifySessionInfoChanged(routerRecord, sessionInfo);
+            notifySessionInfoChangedToRouter(routerRecord, sessionInfo);
         }
 
         private void onSessionReleasedOnHandler(@NonNull MediaRoute2Provider provider,
@@ -1442,10 +1478,38 @@
                 Slog.w(TAG, "No matching router found for session=" + sessionInfo);
                 return;
             }
-            notifySessionReleased(routerRecord, sessionInfo);
+            notifySessionReleasedToRouter(routerRecord, sessionInfo);
         }
 
-        private void notifySessionCreated(@NonNull RouterRecord routerRecord,
+        private void onRequestFailedOnHandler(@NonNull MediaRoute2Provider provider,
+                long requestId, int reason) {
+            final int managerId = toRouterOrManagerId(requestId);
+
+            MediaRouter2ServiceImpl service = mServiceRef.get();
+            if (service == null) {
+                return;
+            }
+
+            ManagerRecord managerToNotifyFailure = null;
+            synchronized (service.mLock) {
+                for (ManagerRecord manager : mUserRecord.mManagerRecords) {
+                    if (manager.mManagerId == managerId) {
+                        managerToNotifyFailure = manager;
+                        break;
+                    }
+                }
+            }
+
+            if (managerToNotifyFailure == null) {
+                Slog.w(TAG, "No matching managerRecord found for managerId=" + managerId);
+                return;
+            }
+
+            notifyRequestFailedToManager(
+                    managerToNotifyFailure.mManager, toOriginalRequestId(requestId), reason);
+        }
+
+        private void notifySessionCreatedToRouter(@NonNull RouterRecord routerRecord,
                 @NonNull RoutingSessionInfo sessionInfo, int requestId) {
             try {
                 routerRecord.mRouter.notifySessionCreated(sessionInfo, requestId);
@@ -1455,7 +1519,7 @@
             }
         }
 
-        private void notifySessionCreationFailed(@NonNull RouterRecord routerRecord,
+        private void notifySessionCreationFailedToRouter(@NonNull RouterRecord routerRecord,
                 int requestId) {
             try {
                 routerRecord.mRouter.notifySessionCreated(/* sessionInfo= */ null, requestId);
@@ -1465,7 +1529,7 @@
             }
         }
 
-        private void notifySessionInfoChanged(@NonNull RouterRecord routerRecord,
+        private void notifySessionInfoChangedToRouter(@NonNull RouterRecord routerRecord,
                 @NonNull RoutingSessionInfo sessionInfo) {
             try {
                 routerRecord.mRouter.notifySessionInfoChanged(sessionInfo);
@@ -1475,7 +1539,7 @@
             }
         }
 
-        private void notifySessionReleased(@NonNull RouterRecord routerRecord,
+        private void notifySessionReleasedToRouter(@NonNull RouterRecord routerRecord,
                 @NonNull RoutingSessionInfo sessionInfo) {
             try {
                 routerRecord.mRouter.notifySessionReleased(sessionInfo);
@@ -1485,21 +1549,23 @@
             }
         }
 
-        private void setRouteVolumeOnHandler(@NonNull MediaRoute2Info route, int volume) {
+        private void setRouteVolumeOnHandler(@NonNull MediaRoute2Info route, int volume,
+                long requestId) {
             final MediaRoute2Provider provider = findProvider(route.getProviderId());
             if (provider != null) {
-                provider.setRouteVolume(route.getOriginalId(), volume);
+                provider.setRouteVolume(route.getOriginalId(), volume, requestId);
             }
         }
 
-        private void setSessionVolumeOnHandler(@NonNull String uniqueSessionId, int volume) {
+        private void setSessionVolumeOnHandler(@NonNull String uniqueSessionId, int volume,
+                long requestId) {
             final MediaRoute2Provider provider = findProvider(getProviderId(uniqueSessionId));
             if (provider == null) {
                 Slog.w(TAG, "setSessionVolume: couldn't find provider for session "
                         + "id=" + uniqueSessionId);
                 return;
             }
-            provider.setSessionVolume(getOriginalId(uniqueSessionId), volume);
+            provider.setSessionVolume(getOriginalId(uniqueSessionId), volume, requestId);
         }
 
         private List<IMediaRouter2> getRouters() {
@@ -1683,7 +1749,17 @@
             }
         }
 
-        private void updateDiscoveryPreference() {
+        private void notifyRequestFailedToManager(@NonNull IMediaRouter2Manager manager,
+                int requestId, int reason) {
+            try {
+                manager.notifyRequestFailed(requestId, reason);
+            } catch (RemoteException ex) {
+                Slog.w(TAG, "Failed to notify manager of the request failure."
+                        + " Manager probably died.", ex);
+            }
+        }
+
+        private void updateDiscoveryPreferenceOnHandler() {
             MediaRouter2ServiceImpl service = mServiceRef.get();
             if (service == null) {
                 return;
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 580fc52..a13ee10 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -543,8 +543,8 @@
     // Binder call
     @Override
     public void setRouteVolumeWithManager(IMediaRouter2Manager manager,
-            MediaRoute2Info route, int volume) {
-        mService2.setRouteVolumeWithManager(manager, route, volume);
+            MediaRoute2Info route, int volume, int requestId) {
+        mService2.setRouteVolumeWithManager(manager, route, volume, requestId);
     }
 
     // Binder call
@@ -557,35 +557,36 @@
     // Binder call
     @Override
     public void selectRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            MediaRoute2Info route) {
-        mService2.selectRouteWithManager(manager, sessionId, route);
+            MediaRoute2Info route, int requestId) {
+        mService2.selectRouteWithManager(manager, sessionId, route, requestId);
     }
 
     // Binder call
     @Override
     public void deselectRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            MediaRoute2Info route) {
-        mService2.deselectRouteWithManager(manager, sessionId, route);
+            MediaRoute2Info route, int requestId) {
+        mService2.deselectRouteWithManager(manager, sessionId, route, requestId);
     }
 
     // Binder call
     @Override
     public void transferToRouteWithManager(IMediaRouter2Manager manager, String sessionId,
-            MediaRoute2Info route) {
-        mService2.transferToRouteWithManager(manager, sessionId, route);
+            MediaRoute2Info route, int requestId) {
+        mService2.transferToRouteWithManager(manager, sessionId, route, requestId);
     }
 
     // Binder call
     @Override
     public void setSessionVolumeWithManager(IMediaRouter2Manager manager,
-            String sessionId, int volume) {
-        mService2.setSessionVolumeWithManager(manager, sessionId, volume);
+            String sessionId, int volume, int requestId) {
+        mService2.setSessionVolumeWithManager(manager, sessionId, volume, requestId);
     }
 
     // Binder call
     @Override
-    public void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId) {
-        mService2.releaseSessionWithManager(manager, sessionId);
+    public void releaseSessionWithManager(IMediaRouter2Manager manager, String sessionId,
+            int requestId) {
+        mService2.releaseSessionWithManager(manager, sessionId, requestId);
     }
 
     void restoreBluetoothA2dp() {
diff --git a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
index 05867ba..ce72a8a 100644
--- a/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/SystemMediaRoute2Provider.java
@@ -130,26 +130,27 @@
     }
 
     @Override
-    public void releaseSession(String sessionId) {
+    public void releaseSession(String sessionId, long requestId) {
         // Do nothing
     }
+
     @Override
     public void updateDiscoveryPreference(RouteDiscoveryPreference discoveryPreference) {
         // Do nothing
     }
 
     @Override
-    public void selectRoute(String sessionId, String routeId) {
+    public void selectRoute(String sessionId, String routeId, long requestId) {
         // Do nothing since we don't support multiple BT yet.
     }
 
     @Override
-    public void deselectRoute(String sessionId, String routeId) {
+    public void deselectRoute(String sessionId, String routeId, long requestId) {
         // Do nothing since we don't support multiple BT yet.
     }
 
     @Override
-    public void transferToRoute(String sessionId, String routeId) {
+    public void transferToRoute(String sessionId, String routeId, long requestId) {
         if (TextUtils.equals(routeId, mDefaultRoute.getId())) {
             mBtRouteProvider.transferTo(null);
         } else {
@@ -158,7 +159,7 @@
     }
 
     @Override
-    public void setRouteVolume(String routeId, int volume) {
+    public void setRouteVolume(String routeId, int volume, long requestId) {
         if (!TextUtils.equals(routeId, mSelectedRouteId)) {
             return;
         }
@@ -166,7 +167,7 @@
     }
 
     @Override
-    public void setSessionVolume(String sessionId, int volume) {
+    public void setSessionVolume(String sessionId, int volume, long requestId) {
         // Do nothing since we don't support grouping volume yet.
     }
 
@@ -214,6 +215,8 @@
      * Updates the mSessionInfo. Returns true if the session info is changed.
      */
     boolean updateSessionInfosIfNeededLocked() {
+        // Prevent to execute this method before mBtRouteProvider is created.
+        if (mBtRouteProvider == null) return false;
         RoutingSessionInfo oldSessionInfo = mSessionInfos.isEmpty() ? null : mSessionInfos.get(0);
 
         RoutingSessionInfo.Builder builder = new RoutingSessionInfo.Builder(
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 0662400..ee5a4fe 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -1253,7 +1253,7 @@
         final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
         Trace.traceEnd(TRACE_TAG_NETWORK);
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
-        final NetworkStats xtSnapshot = getNetworkStatsXt();
+        final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
         Trace.traceEnd(TRACE_TAG_NETWORK);
         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
         final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
@@ -1742,18 +1742,6 @@
                 mUseBpfTrafficStats);
         uidSnapshot.combineAllValues(tetherSnapshot);
 
-        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
-                Context.TELEPHONY_SERVICE);
-
-        // fold video calling data usage stats into uid snapshot
-        final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
-        if (vtStats != null) {
-            vtStats.filter(UID_ALL, ifaces, TAG_ALL);
-            mStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats,
-                    mUseBpfTrafficStats);
-            uidSnapshot.combineAllValues(vtStats);
-        }
-
         // 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);
@@ -1766,24 +1754,6 @@
     }
 
     /**
-     * Return snapshot of current XT statistics with video calling data usage statistics.
-     */
-    private NetworkStats getNetworkStatsXt() throws RemoteException {
-        final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
-
-        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
-                Context.TELEPHONY_SERVICE);
-
-        // Merge video calling data usage into XT
-        final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE);
-        if (vtSnapshot != null) {
-            xtSnapshot.combineAllValues(vtSnapshot);
-        }
-
-        return xtSnapshot;
-    }
-
-    /**
      * Return snapshot of current tethering statistics. Will return empty
      * {@link NetworkStats} if any problems are encountered.
      */
diff --git a/services/core/java/com/android/server/notification/NotificationManagerInternal.java b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
index fce10e6..c301cd2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerInternal.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerInternal.java
@@ -27,4 +27,6 @@
             String tag, int id, int userId);
 
     void removeForegroundServiceFlagFromNotification(String pkg, int notificationId, int userId);
+
+    void onConversationRemoved(String pkg, int uid, String conversationId);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index ad4e81b..475f229 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -772,7 +772,7 @@
                         parser, mAllowedManagedServicePackages, forRestore, userId);
                 migratedManagedServices = true;
             } else if (mSnoozeHelper.XML_TAG_NAME.equals(parser.getName())) {
-                mSnoozeHelper.readXml(parser);
+                mSnoozeHelper.readXml(parser, System.currentTimeMillis());
             }
             if (LOCKSCREEN_ALLOW_SECURE_NOTIFICATIONS_TAG.equals(parser.getName())) {
                 if (forRestore && userId != UserHandle.USER_SYSTEM) {
@@ -2322,6 +2322,8 @@
             mConditionProviders.onBootPhaseAppsCanStart();
             mHistoryManager.onBootPhaseAppsCanStart();
             registerDeviceConfigChange();
+        } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
+            mSnoozeHelper.scheduleRepostsForPersistedNotifications(System.currentTimeMillis());
         }
     }
 
@@ -3440,6 +3442,27 @@
         }
 
         @Override
+        public ParceledListSlice<ConversationChannelWrapper> getConversations(
+                boolean onlyImportant) {
+            enforceSystemOrSystemUI("getConversations");
+            ArrayList<ConversationChannelWrapper> conversations =
+                    mPreferencesHelper.getConversations(onlyImportant);
+            for (ConversationChannelWrapper conversation : conversations) {
+                LauncherApps.ShortcutQuery query = new LauncherApps.ShortcutQuery()
+                        .setPackage(conversation.getPkg())
+                        .setQueryFlags(FLAG_MATCH_DYNAMIC | FLAG_MATCH_PINNED)
+                        .setShortcutIds(Arrays.asList(
+                                conversation.getNotificationChannel().getConversationId()));
+                List<ShortcutInfo> shortcuts = mLauncherAppsService.getShortcuts(
+                        query, UserHandle.of(UserHandle.getUserId(conversation.getUid())));
+                if (shortcuts != null && !shortcuts.isEmpty()) {
+                    conversation.setShortcutInfo(shortcuts.get(0));
+                }
+            }
+            return new ParceledListSlice<>(conversations);
+        }
+
+        @Override
         public ParceledListSlice<NotificationChannelGroup> getNotificationChannelGroupsForPackage(
                 String pkg, int uid, boolean includeDeleted) {
             enforceSystemOrSystemUI("getNotificationChannelGroupsForPackage");
@@ -5453,6 +5476,11 @@
             });
         }
 
+        @Override
+        public void onConversationRemoved(String pkg, int uid, String conversationId) {
+            onConversationRemovedInternal(pkg, uid, conversationId);
+        }
+
         @GuardedBy("mNotificationLock")
         private void removeForegroundServiceFlagLocked(NotificationRecord r) {
             if (r == null) {
@@ -5655,7 +5683,7 @@
         mHandler.post(new EnqueueNotificationRunnable(userId, r, isAppForeground));
     }
 
-    public void onConversationRemoved(String pkg, int uid, String conversationId) {
+    private void onConversationRemovedInternal(String pkg, int uid, String conversationId) {
         checkCallerIsSystem();
         Preconditions.checkStringNotEmpty(pkg);
         Preconditions.checkStringNotEmpty(conversationId);
@@ -8609,21 +8637,11 @@
 
     @VisibleForTesting
     boolean canUseManagedServices(String pkg, Integer userId, String requiredPermission) {
-        boolean canUseManagedServices = !mActivityManager.isLowRamDevice()
-                || mPackageManagerClient.hasSystemFeature(PackageManager.FEATURE_WATCH);
-
-        for (String whitelisted : getContext().getResources().getStringArray(
-                R.array.config_allowedManagedServicesOnLowRamDevices)) {
-            if (whitelisted.equals(pkg)) {
-                canUseManagedServices = true;
-                break;
-            }
-        }
-
+        boolean canUseManagedServices = true;
         if (requiredPermission != null) {
             try {
                 if (mPackageManager.checkPermission(requiredPermission, pkg, userId)
-                    != PackageManager.PERMISSION_GRANTED) {
+                        != PackageManager.PERMISSION_GRANTED) {
                     canUseManagedServices = false;
                 }
             } catch (RemoteException e) {
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 20c8625..b8186ed 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -1186,6 +1186,44 @@
         return groups;
     }
 
+    public ArrayList<ConversationChannelWrapper> getConversations(boolean onlyImportant) {
+        synchronized (mPackagePreferences) {
+            ArrayList<ConversationChannelWrapper> conversations = new ArrayList<>();
+
+            for (PackagePreferences p : mPackagePreferences.values()) {
+                int N = p.channels.size();
+                for (int i = 0; i < N; i++) {
+                    final NotificationChannel nc = p.channels.valueAt(i);
+                    if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()
+                            && (nc.isImportantConversation() || !onlyImportant)) {
+                        ConversationChannelWrapper conversation = new ConversationChannelWrapper();
+                        conversation.setPkg(p.pkg);
+                        conversation.setUid(p.uid);
+                        conversation.setNotificationChannel(nc);
+                        conversation.setParentChannelLabel(
+                                p.channels.get(nc.getParentChannelId()).getName());
+                        boolean blockedByGroup = false;
+                        if (nc.getGroup() != null) {
+                            NotificationChannelGroup group = p.groups.get(nc.getGroup());
+                            if (group != null) {
+                                if (group.isBlocked()) {
+                                    blockedByGroup = true;
+                                } else {
+                                    conversation.setGroupLabel(group.getName());
+                                }
+                            }
+                        }
+                        if (!blockedByGroup) {
+                            conversations.add(conversation);
+                        }
+                    }
+                }
+            }
+
+            return conversations;
+        }
+    }
+
     public ArrayList<ConversationChannelWrapper> getConversations(String pkg, int uid) {
         Objects.requireNonNull(pkg);
         synchronized (mPackagePreferences) {
@@ -1199,6 +1237,8 @@
                 final NotificationChannel nc = r.channels.valueAt(i);
                 if (!TextUtils.isEmpty(nc.getConversationId()) && !nc.isDeleted()) {
                     ConversationChannelWrapper conversation = new ConversationChannelWrapper();
+                    conversation.setPkg(r.pkg);
+                    conversation.setUid(r.uid);
                     conversation.setNotificationChannel(nc);
                     conversation.setParentChannelLabel(
                             r.channels.get(nc.getParentChannelId()).getName());
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index bae1dd3..d60c291 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -36,6 +36,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
+import com.android.internal.util.XmlUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
@@ -43,9 +44,7 @@
 
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.sql.Array;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
@@ -172,7 +171,7 @@
             for (int i = 0; i < allRecords.size(); i++) {
                 NotificationRecord r = allRecords.valueAt(i);
                 String currentGroupKey = r.getSbn().getGroup();
-                if (currentGroupKey.equals(groupKey)) {
+                if (Objects.equals(currentGroupKey, groupKey)) {
                     records.add(r);
                 }
             }
@@ -217,7 +216,7 @@
 
         snooze(record);
         scheduleRepost(pkg, key, userId, duration);
-        Long activateAt = System.currentTimeMillis() + duration;
+        Long activateAt = SystemClock.elapsedRealtime() + duration;
         synchronized (mPersistedSnoozedNotifications) {
             storeRecord(pkg, key, userId, mPersistedSnoozedNotifications, activateAt);
         }
@@ -244,8 +243,6 @@
         }
         storeRecord(record.getSbn().getPackageName(), record.getKey(),
                 userId, mSnoozedNotifications, record);
-        mPackages.put(record.getKey(), record.getSbn().getPackageName());
-        mUsers.put(record.getKey(), userId);
     }
 
     private <T> void storeRecord(String pkg, String key, Integer userId,
@@ -258,6 +255,8 @@
         keyToValue.put(key, object);
         targets.put(getPkgKey(userId, pkg), keyToValue);
 
+        mPackages.put(key, pkg);
+        mUsers.put(key, userId);
     }
 
     private <T> T removeRecord(String pkg, String key, Integer userId,
@@ -425,12 +424,34 @@
                 PendingIntent.FLAG_UPDATE_CURRENT);
     }
 
+    public void scheduleRepostsForPersistedNotifications(long currentTime) {
+        for (ArrayMap<String, Long> snoozed : mPersistedSnoozedNotifications.values()) {
+            for (int i = 0; i < snoozed.size(); i++) {
+                String key = snoozed.keyAt(i);
+                Long time = snoozed.valueAt(i);
+                String pkg = mPackages.get(key);
+                Integer userId = mUsers.get(key);
+                if (time == null || pkg == null || userId == null) {
+                    Slog.w(TAG, "data out of sync: " + time + "|" + pkg + "|" + userId);
+                    continue;
+                }
+                if (time != null && time > currentTime) {
+                    scheduleRepostAtTime(pkg, key, userId, time);
+                }
+            }
+
+        }
+    }
+
     private void scheduleRepost(String pkg, String key, int userId, long duration) {
+        scheduleRepostAtTime(pkg, key, userId, SystemClock.elapsedRealtime() + duration);
+    }
+
+    private void scheduleRepostAtTime(String pkg, String key, int userId, long time) {
         long identity = Binder.clearCallingIdentity();
         try {
             final PendingIntent pi = createPendingIntent(pkg, key, userId);
             mAm.cancel(pi);
-            long time = SystemClock.elapsedRealtime() + duration;
             if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
             mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
         } finally {
@@ -496,6 +517,7 @@
     private interface Inserter<T> {
         void insert(T t) throws IOException;
     }
+
     private <T> void writeXml(XmlSerializer out,
             ArrayMap<String, ArrayMap<String, T>> targets, String tag,
             Inserter<T> attributeInserter)
@@ -503,12 +525,13 @@
         synchronized (targets) {
             final int M = targets.size();
             for (int i = 0; i < M; i++) {
-                String userIdPkgKey = targets.keyAt(i);
                 // T is a String (snoozed until context) or Long (snoozed until time)
                 ArrayMap<String, T> keyToValue = targets.valueAt(i);
                 for (int j = 0; j < keyToValue.size(); j++) {
                     String key = keyToValue.keyAt(j);
                     T value = keyToValue.valueAt(j);
+                    String pkg = mPackages.get(key);
+                    Integer userId = mUsers.get(key);
 
                     out.startTag(null, tag);
 
@@ -518,8 +541,7 @@
                             XML_SNOOZED_NOTIFICATION_VERSION);
                     out.attribute(null, XML_SNOOZED_NOTIFICATION_KEY, key);
 
-                    String pkg = mPackages.get(key);
-                    int userId = mUsers.get(key);
+
                     out.attribute(null, XML_SNOOZED_NOTIFICATION_PKG, pkg);
                     out.attribute(null, XML_SNOOZED_NOTIFICATION_USER_ID,
                             String.valueOf(userId));
@@ -530,7 +552,7 @@
         }
     }
 
-    protected void readXml(XmlPullParser parser)
+    protected void readXml(XmlPullParser parser, long currentTime)
             throws XmlPullParserException, IOException {
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
@@ -547,16 +569,15 @@
                 try {
                     final String key = parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_KEY);
                     final String pkg = parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_PKG);
-                    final int userId = Integer.parseInt(
-                            parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_USER_ID));
+                    final int userId = XmlUtils.readIntAttribute(
+                            parser, XML_SNOOZED_NOTIFICATION_USER_ID, UserHandle.USER_ALL);
                     if (tag.equals(XML_SNOOZED_NOTIFICATION)) {
-                        final Long time = Long.parseLong(
-                                parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_TIME));
-                        if (time > System.currentTimeMillis()) { //only read new stuff
+                        final Long time = XmlUtils.readLongAttribute(
+                                parser, XML_SNOOZED_NOTIFICATION_TIME, 0);
+                        if (time > currentTime) { //only read new stuff
                             synchronized (mPersistedSnoozedNotifications) {
                                 storeRecord(pkg, key, userId, mPersistedSnoozedNotifications, time);
                             }
-                            scheduleRepost(pkg, key, userId, time - System.currentTimeMillis());
                         }
                     }
                     if (tag.equals(XML_SNOOZED_NOTIFICATION_CONTEXT)) {
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index 3b564c3..f45e66e 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -19,6 +19,7 @@
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_DISABLED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_ENABLED;
 import static android.app.NotificationManager.AUTOMATIC_RULE_STATUS_REMOVED;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
 
 import android.app.AppOpsManager;
 import android.app.AutomaticZenRule;
@@ -1011,21 +1012,23 @@
 
     @VisibleForTesting
     protected void applyRestrictions() {
+        final boolean zenOn = mZenMode != Global.ZEN_MODE_OFF;
         final boolean zenPriorityOnly = mZenMode == Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         final boolean zenSilence = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;
         final boolean zenAlarmsOnly = mZenMode == Global.ZEN_MODE_ALARMS;
-        final boolean allowCalls = mConsolidatedPolicy.allowCalls();
+        final boolean allowCalls = mConsolidatedPolicy.allowCalls()
+                && mConsolidatedPolicy.allowCallsFrom() == PRIORITY_SENDERS_ANY;
         final boolean allowRepeatCallers = mConsolidatedPolicy.allowRepeatCallers();
         final boolean allowSystem = mConsolidatedPolicy.allowSystem();
         final boolean allowMedia = mConsolidatedPolicy.allowMedia();
         final boolean allowAlarms = mConsolidatedPolicy.allowAlarms();
 
         // notification restrictions
-        final boolean muteNotifications =
-                (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
+        final boolean muteNotifications = zenOn
+                || (mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
         // call restrictions
         final boolean muteCalls = zenAlarmsOnly
-                || (zenPriorityOnly && !allowCalls && !allowRepeatCallers)
+                || (zenPriorityOnly && !(allowCalls || allowRepeatCallers))
                 || (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
         // alarm restrictions
         final boolean muteAlarms = zenPriorityOnly && !allowAlarms;
diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java
index d75eb6d..f221285 100644
--- a/services/core/java/com/android/server/om/OverlayManagerService.java
+++ b/services/core/java/com/android/server/om/OverlayManagerService.java
@@ -62,6 +62,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 
+import com.android.internal.content.om.OverlayConfig;
 import com.android.server.FgThread;
 import com.android.server.IoThread;
 import com.android.server.LocalServices;
@@ -248,7 +249,8 @@
             IdmapManager im = new IdmapManager(mPackageManager);
             mSettings = new OverlayManagerSettings();
             mImpl = new OverlayManagerServiceImpl(mPackageManager, im, mSettings,
-                    getDefaultOverlayPackages(), new OverlayChangeListener());
+                    OverlayConfig.getSystemInstance(), getDefaultOverlayPackages(),
+                    new OverlayChangeListener());
             mActorEnforcer = new OverlayActorEnforcer(mPackageManager);
 
             final IntentFilter packageFilter = new IntentFilter();
@@ -835,7 +837,7 @@
                     case "basecodepath":
                     case "state":
                     case "isenabled":
-                    case "isstatic":
+                    case "ismutable":
                     case "priority":
                     case "category":
                         dumpState.setField(arg);
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 9623542..2493057 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -18,7 +18,7 @@
 
 import static android.content.om.OverlayInfo.STATE_DISABLED;
 import static android.content.om.OverlayInfo.STATE_ENABLED;
-import static android.content.om.OverlayInfo.STATE_ENABLED_STATIC;
+import static android.content.om.OverlayInfo.STATE_ENABLED_IMMUTABLE;
 import static android.content.om.OverlayInfo.STATE_MISSING_TARGET;
 import static android.content.om.OverlayInfo.STATE_NO_IDMAP;
 import static android.content.om.OverlayInfo.STATE_OVERLAY_IS_BEING_REPLACED;
@@ -37,6 +37,7 @@
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.content.om.OverlayConfig;
 import com.android.internal.util.ArrayUtils;
 
 import java.io.PrintWriter;
@@ -69,6 +70,7 @@
     private final PackageManagerHelper mPackageManager;
     private final IdmapManager mIdmapManager;
     private final OverlayManagerSettings mSettings;
+    private final OverlayConfig mOverlayConfig;
     private final String[] mDefaultOverlays;
     private final OverlayChangeListener mListener;
 
@@ -83,7 +85,7 @@
      * should either scrap the overlay manager's previous settings or merge the old
      * settings with the new.
      */
-    private static boolean mustReinitializeOverlay(@NonNull final PackageInfo theTruth,
+    private boolean mustReinitializeOverlay(@NonNull final PackageInfo theTruth,
             @Nullable final OverlayInfo oldSettings) {
         if (oldSettings == null) {
             return true;
@@ -94,27 +96,35 @@
         if (!Objects.equals(theTruth.targetOverlayableName, oldSettings.targetOverlayableName)) {
             return true;
         }
-        if (theTruth.isStaticOverlayPackage() != oldSettings.isStatic) {
+
+        boolean isMutable = isPackageConfiguredMutable(theTruth.packageName);
+        if (isMutable != oldSettings.isMutable) {
             return true;
         }
-        // a change in priority is only relevant for static RROs: specifically,
-        // a regular RRO should not have its state reset only because a change
-        // in priority
-        if (theTruth.isStaticOverlayPackage()
-                && theTruth.overlayPriority != oldSettings.priority) {
+
+        if (getPackageConfiguredPriority(theTruth.packageName) != oldSettings.priority) {
             return true;
         }
+
+        // If an immutable overlay changes its configured enabled state, reinitialize the overlay.
+        if (!isMutable && isPackageConfiguredEnabled(theTruth.packageName)
+                != oldSettings.isEnabled()) {
+            return true;
+        }
+
         return false;
     }
 
     OverlayManagerServiceImpl(@NonNull final PackageManagerHelper packageManager,
             @NonNull final IdmapManager idmapManager,
             @NonNull final OverlayManagerSettings settings,
+            @NonNull final OverlayConfig overlayConfig,
             @NonNull final String[] defaultOverlays,
             @NonNull final OverlayChangeListener listener) {
         mPackageManager = packageManager;
         mIdmapManager = idmapManager;
         mSettings = settings;
+        mOverlayConfig = overlayConfig;
         mDefaultOverlays = defaultOverlays;
         mListener = listener;
     }
@@ -162,8 +172,9 @@
                         overlayPackage.overlayTarget,
                         overlayPackage.targetOverlayableName,
                         overlayPackage.applicationInfo.getBaseCodePath(),
-                        overlayPackage.isStaticOverlayPackage(),
-                        overlayPackage.overlayPriority,
+                        isPackageConfiguredMutable(overlayPackage.packageName),
+                        isPackageConfiguredEnabled(overlayPackage.packageName),
+                        getPackageConfiguredPriority(overlayPackage.packageName),
                         overlayPackage.overlayCategory);
             }
 
@@ -374,7 +385,9 @@
         mSettings.init(packageName, userId, overlayPackage.overlayTarget,
                 overlayPackage.targetOverlayableName,
                 overlayPackage.applicationInfo.getBaseCodePath(),
-                overlayPackage.isStaticOverlayPackage(), overlayPackage.overlayPriority,
+                isPackageConfiguredMutable(overlayPackage.packageName),
+                isPackageConfiguredEnabled(overlayPackage.packageName),
+                getPackageConfiguredPriority(overlayPackage.packageName),
                 overlayPackage.overlayCategory);
         try {
             if (updateState(overlayPackage.overlayTarget, packageName, userId, 0)) {
@@ -439,8 +452,10 @@
                     mListener.onOverlaysChanged(pkg.overlayTarget, userId);
                 }
                 mSettings.init(packageName, userId, pkg.overlayTarget, pkg.targetOverlayableName,
-                        pkg.applicationInfo.getBaseCodePath(), pkg.isStaticOverlayPackage(),
-                        pkg.overlayPriority, pkg.overlayCategory);
+                        pkg.applicationInfo.getBaseCodePath(),
+                        isPackageConfiguredMutable(pkg.packageName),
+                        isPackageConfiguredEnabled(pkg.packageName),
+                        getPackageConfiguredPriority(pkg.packageName), pkg.overlayCategory);
             }
 
             if (updateState(pkg.overlayTarget, packageName, userId, 0)) {
@@ -492,13 +507,13 @@
             return false;
         }
 
-        // Ignore static overlays.
-        if (overlayPackage.isStaticOverlayPackage()) {
-            return false;
-        }
-
         try {
             final OverlayInfo oi = mSettings.getOverlayInfo(packageName, userId);
+            if (!oi.isMutable) {
+                // Ignore immutable overlays.
+                return false;
+            }
+
             boolean modified = mSettings.setEnabled(packageName, userId, enable);
             modified |= updateState(oi.targetPackageName, oi.packageName, userId, 0);
 
@@ -534,7 +549,8 @@
             // Disable all other overlays.
             allOverlays.remove(oi);
             for (int i = 0; i < allOverlays.size(); i++) {
-                final String disabledOverlayPackageName = allOverlays.get(i).packageName;
+                final OverlayInfo disabledInfo = allOverlays.get(i);
+                final String disabledOverlayPackageName = disabledInfo.packageName;
                 final PackageInfo disabledOverlayPackageInfo = mPackageManager.getPackageInfo(
                         disabledOverlayPackageName, userId);
                 if (disabledOverlayPackageInfo == null) {
@@ -542,8 +558,8 @@
                     continue;
                 }
 
-                if (disabledOverlayPackageInfo.isStaticOverlayPackage()) {
-                    // Don't touch static overlays.
+                if (!disabledInfo.isMutable) {
+                    // Don't touch immutable overlays.
                     continue;
                 }
                 if (withinCategory && !Objects.equals(disabledOverlayPackageInfo.overlayCategory,
@@ -570,12 +586,16 @@
         }
     }
 
-    private boolean isPackageUpdatableOverlay(@NonNull final String packageName, final int userId) {
-        final PackageInfo overlayPackage = mPackageManager.getPackageInfo(packageName, userId);
-        if (overlayPackage == null || overlayPackage.isStaticOverlayPackage()) {
-            return false;
-        }
-        return true;
+    private boolean isPackageConfiguredMutable(@NonNull final String packageName) {
+        return mOverlayConfig.isMutable(packageName);
+    }
+
+    private int getPackageConfiguredPriority(@NonNull final String packageName) {
+        return mOverlayConfig.getPriority(packageName);
+    }
+
+    private boolean isPackageConfiguredEnabled(@NonNull final String packageName) {
+        return mOverlayConfig.isEnabled(packageName);
     }
 
     boolean setPriority(@NonNull final String packageName,
@@ -585,7 +605,7 @@
                     + newParentPackageName + " userId=" + userId);
         }
 
-        if (!isPackageUpdatableOverlay(packageName, userId)) {
+        if (!isPackageConfiguredMutable(packageName)) {
             return false;
         }
 
@@ -605,7 +625,7 @@
             Slog.d(TAG, "setHighestPriority packageName=" + packageName + " userId=" + userId);
         }
 
-        if (!isPackageUpdatableOverlay(packageName, userId)) {
+        if (!isPackageConfiguredMutable(packageName)) {
             return false;
         }
 
@@ -625,7 +645,7 @@
             Slog.d(TAG, "setLowestPriority packageName=" + packageName + " userId=" + userId);
         }
 
-        if (!isPackageUpdatableOverlay(packageName, userId)) {
+        if (!isPackageConfiguredMutable(packageName)) {
             return false;
         }
 
@@ -682,10 +702,10 @@
         final PackageInfo overlayPackage = mPackageManager.getPackageInfo(overlayPackageName,
                 userId);
 
-        // Static RROs targeting to "android", ie framework-res.apk, are handled by native layers.
+        // Immutable RROs targeting to "android", ie framework-res.apk, are handled by native layers.
         if (targetPackage != null && overlayPackage != null
                 && !("android".equals(targetPackageName)
-                    && overlayPackage.isStaticOverlayPackage())) {
+                    && !isPackageConfiguredMutable(overlayPackageName))) {
             mIdmapManager.createIdmap(targetPackage, overlayPackage, userId);
         }
 
@@ -737,10 +757,6 @@
             return STATE_NO_IDMAP;
         }
 
-        if (overlayPackage.isStaticOverlayPackage()) {
-            return STATE_ENABLED_STATIC;
-        }
-
         final boolean enabled = mSettings.getEnabled(overlayPackage.packageName, userId);
         return enabled ? STATE_ENABLED : STATE_DISABLED;
     }
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index b7346d4..6bccdfc 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -67,32 +67,27 @@
     private final ArrayList<SettingsItem> mItems = new ArrayList<>();
 
     void init(@NonNull final String packageName, final int userId,
-            @NonNull final String targetPackageName,  @Nullable final String targetOverlayableName,
-            @NonNull final String baseCodePath, boolean isStatic, int priority,
+            @NonNull final String targetPackageName, @Nullable final String targetOverlayableName,
+            @NonNull final String baseCodePath, boolean isMutable, boolean isEnabled, int priority,
             @Nullable String overlayCategory) {
         remove(packageName, userId);
         final SettingsItem item =
                 new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName,
-                        baseCodePath, isStatic, priority, overlayCategory);
-        if (isStatic) {
-            // All static overlays are always enabled.
-            item.setEnabled(true);
+                        baseCodePath, OverlayInfo.STATE_UNKNOWN, isEnabled, isMutable, priority,
+                        overlayCategory);
 
-            int i;
-            for (i = mItems.size() - 1; i >= 0; i--) {
-                SettingsItem parentItem = mItems.get(i);
-                if (parentItem.mIsStatic && parentItem.mPriority <= priority) {
-                    break;
-                }
+        int i;
+        for (i = mItems.size() - 1; i >= 0; i--) {
+            SettingsItem parentItem = mItems.get(i);
+            if (parentItem.mPriority <= priority) {
+                break;
             }
-            int pos = i + 1;
-            if (pos == mItems.size()) {
-                mItems.add(item);
-            } else {
-                mItems.add(pos, item);
-            }
-        } else {
+        }
+        int pos = i + 1;
+        if (pos == mItems.size()) {
             mItems.add(item);
+        } else {
+            mItems.add(pos, item);
         }
     }
 
@@ -182,19 +177,19 @@
 
     List<OverlayInfo> getOverlaysForTarget(@NonNull final String targetPackageName,
             final int userId) {
-        // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+        // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be
         // ignored in OverlayManagerService.
         return selectWhereTarget(targetPackageName, userId)
-                .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
+                .filter((i) -> i.isMutable() || !"android".equals(i.getTargetPackageName()))
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.toList());
     }
 
     ArrayMap<String, List<OverlayInfo>> getOverlaysForUser(final int userId) {
-        // Static RROs targeting "android" are loaded from AssetManager, and so they should be
+        // Immutable RROs targeting "android" are loaded from AssetManager, and so they should be
         // ignored in OverlayManagerService.
         return selectWhereUser(userId)
-                .filter((i) -> !(i.isStatic() && "android".equals(i.getTargetPackageName())))
+                .filter((i) -> i.isMutable() || !"android".equals(i.getTargetPackageName()))
                 .map(SettingsItem::getOverlayInfo)
                 .collect(Collectors.groupingBy(info -> info.targetPackageName, ArrayMap::new,
                         Collectors.toList()));
@@ -320,7 +315,7 @@
         pw.println("mBaseCodePath..........: " + item.getBaseCodePath());
         pw.println("mState.................: " + OverlayInfo.stateToString(item.getState()));
         pw.println("mIsEnabled.............: " + item.isEnabled());
-        pw.println("mIsStatic..............: " + item.isStatic());
+        pw.println("mIsMutable.............: " + item.isMutable());
         pw.println("mPriority..............: " + item.mPriority);
         pw.println("mCategory..............: " + item.mCategory);
 
@@ -352,8 +347,8 @@
             case "isenabled":
                 pw.println(item.mIsEnabled);
                 break;
-            case "isstatic":
-                pw.println(item.mIsStatic);
+            case "ismutable":
+                pw.println(item.mIsMutable);
                 break;
             case "priority":
                 pw.println(item.mPriority);
@@ -446,7 +441,7 @@
             final String category = XmlUtils.readStringAttribute(parser, ATTR_CATEGORY);
 
             return new SettingsItem(packageName, userId, targetPackageName, targetOverlayableName,
-                    baseCodePath, state, isEnabled, isStatic, priority, category);
+                    baseCodePath, state, isEnabled, !isStatic, priority, category);
         }
 
         public static void persist(@NonNull final ArrayList<SettingsItem> table,
@@ -478,7 +473,7 @@
             XmlUtils.writeStringAttribute(xml, ATTR_BASE_CODE_PATH, item.mBaseCodePath);
             XmlUtils.writeIntAttribute(xml, ATTR_STATE, item.mState);
             XmlUtils.writeBooleanAttribute(xml, ATTR_IS_ENABLED, item.mIsEnabled);
-            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, item.mIsStatic);
+            XmlUtils.writeBooleanAttribute(xml, ATTR_IS_STATIC, !item.mIsMutable);
             XmlUtils.writeIntAttribute(xml, ATTR_PRIORITY, item.mPriority);
             XmlUtils.writeStringAttribute(xml, ATTR_CATEGORY, item.mCategory);
             xml.endTag(null, TAG_ITEM);
@@ -494,36 +489,28 @@
         private @OverlayInfo.State int mState;
         private boolean mIsEnabled;
         private OverlayInfo mCache;
-        private boolean mIsStatic;
+        private boolean mIsMutable;
         private int mPriority;
         private String mCategory;
 
         SettingsItem(@NonNull final String packageName, final int userId,
                 @NonNull final String targetPackageName,
                 @Nullable final String targetOverlayableName, @NonNull final String baseCodePath,
-                final @OverlayInfo.State int state, final boolean isEnabled, final boolean isStatic,
-                final int priority,  @Nullable String category) {
+                final @OverlayInfo.State int state, final boolean isEnabled,
+                final boolean isMutable, final int priority,  @Nullable String category) {
             mPackageName = packageName;
             mUserId = userId;
             mTargetPackageName = targetPackageName;
             mTargetOverlayableName = targetOverlayableName;
             mBaseCodePath = baseCodePath;
             mState = state;
-            mIsEnabled = isEnabled || isStatic;
+            mIsEnabled = isEnabled;
             mCategory = category;
             mCache = null;
-            mIsStatic = isStatic;
+            mIsMutable = isMutable;
             mPriority = priority;
         }
 
-        SettingsItem(@NonNull final String packageName, final int userId,
-                @NonNull final String targetPackageName,
-                @Nullable final String targetOverlayableName, @NonNull final String baseCodePath,
-                final boolean isStatic, final int priority, @Nullable String category) {
-            this(packageName, userId, targetPackageName, targetOverlayableName, baseCodePath,
-                    OverlayInfo.STATE_UNKNOWN, false, isStatic, priority, category);
-        }
-
         private String getTargetPackageName() {
             return mTargetPackageName;
         }
@@ -567,7 +554,7 @@
         }
 
         private boolean setEnabled(boolean enable) {
-            if (mIsStatic) {
+            if (!mIsMutable) {
                 return false;
             }
 
@@ -591,7 +578,7 @@
         private OverlayInfo getOverlayInfo() {
             if (mCache == null) {
                 mCache = new OverlayInfo(mPackageName, mTargetPackageName, mTargetOverlayableName,
-                        mCategory, mBaseCodePath, mState, mUserId, mPriority, mIsStatic);
+                        mCategory, mBaseCodePath, mState, mUserId, mPriority, mIsMutable);
             }
             return mCache;
         }
@@ -600,8 +587,8 @@
             mCache = null;
         }
 
-        private boolean isStatic() {
-            return mIsStatic;
+        private boolean isMutable() {
+            return mIsMutable;
         }
 
         private int getPriority() {
diff --git a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
index eb43275..bf99bd6 100644
--- a/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
+++ b/services/core/java/com/android/server/om/OverlayManagerShellCommand.java
@@ -181,7 +181,7 @@
     private void printListOverlay(PrintWriter out, OverlayInfo oi) {
         String status;
         switch (oi.state) {
-            case OverlayInfo.STATE_ENABLED_STATIC:
+            case OverlayInfo.STATE_ENABLED_IMMUTABLE:
             case OverlayInfo.STATE_ENABLED:
                 status = "[x]";
                 break;
diff --git a/services/core/java/com/android/server/om/OverlayReferenceMapper.java b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
index 8bea119..cadb8e4 100644
--- a/services/core/java/com/android/server/om/OverlayReferenceMapper.java
+++ b/services/core/java/com/android/server/om/OverlayReferenceMapper.java
@@ -18,16 +18,14 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.pm.parsing.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import android.text.TextUtils;
-import android.util.ArraySet;
 import android.util.Pair;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.CollectionUtils;
 import com.android.server.SystemConfig;
-import com.android.server.pm.PackageSetting;
 
 import java.util.Collections;
 import java.util.HashMap;
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index a440c62..d12e03d 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -32,7 +32,6 @@
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Environment;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -47,6 +46,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.utils.TimingsTraceAndSlog;
 
 import com.google.android.collect.Lists;
diff --git a/services/core/java/com/android/server/pm/AppsFilter.java b/services/core/java/com/android/server/pm/AppsFilter.java
index 0fb889c..1205a33 100644
--- a/services/core/java/com/android/server/pm/AppsFilter.java
+++ b/services/core/java/com/android/server/pm/AppsFilter.java
@@ -26,13 +26,12 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
-import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
 import android.os.Binder;
 import android.os.Process;
 import android.os.Trace;
@@ -50,6 +49,7 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.FgThread;
 import com.android.server.om.OverlayReferenceMapper;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.PrintWriter;
 import java.util.List;
@@ -69,7 +69,6 @@
     // Logs all filtering instead of enforcing
     private static final boolean DEBUG_ALLOW_ALL = false;
     private static final boolean DEBUG_LOGGING = false;
-    private static final boolean FEATURE_ENABLED_BY_DEFAULT = true;
 
     /**
      * This contains a list of app UIDs that are implicitly queryable because another app explicitly
@@ -135,7 +134,8 @@
     private static class FeatureConfigImpl implements FeatureConfig {
         private static final String FILTERING_ENABLED_NAME = "package_query_filtering_enabled";
         private final PackageManagerService.Injector mInjector;
-        private volatile boolean mFeatureEnabled = FEATURE_ENABLED_BY_DEFAULT;
+        private volatile boolean mFeatureEnabled =
+                PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT;
 
         private FeatureConfigImpl(PackageManagerService.Injector injector) {
             mInjector = injector;
@@ -145,14 +145,14 @@
         public void onSystemReady() {
             mFeatureEnabled = DeviceConfig.getBoolean(
                     NAMESPACE_PACKAGE_MANAGER_SERVICE, FILTERING_ENABLED_NAME,
-                    FEATURE_ENABLED_BY_DEFAULT);
+                    PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT);
             DeviceConfig.addOnPropertiesChangedListener(
                     NAMESPACE_PACKAGE_MANAGER_SERVICE, FgThread.getExecutor(),
                     properties -> {
                         if (properties.getKeyset().contains(FILTERING_ENABLED_NAME)) {
                             synchronized (FeatureConfigImpl.this) {
                                 mFeatureEnabled = properties.getBoolean(FILTERING_ENABLED_NAME,
-                                        FEATURE_ENABLED_BY_DEFAULT);
+                                        PackageManager.APP_ENUMERATION_ENABLED_BY_DEFAULT);
                             }
                         }
                     });
@@ -207,14 +207,14 @@
     /** Returns true if the querying package may query for the potential target package */
     private static boolean canQueryViaComponents(AndroidPackage querying,
             AndroidPackage potentialTarget) {
-        if (querying.getQueriesIntents() != null) {
+        if (!querying.getQueriesIntents().isEmpty()) {
             for (Intent intent : querying.getQueriesIntents()) {
                 if (matchesIntentFilters(intent, potentialTarget)) {
                     return true;
                 }
             }
         }
-        if (querying.getQueriesProviders() != null
+        if (!querying.getQueriesProviders().isEmpty()
                 && matchesProviders(querying.getQueriesProviders(), potentialTarget)) {
             return true;
         }
@@ -223,7 +223,7 @@
 
     private static boolean canQueryViaPackage(AndroidPackage querying,
             AndroidPackage potentialTarget) {
-        return querying.getQueriesPackages() != null
+        return !querying.getQueriesPackages().isEmpty()
                 && querying.getQueriesPackages().contains(potentialTarget.getPackageName());
     }
 
@@ -261,7 +261,7 @@
     private static boolean matchesIntentFilters(Intent intent, AndroidPackage potentialTarget) {
         for (int s = ArrayUtils.size(potentialTarget.getServices()) - 1; s >= 0; s--) {
             ParsedService service = potentialTarget.getServices().get(s);
-            if (!service.exported) {
+            if (!service.isExported()) {
                 continue;
             }
             if (matchesAnyFilter(intent, service)) {
@@ -270,7 +270,7 @@
         }
         for (int a = ArrayUtils.size(potentialTarget.getActivities()) - 1; a >= 0; a--) {
             ParsedActivity activity = potentialTarget.getActivities().get(a);
-            if (!activity.exported) {
+            if (!activity.isExported()) {
                 continue;
             }
             if (matchesAnyFilter(intent, activity)) {
@@ -279,7 +279,7 @@
         }
         for (int r = ArrayUtils.size(potentialTarget.getReceivers()) - 1; r >= 0; r--) {
             ParsedActivity receiver = potentialTarget.getReceivers().get(r);
-            if (!receiver.exported) {
+            if (!receiver.isExported()) {
                 continue;
             }
             if (matchesAnyFilter(intent, receiver)) {
@@ -289,9 +289,8 @@
         return false;
     }
 
-    private static boolean matchesAnyFilter(
-            Intent intent, ParsedComponent<? extends ParsedIntentInfo> component) {
-        List<? extends ParsedIntentInfo> intents = component.intents;
+    private static boolean matchesAnyFilter(Intent intent, ParsedComponent component) {
+        List<ParsedIntentInfo> intents = component.getIntents();
         for (int i = ArrayUtils.size(intents) - 1; i >= 0; i--) {
             IntentFilter intentFilter = intents.get(i);
             if (intentFilter.match(intent.getAction(), intent.getType(), intent.getScheme(),
@@ -673,8 +672,7 @@
             String targetName) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "callingPkgInstruments");
-            final List<ComponentParseUtils.ParsedInstrumentation> inst =
-                    callingPkgSetting.pkg.getInstrumentations();
+            final List<ParsedInstrumentation> inst = callingPkgSetting.pkg.getInstrumentations();
             for (int i = ArrayUtils.size(inst) - 1; i >= 0; i--) {
                 if (Objects.equals(inst.get(i).getTargetPackage(), targetName)) {
                     if (DEBUG_LOGGING) {
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
index 13bd7e5..85810e3 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -22,28 +22,27 @@
 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
 import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
 import android.content.pm.PackageUserState;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProviderIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
-import android.content.pm.parsing.ComponentParseUtils.ParsedServiceIntentInfo;
-import android.content.pm.parsing.PackageInfoUtils;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -56,6 +55,8 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.IntentResolver;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -189,8 +190,11 @@
      * of these during boot as we need to inspect at all of the intent filters on the
      * /system partition in order to know which component is the setup wizard. This can
      * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}.
+     *
+     * This is a pair of component package name to actual filter, because we don't store the
+     * name inside the filter. It's technically independent of the component it's contained in.
      */
-    private List<ParsedActivityIntentInfo> mProtectedFilters;
+    private List<Pair<ParsedMainComponent, ParsedIntentInfo>> mProtectedFilters;
 
     ComponentResolver(UserManagerService userManager,
             PackageManagerInternal packageManagerInternal,
@@ -229,9 +233,11 @@
     }
 
     @Nullable
-    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
+    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+            @PrivateResolveFlags int privateResolveFlags, int userId) {
         synchronized (mLock) {
-            return mActivities.queryIntent(intent, resolvedType, flags, userId);
+            return mActivities.queryIntent(
+                    intent, resolvedType, flags, privateResolveFlags, userId);
         }
     }
 
@@ -295,7 +301,7 @@
                     continue;
                 }
                 final ProviderInfo info = PackageInfoUtils.generateProviderInfo(
-                        pkg, p, flags, ps.readUserState(userId), userId);
+                        pkg, p, flags, ps.readUserState(userId), userId, ps);
                 if (info == null) {
                     continue;
                 }
@@ -325,7 +331,7 @@
                 return null;
             }
             return PackageInfoUtils.generateProviderInfo(pkg, p, flags,
-                    ps.readUserState(userId), userId);
+                    ps.readUserState(userId), userId, ps);
         }
     }
 
@@ -350,12 +356,12 @@
                     continue;
                 }
 
-                if (safeMode && (pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                if (safeMode && !pkg.isSystem()) {
                     continue;
                 }
                 final ProviderInfo info =
                         PackageInfoUtils.generateProviderInfo(pkg, p, 0,
-                                ps.readUserState(userId), userId);
+                                ps.readUserState(userId), userId, ps);
                 if (info == null) {
                     continue;
                 }
@@ -368,7 +374,7 @@
     @Nullable
     List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
         synchronized (mLock) {
-            return mReceivers.queryIntent(intent, resolvedType, flags, userId);
+            return mReceivers.queryIntent(intent, resolvedType, flags, 0, userId);
         }
     }
 
@@ -411,7 +417,7 @@
 
     /** Add all components defined in the given package to the internal structures. */
     void addAllComponents(AndroidPackage pkg, boolean chatty) {
-        final ArrayList<ParsedActivityIntentInfo> newIntents = new ArrayList<>();
+        final ArrayList<Pair<ParsedActivity, ParsedIntentInfo>> newIntents = new ArrayList<>();
         synchronized (mLock) {
             addActivitiesLocked(pkg, newIntents, chatty);
             addReceiversLocked(pkg, chatty);
@@ -424,14 +430,14 @@
                         PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM));
 
         for (int i = newIntents.size() - 1; i >= 0; --i) {
-            final ParsedActivityIntentInfo intentInfo = newIntents.get(i);
+            final Pair<ParsedActivity, ParsedIntentInfo> pair = newIntents.get(i);
             final PackageSetting disabledPkgSetting = (PackageSetting) sPackageManagerInternal
-                    .getDisabledSystemPackage(intentInfo.getPackageName());
+                    .getDisabledSystemPackage(pair.first.getPackageName());
             final AndroidPackage disabledPkg =
                     disabledPkgSetting == null ? null : disabledPkgSetting.pkg;
             final List<ParsedActivity> systemActivities =
                     disabledPkg != null ? disabledPkg.getActivities() : null;
-            adjustPriority(systemActivities, intentInfo, setupWizardPackage);
+            adjustPriority(systemActivities, pair.first, pair.second, setupWizardPackage);
         }
     }
 
@@ -455,7 +461,8 @@
         if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
             return;
         }
-        final List<ParsedActivityIntentInfo> protectedFilters = mProtectedFilters;
+        final List<Pair<ParsedMainComponent, ParsedIntentInfo>> protectedFilters =
+                mProtectedFilters;
         mProtectedFilters = null;
 
         // expect single setupwizard package
@@ -468,13 +475,17 @@
                     + " All protected intents capped to priority 0");
         }
         for (int i = protectedFilters.size() - 1; i >= 0; --i) {
-            final ParsedActivityIntentInfo filter = protectedFilters.get(i);
-            if (filter.getPackageName().equals(setupWizardPackage)) {
+            final Pair<ParsedMainComponent, ParsedIntentInfo> pair = protectedFilters.get(i);
+            ParsedMainComponent component = pair.first;
+            ParsedIntentInfo filter = pair.second;
+            String packageName = component.getPackageName();
+            String className = component.getClassName();
+            if (packageName.equals(setupWizardPackage)) {
                 if (DEBUG_FILTERS) {
                     Slog.i(TAG, "Found setup wizard;"
                             + " allow priority " + filter.getPriority() + ";"
-                            + " package: " + filter.getPackageName()
-                            + " activity: " + filter.getClassName()
+                            + " package: " + packageName
+                            + " activity: " + className
                             + " priority: " + filter.getPriority());
                 }
                 // skip setup wizard; allow it to keep the high priority filter
@@ -482,8 +493,8 @@
             }
             if (DEBUG_FILTERS) {
                 Slog.i(TAG, "Protected action; cap priority to 0;"
-                        + " package: " + filter.getPackageName()
-                        + " activity: " + filter.getClassName()
+                        + " package: " + packageName
+                        + " activity: " + className
                         + " origPrio: " + filter.getPriority());
             }
             filter.setPriority(0);
@@ -536,7 +547,7 @@
                 printedSomething = true;
             }
             pw.print("  ");
-            ComponentName.printShortString(pw, p.getPackageName(), p.className);
+            ComponentName.printShortString(pw, p.getPackageName(), p.getName());
             pw.println(":");
             pw.print("    ");
             pw.println(p.toString());
@@ -571,24 +582,11 @@
         if (dumpState.onTitlePrinted()) pw.println();
         pw.println("Service permissions:");
 
-        final Iterator<ParsedServiceIntentInfo> filterIterator = mServices.filterIterator();
+        final Iterator<Pair<ParsedService, ParsedIntentInfo>> filterIterator =
+                mServices.filterIterator();
         while (filterIterator.hasNext()) {
-            final ParsedServiceIntentInfo info = filterIterator.next();
-
-            ParsedService service = null;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(info.getPackageName());
-            if (pkg != null && pkg.getServices() != null) {
-                for (ParsedService parsedService : pkg.getServices()) {
-                    if (Objects.equals(parsedService.className, info.getClassName())) {
-                        service = parsedService;
-                    }
-                }
-            }
-
-            if (service == null) {
-                continue;
-            }
+            final Pair<ParsedService, ParsedIntentInfo> pair = filterIterator.next();
+            ParsedService service = pair.first;
 
             final String permission = service.getPermission();
             if (permission != null) {
@@ -602,7 +600,7 @@
 
     @GuardedBy("mLock")
     private void addActivitiesLocked(AndroidPackage pkg,
-            List<ParsedActivityIntentInfo> newIntents, boolean chatty) {
+            List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents, boolean chatty) {
         final int activitiesSize = ArrayUtils.size(pkg.getActivities());
         StringBuilder r = null;
         for (int i = 0; i < activitiesSize; i++) {
@@ -667,7 +665,7 @@
                         final String packageName =
                                 component != null ? component.getPackageName() : "?";
                         Slog.w(TAG, "Skipping provider name " + names[j]
-                                + " (in package " + pkg.getAppInfoPackageName() + ")"
+                                + " (in package " + pkg.getPackageName() + ")"
                                 + ": name already used by " + packageName);
                     }
                 }
@@ -732,8 +730,8 @@
      * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
      * MODIFIED. Do not pass in a list that should not be changed.
      */
-    private static <T> void getIntentListSubset(List<ParsedActivityIntentInfo> intentList,
-            Function<ParsedActivityIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator) {
+    private static <T> void getIntentListSubset(List<ParsedIntentInfo> intentList,
+            Function<ParsedIntentInfo, Iterator<T>> generator, Iterator<T> searchIterator) {
         // loop through the set of actions; every one must be found in the intent filter
         while (searchIterator.hasNext()) {
             // we must have at least one filter in the list to consider a match
@@ -744,9 +742,9 @@
             final T searchAction = searchIterator.next();
 
             // loop through the set of intent filters
-            final Iterator<ParsedActivityIntentInfo> intentIter = intentList.iterator();
+            final Iterator<ParsedIntentInfo> intentIter = intentList.iterator();
             while (intentIter.hasNext()) {
-                final ParsedActivityIntentInfo intentInfo = intentIter.next();
+                final ParsedIntentInfo intentInfo = intentIter.next();
                 boolean selectionFound = false;
 
                 // loop through the intent filter's selection criteria; at least one
@@ -769,7 +767,7 @@
         }
     }
 
-    private static boolean isProtectedAction(ParsedActivityIntentInfo filter) {
+    private static boolean isProtectedAction(ParsedIntentInfo filter) {
         final Iterator<String> actionsIter = filter.actionsIterator();
         while (actionsIter != null && actionsIter.hasNext()) {
             final String filterAction = actionsIter.next();
@@ -789,14 +787,14 @@
             if (sysActivity.getName().equals(activityInfo.getName())) {
                 return sysActivity;
             }
-            if (sysActivity.getName().equals(activityInfo.targetActivity)) {
+            if (sysActivity.getName().equals(activityInfo.getTargetActivity())) {
                 return sysActivity;
             }
-            if (sysActivity.targetActivity != null) {
-                if (sysActivity.targetActivity.equals(activityInfo.getName())) {
+            if (sysActivity.getTargetActivity() != null) {
+                if (sysActivity.getTargetActivity().equals(activityInfo.getName())) {
                     return sysActivity;
                 }
-                if (sysActivity.targetActivity.equals(activityInfo.targetActivity)) {
+                if (sysActivity.getTargetActivity().equals(activityInfo.getTargetActivity())) {
                     return sysActivity;
                 }
             }
@@ -817,23 +815,24 @@
      * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
      * allowed to obtain any priority on any action.
      */
-    private void adjustPriority(List<ParsedActivity> systemActivities,
-            ParsedActivityIntentInfo intent, String setupWizardPackage) {
+    private void adjustPriority(List<ParsedActivity> systemActivities, ParsedActivity activity,
+            ParsedIntentInfo intent, String setupWizardPackage) {
         // nothing to do; priority is fine as-is
         if (intent.getPriority() <= 0) {
             return;
         }
 
-        AndroidPackage pkg = sPackageManagerInternal.getPackage(intent.getPackageName());
+        String packageName = activity.getPackageName();
+        AndroidPackage pkg = sPackageManagerInternal.getPackage(packageName);
 
-        final boolean privilegedApp =
-                ((pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+        final boolean privilegedApp = pkg.isPrivileged();
+        String className = activity.getClassName();
         if (!privilegedApp) {
             // non-privileged applications can never define a priority >0
             if (DEBUG_FILTERS) {
                 Slog.i(TAG, "Non-privileged app; cap priority to 0;"
-                        + " package: " + pkg.getPackageName()
-                        + " activity: " + intent.getClassName()
+                        + " package: " + packageName
+                        + " activity: " + className
                         + " origPrio: " + intent.getPriority());
             }
             intent.setPriority(0);
@@ -854,11 +853,11 @@
                     if (mProtectedFilters == null) {
                         mProtectedFilters = new ArrayList<>();
                     }
-                    mProtectedFilters.add(intent);
+                    mProtectedFilters.add(Pair.create(activity, intent));
                     if (DEBUG_FILTERS) {
                         Slog.i(TAG, "Protected action; save for later;"
-                                + " package: " + pkg.getPackageName()
-                                + " activity: " + intent.getClassName()
+                                + " package: " + packageName
+                                + " activity: " + className
                                 + " origPrio: " + intent.getPriority());
                     }
                     return;
@@ -867,12 +866,12 @@
                         Slog.i(TAG, "No setup wizard;"
                                 + " All protected intents capped to priority 0");
                     }
-                    if (intent.getPackageName().equals(setupWizardPackage)) {
+                    if (packageName.equals(setupWizardPackage)) {
                         if (DEBUG_FILTERS) {
                             Slog.i(TAG, "Found setup wizard;"
                                     + " allow priority " + intent.getPriority() + ";"
-                                    + " package: " + intent.getPackageName()
-                                    + " activity: " + intent.getClassName()
+                                    + " package: " + packageName
+                                    + " activity: " + className
                                     + " priority: " + intent.getPriority());
                         }
                         // setup wizard gets whatever it wants
@@ -880,8 +879,8 @@
                     }
                     if (DEBUG_FILTERS) {
                         Slog.i(TAG, "Protected action; cap priority to 0;"
-                                + " package: " + intent.getPackageName()
-                                + " activity: " + intent.getClassName()
+                                + " package: " + packageName
+                                + " activity: " + className
                                 + " origPrio: " + intent.getPriority());
                     }
                     intent.setPriority(0);
@@ -894,27 +893,13 @@
 
         // privileged app unbundled update ... try to find the same activity
 
-        ParsedActivity foundActivity = null;
-        ParsedActivity activity = null;
-
-        if (pkg.getActivities() != null) {
-            for (ParsedActivity parsedProvider : pkg.getActivities()) {
-                if (Objects.equals(parsedProvider.className, intent.getClassName())) {
-                    activity = parsedProvider;
-                }
-            }
-        }
-
-        if (activity != null) {
-            foundActivity = findMatchingActivity(systemActivities, activity);
-        }
-
+        ParsedActivity foundActivity = findMatchingActivity(systemActivities, activity);
         if (foundActivity == null) {
             // this is a new activity; it cannot obtain >0 priority
             if (DEBUG_FILTERS) {
                 Slog.i(TAG, "New activity; cap priority to 0;"
-                        + " package: " + pkg.getPackageName()
-                        + " activity: " + intent.getClassName()
+                        + " package: " + packageName
+                        + " activity: " + className
                         + " origPrio: " + intent.getPriority());
             }
             intent.setPriority(0);
@@ -924,8 +909,8 @@
         // found activity, now check for filter equivalence
 
         // a shallow copy is enough; we modify the list, not its contents
-        final List<ParsedActivityIntentInfo> intentListCopy =
-                new ArrayList<>(foundActivity.intents);
+        final List<ParsedIntentInfo> intentListCopy =
+                new ArrayList<>(foundActivity.getIntents());
 
         // find matching action subsets
         final Iterator<String> actionsIterator = intent.actionsIterator();
@@ -935,8 +920,8 @@
                 // no more intents to match; we're not equivalent
                 if (DEBUG_FILTERS) {
                     Slog.i(TAG, "Mismatched action; cap priority to 0;"
-                            + " package: " + pkg.getPackageName()
-                            + " activity: " + intent.getClassName()
+                            + " package: " + packageName
+                            + " activity: " + className
                             + " origPrio: " + intent.getPriority());
                 }
                 intent.setPriority(0);
@@ -953,8 +938,8 @@
                 // no more intents to match; we're not equivalent
                 if (DEBUG_FILTERS) {
                     Slog.i(TAG, "Mismatched category; cap priority to 0;"
-                            + " package: " + pkg.getPackageName()
-                            + " activity: " + intent.getClassName()
+                            + " package: " + packageName
+                            + " activity: " + className
                             + " origPrio: " + intent.getPriority());
                 }
                 intent.setPriority(0);
@@ -970,8 +955,8 @@
                 // no more intents to match; we're not equivalent
                 if (DEBUG_FILTERS) {
                     Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
-                            + " package: " + pkg.getPackageName()
-                            + " activity: " + intent.getClassName()
+                            + " package: " + packageName
+                            + " activity: " + className
                             + " origPrio: " + intent.getPriority());
                 }
                 intent.setPriority(0);
@@ -989,8 +974,8 @@
                 // no more intents to match; we're not equivalent
                 if (DEBUG_FILTERS) {
                     Slog.i(TAG, "Mismatched authority; cap priority to 0;"
-                            + " package: " + pkg.getPackageName()
-                            + " activity: " + intent.getClassName()
+                            + " package: " + packageName
+                            + " activity: " + className
                             + " origPrio: " + intent.getPriority());
                 }
                 intent.setPriority(0);
@@ -1007,8 +992,8 @@
             if (DEBUG_FILTERS) {
                 Slog.i(TAG, "Found matching filter(s);"
                         + " cap priority to " + cappedPriority + ";"
-                        + " package: " + pkg.getPackageName()
-                        + " activity: " + intent.getClassName()
+                        + " package: " + packageName
+                        + " activity: " + className
                         + " origPrio: " + intent.getPriority());
             }
             intent.setPriority(cappedPriority);
@@ -1142,8 +1127,109 @@
         }
     }
 
+    private abstract static class MimeGroupsAwareIntentResolver<F extends Pair<?
+            extends ParsedComponent, ParsedIntentInfo>, R>
+            extends IntentResolver<F, R> {
+        private ArrayMap<String, F[]> mMimeGroupToFilter = new ArrayMap<>();
+        private boolean mIsUpdatingMimeGroup = false;
+
+        @Override
+        public void addFilter(F f) {
+            IntentFilter intentFilter = getIntentFilter(f);
+            applyMimeGroups(f);
+            super.addFilter(f);
+
+            if (!mIsUpdatingMimeGroup) {
+                register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
+                        "      MimeGroup: ");
+            }
+        }
+
+        @Override
+        protected void removeFilterInternal(F f) {
+            IntentFilter intentFilter = getIntentFilter(f);
+            if (!mIsUpdatingMimeGroup) {
+                unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
+                        "      MimeGroup: ");
+            }
+
+            super.removeFilterInternal(f);
+            intentFilter.clearDynamicDataTypes();
+        }
+
+        /**
+         * Updates MIME group by applying changes to all IntentFilters
+         * that contain the group and repopulating m*ToFilter maps accordingly
+         *
+         * @param packageName package to which MIME group belongs
+         * @param mimeGroup MIME group to update
+         * @return true, if any intent filters were changed due to this update
+         */
+        public boolean updateMimeGroup(String packageName, String mimeGroup) {
+            F[] filters = mMimeGroupToFilter.get(mimeGroup);
+            int n = filters != null ? filters.length : 0;
+
+            mIsUpdatingMimeGroup = true;
+            boolean hasChanges = false;
+            F filter;
+            for (int i = 0; i < n && (filter = filters[i]) != null; i++) {
+                if (isPackageForFilter(packageName, filter)) {
+                    hasChanges |= updateFilter(filter);
+                }
+            }
+            mIsUpdatingMimeGroup = false;
+            return hasChanges;
+        }
+
+        private boolean updateFilter(F f) {
+            IntentFilter filter = getIntentFilter(f);
+            List<String> oldTypes = filter.dataTypes();
+            removeFilter(f);
+            addFilter(f);
+            List<String> newTypes = filter.dataTypes();
+            return !equalLists(oldTypes, newTypes);
+        }
+
+        private boolean equalLists(List<String> first, List<String> second) {
+            if (first == null) {
+                return second == null;
+            } else if (second == null) {
+                return false;
+            }
+
+            if (first.size() != second.size()) {
+                return false;
+            }
+
+            Collections.sort(first);
+            Collections.sort(second);
+            return first.equals(second);
+        }
+
+        private void applyMimeGroups(F f) {
+            IntentFilter filter = getIntentFilter(f);
+
+            for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
+                List<String> mimeTypes = sPackageManagerInternal.getMimeGroup(
+                        f.first.getPackageName(), filter.getMimeGroup(i));
+
+                for (int typeIndex = mimeTypes.size() - 1; typeIndex >= 0; typeIndex--) {
+                    String mimeType = mimeTypes.get(typeIndex);
+
+                    try {
+                        filter.addDynamicDataType(mimeType);
+                    } catch (IntentFilter.MalformedMimeTypeException e) {
+                        if (DEBUG) {
+                            Slog.w(TAG, "Malformed mime type: " + mimeType, e);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private static class ActivityIntentResolver
-            extends IntentResolver<ParsedActivityIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
 
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
@@ -1154,11 +1240,12 @@
         }
 
         List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
+                int privateResolveFlags, int userId) {
             if (!sUserManager.exists(userId)) {
                 return null;
             }
             mFlags = flags;
+            mPrivateResolveFlags = privateResolveFlags;
             return super.queryIntent(intent, resolvedType,
                     (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
                     userId);
@@ -1175,15 +1262,18 @@
             mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int activitiesSize = packageActivities.size();
-            ArrayList<ParsedActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize);
+            ArrayList<Pair<ParsedActivity, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(activitiesSize);
 
-            List<ParsedActivityIntentInfo> intentFilters;
+            List<ParsedIntentInfo> intentFilters;
             for (int i = 0; i < activitiesSize; ++i) {
-                intentFilters = packageActivities.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    ParsedActivityIntentInfo[] array =
-                            new ParsedActivityIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
+                ParsedActivity activity = packageActivities.get(i);
+                intentFilters = activity.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedActivity, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(activity, intentFilters.get(arrayIndex));
+                    }
                     listCut.add(array);
                 }
             }
@@ -1191,22 +1281,17 @@
         }
 
         private void addActivity(ParsedActivity a, String type,
-                List<ParsedActivityIntentInfo> newIntents) {
+                List<Pair<ParsedActivity, ParsedIntentInfo>> newIntents) {
             mActivities.put(a.getComponentName(), a);
             if (DEBUG_SHOW_INFO) {
-                final CharSequence label = a.nonLocalizedLabel != null
-                        ? a.nonLocalizedLabel
-                        : a.getName();
-                Log.v(TAG, "  " + type + " " + label + ":");
-            }
-            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + type + ":");
                 Log.v(TAG, "    Class=" + a.getName());
             }
-            final int intentsSize = a.intents.size();
+            final int intentsSize = a.getIntents().size();
             for (int j = 0; j < intentsSize; j++) {
-                ParsedActivityIntentInfo intent = a.intents.get(j);
+                ParsedIntentInfo intent = a.getIntents().get(j);
                 if (newIntents != null && "activity".equals(type)) {
-                    newIntents.add(intent);
+                    newIntents.add(Pair.create(a, intent));
                 }
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
@@ -1215,36 +1300,34 @@
                 if (!intent.debugCheck()) {
                     Log.w(TAG, "==> For Activity " + a.getName());
                 }
-                addFilter(intent);
+                addFilter(Pair.create(a, intent));
             }
         }
 
         private void removeActivity(ParsedActivity a, String type) {
             mActivities.remove(a.getComponentName());
             if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + type + " "
-                        + (a.nonLocalizedLabel != null ? a.nonLocalizedLabel
-                                : a.getName()) + ":");
+                Log.v(TAG, "  " + type + ":");
                 Log.v(TAG, "    Class=" + a.getName());
             }
-            final int intentsSize = a.intents.size();
+            final int intentsSize = a.getIntents().size();
             for (int j = 0; j < intentsSize; j++) {
-                ParsedActivityIntentInfo intent = a.intents.get(j);
+                ParsedIntentInfo intent = a.getIntents().get(j);
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
                 }
-                removeFilter(intent);
+                removeFilter(Pair.create(a, intent));
             }
         }
 
         @Override
-        protected boolean allowFilterResult(
-                ParsedActivityIntentInfo filter, List<ResolveInfo> dest) {
+        protected boolean allowFilterResult(Pair<ParsedActivity, ParsedIntentInfo> filter,
+                List<ResolveInfo> dest) {
             for (int i = dest.size() - 1; i >= 0; --i) {
                 ActivityInfo destAi = dest.get(i).activityInfo;
-                if (Objects.equals(destAi.name, filter.getClassName())
-                        && Objects.equals(destAi.packageName, filter.getPackageName())) {
+                if (Objects.equals(destAi.name, filter.first.getName())
+                        && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
                     return false;
                 }
             }
@@ -1252,39 +1335,23 @@
         }
 
         @Override
-        protected ParsedActivityIntentInfo[] newArray(int size) {
-            return new ParsedActivityIntentInfo[size];
+        protected Pair<ParsedActivity, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedActivity, ParsedIntentInfo>[]) new Pair<?, ?>[size];
         }
 
         @Override
-        protected boolean isFilterStopped(ParsedActivityIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg == null) {
-                return false;
-            }
-
-            PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
-            if (ps == null) {
-                return false;
-            }
-
-            // System apps are never considered stopped for purposes of
-            // filtering, because there may be no way for the user to
-            // actually re-launch them.
-            return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                    && ps.getStopped(userId);
+        protected boolean isFilterStopped(Pair<ParsedActivity, ParsedIntentInfo> filter, int userId) {
+            return ComponentResolver.isFilterStopped(filter, userId);
         }
 
         @Override
         protected boolean isPackageForFilter(String packageName,
-                ParsedActivityIntentInfo info) {
-            return packageName.equals(info.getPackageName());
+                Pair<ParsedActivity, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
         }
 
-        private void log(String reason, ParsedActivityIntentInfo info, int match,
+        private void log(String reason, ParsedIntentInfo info, int match,
                 int userId) {
             Slog.w(TAG, reason
                     + "; match: "
@@ -1294,8 +1361,11 @@
         }
 
         @Override
-        protected ResolveInfo newResult(ParsedActivityIntentInfo info,
+        protected ResolveInfo newResult(Pair<ParsedActivity, ParsedIntentInfo> pair,
                 int match, int userId) {
+            ParsedActivity activity = pair.first;
+            ParsedIntentInfo info = pair.second;
+
             if (!sUserManager.exists(userId)) {
                 if (DEBUG) {
                     log("User doesn't exist", info, match, userId);
@@ -1303,27 +1373,11 @@
                 return null;
             }
 
-            ParsedActivity activity = null;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(info.getPackageName());
+            AndroidPackage pkg = sPackageManagerInternal.getPackage(activity.getPackageName());
             if (pkg == null) {
                 return null;
             }
 
-            // TODO(b/135203078): Consider more efficient ways of doing this.
-            List<ParsedActivity> activities = getResolveList(pkg);
-            if (activities != null) {
-                for (ParsedActivity parsedActivity : activities) {
-                    if (Objects.equals(parsedActivity.className, info.getClassName())) {
-                        activity = parsedActivity;
-                    }
-                }
-            }
-
-            if (activity == null) {
-                return null;
-            }
-
             if (!sPackageManagerInternal.isEnabledAndMatches(activity, mFlags, userId)) {
                 if (DEBUG) {
                     log("!PackageManagerInternal.isEnabledAndMatches; mFlags="
@@ -1333,7 +1387,7 @@
                 return null;
             }
             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    info.getPackageName());
+                    activity.getPackageName());
             if (ps == null) {
                 if (DEBUG) {
                     log("info.activity.owner.mExtras == null", info, match, userId);
@@ -1341,8 +1395,8 @@
                 return null;
             }
             final PackageUserState userState = ps.readUserState(userId);
-            ActivityInfo ai =
-                    PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags, userState, userId);
+            ActivityInfo ai = PackageInfoUtils.generateActivityInfo(pkg, activity, mFlags,
+                    userState, userId, ps);
             if (ai == null) {
                 if (DEBUG) {
                     log("Failed to create ActivityInfo based on " + activity, info, match,
@@ -1388,6 +1442,11 @@
                 }
                 return null;
             }
+            final boolean matchNonBrowserOnly =
+                    (mPrivateResolveFlags & PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY) != 0;
+            if (matchNonBrowserOnly && info.handleAllWebDataURI()) {
+                return null;
+            }
             final ResolveInfo res = new ResolveInfo();
             res.activityInfo = ai;
             if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
@@ -1395,19 +1454,20 @@
             }
             res.handleAllWebDataURI = info.handleAllWebDataURI();
             res.priority = info.getPriority();
-            res.preferredOrder = pkg.getPreferredOrder();
+            // TODO(b/135203078): This field was unwritten and does nothing
+//            res.preferredOrder = pkg.getPreferredOrder();
             //System.out.println("Result: " + res.activityInfo.className +
             //                   " = " + res.priority);
             res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            res.isDefault = info.isHasDefault();
+            res.labelRes = info.getLabelRes();
+            res.nonLocalizedLabel = info.getNonLocalizedLabel();
             if (sPackageManagerInternal.userNeedsBadging(userId)) {
                 res.noResourceId = true;
             } else {
-                res.icon = info.icon;
+                res.icon = info.getIcon();
             }
-            res.iconResourceId = info.icon;
+            res.iconResourceId = info.getIcon();
             res.system = res.activityInfo.applicationInfo.isSystemApp();
             res.isInstantAppAvailable = userState.instantApp;
             return res;
@@ -1420,43 +1480,44 @@
 
         @Override
         protected void dumpFilter(PrintWriter out, String prefix,
-                ParsedActivityIntentInfo filter) {
-            ParsedActivity activity = null;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg != null && pkg.getActivities() != null) {
-                for (ParsedActivity parsedActivity : pkg.getActivities()) {
-                    if (Objects.equals(parsedActivity.className, filter.getClassName())) {
-                        activity = parsedActivity;
-                    }
-                }
-            }
+                Pair<ParsedActivity, ParsedIntentInfo> pair) {
+            ParsedActivity activity = pair.first;
+            ParsedIntentInfo filter = pair.second;
 
             out.print(prefix);
             out.print(Integer.toHexString(System.identityHashCode(activity)));
             out.print(' ');
-            ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName());
+            ComponentName.printShortString(out, activity.getPackageName(),
+                    activity.getClassName());
             out.print(" filter ");
             out.println(Integer.toHexString(System.identityHashCode(filter)));
         }
 
         @Override
-        protected Object filterToLabel(ParsedActivityIntentInfo filter) {
+        protected Object filterToLabel(Pair<ParsedActivity, ParsedIntentInfo> filter) {
             return filter;
         }
 
         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            ParsedActivityIntentInfo activity = (ParsedActivityIntentInfo) label;
+            @SuppressWarnings("unchecked") Pair<ParsedActivity, ParsedIntentInfo> pair =
+                    (Pair<ParsedActivity, ParsedIntentInfo>) label;
             out.print(prefix);
-            out.print(Integer.toHexString(System.identityHashCode(activity)));
+            out.print(Integer.toHexString(System.identityHashCode(pair.first)));
             out.print(' ');
-            ComponentName.printShortString(out, activity.getPackageName(), activity.getClassName());
+            ComponentName.printShortString(out, pair.first.getPackageName(),
+                    pair.first.getClassName());
             if (count > 1) {
                 out.print(" ("); out.print(count); out.print(" filters)");
             }
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedActivity, ParsedIntentInfo> input) {
+            return input.second;
+        }
+
         protected List<ParsedActivity> getResolveList(AndroidPackage pkg) {
             return pkg.getActivities();
         }
@@ -1465,6 +1526,7 @@
         private final ArrayMap<ComponentName, ParsedActivity> mActivities =
                 new ArrayMap<>();
         private int mFlags;
+        private int mPrivateResolveFlags;
     }
 
     // Both receivers and activities share a class, but point to different get methods
@@ -1477,7 +1539,7 @@
     }
 
     private static final class ProviderIntentResolver
-            extends IntentResolver<ParsedProviderIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                 boolean defaultOnly, int userId) {
@@ -1509,15 +1571,18 @@
             mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int providersSize = packageProviders.size();
-            ArrayList<ParsedProviderIntentInfo[]> listCut = new ArrayList<>(providersSize);
+            ArrayList<Pair<ParsedProvider, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(providersSize);
 
-            List<ParsedProviderIntentInfo> intentFilters;
+            List<ParsedIntentInfo> intentFilters;
             for (int i = 0; i < providersSize; ++i) {
-                intentFilters = packageProviders.get(i).getIntents();
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    ParsedProviderIntentInfo[] array =
-                            new ParsedProviderIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
+                ParsedProvider provider = packageProviders.get(i);
+                intentFilters = provider.getIntents();
+                if (!intentFilters.isEmpty()) {
+                    Pair<ParsedProvider, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(provider, intentFilters.get(arrayIndex));
+                    }
                     listCut.add(array);
                 }
             }
@@ -1532,17 +1597,13 @@
 
             mProviders.put(p.getComponentName(), p);
             if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (p.nonLocalizedLabel != null
-                                ? p.nonLocalizedLabel
-                                : p.getName())
-                        + ":");
+                Log.v(TAG, "  provider:");
                 Log.v(TAG, "    Class=" + p.getName());
             }
             final int intentsSize = p.getIntents().size();
             int j;
             for (j = 0; j < intentsSize; j++) {
-                ParsedProviderIntentInfo intent = p.getIntents().get(j);
+                ParsedIntentInfo intent = p.getIntents().get(j);
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
@@ -1550,37 +1611,35 @@
                 if (!intent.debugCheck()) {
                     Log.w(TAG, "==> For Provider " + p.getName());
                 }
-                addFilter(intent);
+                addFilter(Pair.create(p, intent));
             }
         }
 
         void removeProvider(ParsedProvider p) {
             mProviders.remove(p.getComponentName());
             if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (p.nonLocalizedLabel != null
-                        ? p.nonLocalizedLabel
-                        : p.getName()) + ":");
+                Log.v(TAG, "  provider:");
                 Log.v(TAG, "    Class=" + p.getName());
             }
             final int intentsSize = p.getIntents().size();
             int j;
             for (j = 0; j < intentsSize; j++) {
-                ParsedProviderIntentInfo intent = p.getIntents().get(j);
+                ParsedIntentInfo intent = p.getIntents().get(j);
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
                 }
-                removeFilter(intent);
+                removeFilter(Pair.create(p, intent));
             }
         }
 
         @Override
-        protected boolean allowFilterResult(
-                ParsedProviderIntentInfo filter, List<ResolveInfo> dest) {
+        protected boolean allowFilterResult(Pair<ParsedProvider, ParsedIntentInfo> filter,
+                List<ResolveInfo> dest) {
             for (int i = dest.size() - 1; i >= 0; i--) {
                 ProviderInfo destPi = dest.get(i).providerInfo;
-                if (Objects.equals(destPi.name, filter.getClassName())
-                        && Objects.equals(destPi.packageName, filter.getPackageName())) {
+                if (Objects.equals(destPi.name, filter.first.getClassName())
+                        && Objects.equals(destPi.packageName, filter.first.getPackageName())) {
                     return false;
                 }
             }
@@ -1588,59 +1647,35 @@
         }
 
         @Override
-        protected ParsedProviderIntentInfo[] newArray(int size) {
-            return new ParsedProviderIntentInfo[size];
+        protected Pair<ParsedProvider, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedProvider, ParsedIntentInfo>[]) new Pair<?, ?>[size];
         }
 
         @Override
-        protected boolean isFilterStopped(ParsedProviderIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) {
-                return true;
-            }
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg == null) {
-                return false;
-            }
-
-            PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
-            if (ps == null) {
-                return false;
-            }
-
-            // System apps are never considered stopped for purposes of
-            // filtering, because there may be no way for the user to
-            // actually re-launch them.
-            return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                    && ps.getStopped(userId);
+        protected boolean isFilterStopped(Pair<ParsedProvider, ParsedIntentInfo> filter,
+                int userId) {
+            return ComponentResolver.isFilterStopped(filter, userId);
         }
 
         @Override
         protected boolean isPackageForFilter(String packageName,
-                ParsedProviderIntentInfo info) {
-            return packageName.equals(info.getPackageName());
+                Pair<ParsedProvider, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
         }
 
         @Override
-        protected ResolveInfo newResult(ParsedProviderIntentInfo filter,
+        protected ResolveInfo newResult(Pair<ParsedProvider, ParsedIntentInfo> pair,
                 int match, int userId) {
             if (!sUserManager.exists(userId)) {
                 return null;
             }
 
-            ParsedProvider provider = null;
+            ParsedProvider provider = pair.first;
+            ParsedIntentInfo filter = pair.second;
 
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg != null && pkg.getProviders() != null) {
-                for (ParsedProvider parsedProvider : pkg.getProviders()) {
-                    if (Objects.equals(parsedProvider.className, filter.getClassName())) {
-                        provider = parsedProvider;
-                    }
-                }
-            }
-
-            if (provider == null) {
+            AndroidPackage pkg = sPackageManagerInternal.getPackage(provider.getPackageName());
+            if (pkg == null) {
                 return null;
             }
 
@@ -1649,7 +1684,7 @@
             }
 
             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
+                    provider.getPackageName());
             if (ps == null) {
                 return null;
             }
@@ -1671,8 +1706,8 @@
             if (userState.instantApp && ps.isUpdateAvailable()) {
                 return null;
             }
-            ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider,
-                    mFlags, userState, userId);
+            ProviderInfo pi = PackageInfoUtils.generateProviderInfo(pkg, provider, mFlags,
+                    userState, userId, ps);
             if (pi == null) {
                 return null;
             }
@@ -1682,12 +1717,13 @@
                 res.filter = filter;
             }
             res.priority = filter.getPriority();
-            res.preferredOrder = pkg.getPreferredOrder();
+            // TODO(b/135203078): This field was unwritten and does nothing
+//            res.preferredOrder = pkg.getPreferredOrder();
             res.match = match;
-            res.isDefault = filter.hasDefault;
-            res.labelRes = filter.labelRes;
-            res.nonLocalizedLabel = filter.nonLocalizedLabel;
-            res.icon = filter.icon;
+            res.isDefault = filter.isHasDefault();
+            res.labelRes = filter.getLabelRes();
+            res.nonLocalizedLabel = filter.getNonLocalizedLabel();
+            res.icon = filter.getIcon();
             res.system = res.providerInfo.applicationInfo.isSystemApp();
             return res;
         }
@@ -1699,37 +1735,31 @@
 
         @Override
         protected void dumpFilter(PrintWriter out, String prefix,
-                ParsedProviderIntentInfo filter) {
-            ParsedProvider provider = null;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg != null && pkg.getProviders() != null) {
-                for (ParsedProvider parsedProvider : pkg.getProviders()) {
-                    if (Objects.equals(parsedProvider.className, filter.getClassName())) {
-                        provider = parsedProvider;
-                    }
-                }
-            }
+                Pair<ParsedProvider, ParsedIntentInfo> pair) {
+            ParsedProvider provider = pair.first;
+            ParsedIntentInfo filter = pair.second;
 
             out.print(prefix);
             out.print(Integer.toHexString(System.identityHashCode(provider)));
             out.print(' ');
-            ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName());
+            ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName());
             out.print(" filter ");
             out.println(Integer.toHexString(System.identityHashCode(filter)));
         }
 
         @Override
-        protected Object filterToLabel(ParsedProviderIntentInfo filter) {
+        protected Object filterToLabel(Pair<ParsedProvider, ParsedIntentInfo> filter) {
             return filter;
         }
 
         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            final ParsedProviderIntentInfo provider = (ParsedProviderIntentInfo) label;
+            @SuppressWarnings("unchecked") final Pair<ParsedProvider, ParsedIntentInfo> pair =
+                    (Pair<ParsedProvider, ParsedIntentInfo>) label;
             out.print(prefix);
-            out.print(Integer.toHexString(System.identityHashCode(provider)));
+            out.print(Integer.toHexString(System.identityHashCode(pair.first)));
             out.print(' ');
-            ComponentName.printShortString(out, provider.getPackageName(), provider.getClassName());
+            ComponentName.printShortString(out, pair.first.getPackageName(),
+                    pair.first.getClassName());
             if (count > 1) {
                 out.print(" (");
                 out.print(count);
@@ -1738,12 +1768,18 @@
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedProvider, ParsedIntentInfo> input) {
+            return input.second;
+        }
+
         private final ArrayMap<ComponentName, ParsedProvider> mProviders = new ArrayMap<>();
         private int mFlags;
     }
 
     private static final class ServiceIntentResolver
-            extends IntentResolver<ParsedServiceIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                 boolean defaultOnly, int userId) {
@@ -1769,15 +1805,18 @@
             mFlags = flags;
             final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
             final int servicesSize = packageServices.size();
-            ArrayList<ParsedServiceIntentInfo[]> listCut = new ArrayList<>(servicesSize);
+            ArrayList<Pair<ParsedService, ParsedIntentInfo>[]> listCut =
+                    new ArrayList<>(servicesSize);
 
-            List<ParsedServiceIntentInfo> intentFilters;
+            List<ParsedIntentInfo> intentFilters;
             for (int i = 0; i < servicesSize; ++i) {
-                intentFilters = packageServices.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    ParsedServiceIntentInfo[] array =
-                            new ParsedServiceIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
+                ParsedService service = packageServices.get(i);
+                intentFilters = service.getIntents();
+                if (intentFilters.size() > 0) {
+                    Pair<ParsedService, ParsedIntentInfo>[] array = newArray(intentFilters.size());
+                    for (int arrayIndex = 0; arrayIndex < intentFilters.size(); arrayIndex++) {
+                        array[arrayIndex] = Pair.create(service, intentFilters.get(arrayIndex));
+                    }
                     listCut.add(array);
                 }
             }
@@ -1787,15 +1826,13 @@
         void addService(ParsedService s) {
             mServices.put(s.getComponentName(), s);
             if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (s.nonLocalizedLabel != null
-                        ? s.nonLocalizedLabel : s.getName()) + ":");
+                Log.v(TAG, "  service:");
                 Log.v(TAG, "    Class=" + s.getName());
             }
-            final int intentsSize = s.intents.size();
+            final int intentsSize = s.getIntents().size();
             int j;
             for (j = 0; j < intentsSize; j++) {
-                ParsedServiceIntentInfo intent = s.intents.get(j);
+                ParsedIntentInfo intent = s.getIntents().get(j);
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
@@ -1803,36 +1840,35 @@
                 if (!intent.debugCheck()) {
                     Log.w(TAG, "==> For Service " + s.getName());
                 }
-                addFilter(intent);
+                addFilter(Pair.create(s, intent));
             }
         }
 
         void removeService(ParsedService s) {
             mServices.remove(s.getComponentName());
             if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (s.nonLocalizedLabel != null
-                        ? s.nonLocalizedLabel : s.getName()) + ":");
+                Log.v(TAG, "  service:");
                 Log.v(TAG, "    Class=" + s.getName());
             }
-            final int intentsSize = s.intents.size();
+            final int intentsSize = s.getIntents().size();
             int j;
             for (j = 0; j < intentsSize; j++) {
-                ParsedServiceIntentInfo intent = s.intents.get(j);
+                ParsedIntentInfo intent = s.getIntents().get(j);
                 if (DEBUG_SHOW_INFO) {
                     Log.v(TAG, "    IntentFilter:");
                     intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
                 }
-                removeFilter(intent);
+                removeFilter(Pair.create(s, intent));
             }
         }
 
         @Override
-        protected boolean allowFilterResult(
-                ParsedServiceIntentInfo filter, List<ResolveInfo> dest) {
+        protected boolean allowFilterResult(Pair<ParsedService, ParsedIntentInfo> filter,
+                List<ResolveInfo> dest) {
             for (int i = dest.size() - 1; i >= 0; --i) {
                 ServiceInfo destAi = dest.get(i).serviceInfo;
-                if (Objects.equals(destAi.name, filter.getClassName())
-                        && Objects.equals(destAi.packageName, filter.getPackageName())) {
+                if (Objects.equals(destAi.name, filter.first.getClassName())
+                        && Objects.equals(destAi.packageName, filter.first.getPackageName())) {
                     return false;
                 }
             }
@@ -1840,55 +1876,32 @@
         }
 
         @Override
-        protected ParsedServiceIntentInfo[] newArray(int size) {
-            return new ParsedServiceIntentInfo[size];
+        protected Pair<ParsedService, ParsedIntentInfo>[] newArray(int size) {
+            //noinspection unchecked
+            return (Pair<ParsedService, ParsedIntentInfo>[]) new Pair<?, ?>[size];
         }
 
         @Override
-        protected boolean isFilterStopped(ParsedServiceIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg == null) {
-                return false;
-            }
-
-            PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
-            if (ps == null) {
-                return false;
-            }
-
-            // System apps are never considered stopped for purposes of
-            // filtering, because there may be no way for the user to
-            // actually re-launch them.
-            return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                    && ps.getStopped(userId);
+        protected boolean isFilterStopped(Pair<ParsedService, ParsedIntentInfo> filter, int userId) {
+            return ComponentResolver.isFilterStopped(filter, userId);
         }
 
         @Override
         protected boolean isPackageForFilter(String packageName,
-                ParsedServiceIntentInfo info) {
-            return packageName.equals(info.getPackageName());
+                Pair<ParsedService, ParsedIntentInfo> info) {
+            return packageName.equals(info.first.getPackageName());
         }
 
         @Override
-        protected ResolveInfo newResult(ParsedServiceIntentInfo filter,
-                int match, int userId) {
+        protected ResolveInfo newResult(Pair<ParsedService, ParsedIntentInfo> pair, int match,
+                int userId) {
             if (!sUserManager.exists(userId)) return null;
 
-            ParsedService service = null;
+            ParsedService service = pair.first;
+            ParsedIntentInfo filter = pair.second;
 
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg != null && pkg.getServices() != null) {
-                for (ParsedService parsedService : pkg.getServices()) {
-                    if (Objects.equals(parsedService.className, filter.getClassName())) {
-                        service = parsedService;
-                    }
-                }
-            }
-
-            if (service == null) {
+            AndroidPackage pkg = sPackageManagerInternal.getPackage(service.getPackageName());
+            if (pkg == null) {
                 return null;
             }
 
@@ -1897,13 +1910,13 @@
             }
 
             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
+                    service.getPackageName());
             if (ps == null) {
                 return null;
             }
             final PackageUserState userState = ps.readUserState(userId);
             ServiceInfo si = PackageInfoUtils.generateServiceInfo(pkg, service, mFlags,
-                    userState, userId);
+                    userState, userId, ps);
             if (si == null) {
                 return null;
             }
@@ -1930,12 +1943,13 @@
                 res.filter = filter;
             }
             res.priority = filter.getPriority();
-            res.preferredOrder = pkg.getPreferredOrder();
+            // TODO(b/135203078): This field was unwritten and does nothing
+//            res.preferredOrder = pkg.getPreferredOrder();
             res.match = match;
-            res.isDefault = filter.hasDefault;
-            res.labelRes = filter.labelRes;
-            res.nonLocalizedLabel = filter.nonLocalizedLabel;
-            res.icon = filter.icon;
+            res.isDefault = filter.isHasDefault();
+            res.labelRes = filter.getLabelRes();
+            res.nonLocalizedLabel = filter.getNonLocalizedLabel();
+            res.icon = filter.getIcon();
             res.system = res.serviceInfo.applicationInfo.isSystemApp();
             return res;
         }
@@ -1947,25 +1961,17 @@
 
         @Override
         protected void dumpFilter(PrintWriter out, String prefix,
-                ParsedServiceIntentInfo filter) {
-            ParsedService service = null;
-
-            AndroidPackage pkg = sPackageManagerInternal.getPackage(filter.getPackageName());
-            if (pkg != null && pkg.getServices() != null) {
-                for (ParsedService parsedService : pkg.getServices()) {
-                    if (Objects.equals(parsedService.className, filter.getClassName())) {
-                        service = parsedService;
-                    }
-                }
-            }
+                Pair<ParsedService, ParsedIntentInfo> pair) {
+            ParsedService service = pair.first;
+            ParsedIntentInfo filter = pair.second;
 
             out.print(prefix);
             out.print(Integer.toHexString(System.identityHashCode(service)));
             out.print(' ');
-            ComponentName.printShortString(out, filter.getPackageName(), filter.getClassName());
+            ComponentName.printShortString(out, service.getPackageName(), service.getClassName());
             out.print(" filter ");
             out.print(Integer.toHexString(System.identityHashCode(filter)));
-            if (service != null && service.getPermission() != null) {
+            if (service.getPermission() != null) {
                 out.print(" permission "); out.println(service.getPermission());
             } else {
                 out.println();
@@ -1973,22 +1979,30 @@
         }
 
         @Override
-        protected Object filterToLabel(ParsedServiceIntentInfo filter) {
+        protected Object filterToLabel(Pair<ParsedService, ParsedIntentInfo> filter) {
             return filter;
         }
 
         protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            final ParsedServiceIntentInfo service = (ParsedServiceIntentInfo) label;
+            @SuppressWarnings("unchecked") final Pair<ParsedService, ParsedIntentInfo> pair =
+                    (Pair<ParsedService, ParsedIntentInfo>) label;
             out.print(prefix);
-            out.print(Integer.toHexString(System.identityHashCode(service)));
+            out.print(Integer.toHexString(System.identityHashCode(pair.first)));
             out.print(' ');
-            ComponentName.printShortString(out, service.getPackageName(), service.getClassName());
+            ComponentName.printShortString(out, pair.first.getPackageName(),
+                    pair.first.getClassName());
             if (count > 1) {
                 out.print(" ("); out.print(count); out.print(" filters)");
             }
             out.println();
         }
 
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull Pair<ParsedService, ParsedIntentInfo> input) {
+            return input.second;
+        }
+
         // Keys are String (activity class name), values are Activity.
         private final ArrayMap<ComponentName, ParsedService> mServices = new ArrayMap<>();
         private int mFlags;
@@ -2075,11 +2089,40 @@
                 i--;
             }
         }
+
+        @Override
+        protected IntentFilter getIntentFilter(
+                @NonNull AuxiliaryResolveInfo.AuxiliaryFilter input) {
+            return input;
+        }
+    }
+
+    private static boolean isFilterStopped(Pair<? extends ParsedComponent, ParsedIntentInfo> pair,
+            int userId) {
+        if (!sUserManager.exists(userId)) {
+            return true;
+        }
+
+        AndroidPackage pkg = sPackageManagerInternal.getPackage(pair.first.getPackageName());
+        if (pkg == null) {
+            return false;
+        }
+
+        PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
+                pair.first.getPackageName());
+        if (ps == null) {
+            return false;
+        }
+
+        // System apps are never considered stopped for purposes of
+        // filtering, because there may be no way for the user to
+        // actually re-launch them.
+        return !ps.isSystem() && ps.getStopped(userId);
     }
 
     /** Generic to create an {@link Iterator} for a data type */
     static class IterGenerator<E> {
-        public Iterator<E> generate(ParsedActivityIntentInfo info) {
+        public Iterator<E> generate(ParsedIntentInfo info) {
             return null;
         }
     }
@@ -2087,7 +2130,7 @@
     /** Create an {@link Iterator} for intent actions */
     static class ActionIterGenerator extends IterGenerator<String> {
         @Override
-        public Iterator<String> generate(ParsedActivityIntentInfo info) {
+        public Iterator<String> generate(ParsedIntentInfo info) {
             return info.actionsIterator();
         }
     }
@@ -2095,7 +2138,7 @@
     /** Create an {@link Iterator} for intent categories */
     static class CategoriesIterGenerator extends IterGenerator<String> {
         @Override
-        public Iterator<String> generate(ParsedActivityIntentInfo info) {
+        public Iterator<String> generate(ParsedIntentInfo info) {
             return info.categoriesIterator();
         }
     }
@@ -2103,7 +2146,7 @@
     /** Create an {@link Iterator} for intent schemes */
     static class SchemesIterGenerator extends IterGenerator<String> {
         @Override
-        public Iterator<String> generate(ParsedActivityIntentInfo info) {
+        public Iterator<String> generate(ParsedIntentInfo info) {
             return info.schemesIterator();
         }
     }
@@ -2111,8 +2154,21 @@
     /** Create an {@link Iterator} for intent authorities */
     static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
         @Override
-        public Iterator<IntentFilter.AuthorityEntry> generate(ParsedActivityIntentInfo info) {
+        public Iterator<IntentFilter.AuthorityEntry> generate(ParsedIntentInfo info) {
             return info.authoritiesIterator();
         }
     }
+
+    /**
+     * Removes MIME type from the group, by delegating to IntentResolvers
+     * @return true if any intent filters were changed due to this update
+     */
+    boolean updateMimeGroup(String packageName, String group) {
+        boolean hasChanges = mActivities.updateMimeGroup(packageName, group);
+        hasChanges |= mProviders.updateMimeGroup(packageName, group);
+        hasChanges |= mReceivers.updateMimeGroup(packageName, group);
+        hasChanges |= mServices.updateMimeGroup(packageName, group);
+
+        return hasChanges;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
index 0e0096d..8e6b89a 100644
--- a/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
+++ b/services/core/java/com/android/server/pm/CrossProfileIntentResolver.java
@@ -18,6 +18,9 @@
 package com.android.server.pm;
 
 
+import android.annotation.NonNull;
+import android.content.IntentFilter;
+
 import com.android.server.IntentResolver;
 import java.util.List;
 
@@ -40,4 +43,9 @@
     protected void sortResults(List<CrossProfileIntentFilter> results) {
         //We don't sort the results
     }
+
+    @Override
+    protected IntentFilter getIntentFilter(@NonNull CrossProfileIntentFilter input) {
+        return input;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 8ad3e9d..f37af3a 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -234,11 +234,11 @@
     }
 
     public void moveCompleteApp(String fromUuid, String toUuid, String packageName,
-            String dataAppName, int appId, String seInfo, int targetSdkVersion,
+            int appId, String seInfo, int targetSdkVersion,
             String fromCodePath) throws InstallerException {
         if (!checkBeforeRemote()) return;
         try {
-            mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, dataAppName, appId, seInfo,
+            mInstalld.moveCompleteApp(fromUuid, toUuid, packageName, appId, seInfo,
                     targetSdkVersion, fromCodePath);
         } catch (Exception e) {
             throw InstallerException.from(e);
diff --git a/services/core/java/com/android/server/pm/InstantAppRegistry.java b/services/core/java/com/android/server/pm/InstantAppRegistry.java
index bcfe577..cf85b0f 100644
--- a/services/core/java/com/android/server/pm/InstantAppRegistry.java
+++ b/services/core/java/com/android/server/pm/InstantAppRegistry.java
@@ -24,8 +24,6 @@
 import android.content.pm.InstantAppInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageInfoUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
@@ -52,6 +50,8 @@
 import com.android.internal.os.SomeArgs;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.XmlUtils;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import libcore.io.IoUtils;
 import libcore.util.HexEncoding;
@@ -694,12 +694,13 @@
             final int packageCount = mService.mPackages.size();
             for (int i = 0; i < packageCount; i++) {
                 final AndroidPackage pkg = mService.mPackages.valueAt(i);
-                if (now - pkg.getLatestPackageUseTimeInMills() < maxInstalledCacheDuration) {
+                final PackageSetting ps = mService.getPackageSetting(pkg.getPackageName());
+                if (ps == null) {
                     continue;
                 }
 
-                final PackageSetting ps = mService.getPackageSetting(pkg.getPackageName());
-                if (ps == null) {
+                if (now - ps.getPkgState().getLatestPackageUseTimeInMills()
+                        < maxInstalledCacheDuration) {
                     continue;
                 }
 
@@ -733,30 +734,28 @@
                     } else if (rhsPkg == null) {
                         return 1;
                     } else {
-                        if (lhsPkg.getLatestPackageUseTimeInMills() >
-                                rhsPkg.getLatestPackageUseTimeInMills()) {
+                        final PackageSetting lhsPs = mService.getPackageSetting(
+                                lhsPkg.getPackageName());
+                        if (lhsPs == null) {
+                            return 0;
+                        }
+
+                        final PackageSetting rhsPs = mService.getPackageSetting(
+                                rhsPkg.getPackageName());
+                        if (rhsPs == null) {
+                            return 0;
+                        }
+
+                        if (lhsPs.getPkgState().getLatestPackageUseTimeInMills() >
+                                rhsPs.getPkgState().getLatestPackageUseTimeInMills()) {
                             return 1;
-                        } else if (lhsPkg.getLatestPackageUseTimeInMills() <
-                                rhsPkg.getLatestPackageUseTimeInMills()) {
+                        } else if (lhsPs.getPkgState().getLatestPackageUseTimeInMills() <
+                                rhsPs.getPkgState().getLatestPackageUseTimeInMills()) {
                             return -1;
+                        } else if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) {
+                            return 1;
                         } else {
-                            final PackageSetting lhsPs = mService.getPackageSetting(
-                                    lhsPkg.getPackageName());
-                            if (lhsPs == null) {
-                                return 0;
-                            }
-
-                            final PackageSetting rhsPs = mService.getPackageSetting(
-                                    rhsPkg.getPackageName());
-                            if (rhsPs == null) {
-                                return 0;
-                            }
-
-                            if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) {
-                                return 1;
-                            } else {
-                                return -1;
-                            }
+                            return -1;
                         }
                     }
                 });
@@ -869,10 +868,9 @@
         // TODO(b/135203078): This may be broken due to inner mutability problems that were broken
         //  as part of moving to PackageInfoUtils. Flags couldn't be determined.
         ApplicationInfo appInfo = PackageInfoUtils.generateApplicationInfo(ps.pkg, 0,
-                ps.readUserState(userId), userId);
+                ps.readUserState(userId), userId, ps);
         if (addApplicationInfo) {
-            return new InstantAppInfo(appInfo,
-                    requestedPermissions, grantedPermissions);
+            return new InstantAppInfo(appInfo, requestedPermissions, grantedPermissions);
         } else {
             return new InstantAppInfo(appInfo.packageName,
                     appInfo.loadLabel(mService.mContext.getPackageManager()),
diff --git a/services/core/java/com/android/server/pm/InstructionSets.java b/services/core/java/com/android/server/pm/InstructionSets.java
index 0a065eb..2d42107 100644
--- a/services/core/java/com/android/server/pm/InstructionSets.java
+++ b/services/core/java/com/android/server/pm/InstructionSets.java
@@ -16,12 +16,14 @@
 
 package com.android.server.pm;
 
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Build;
 import android.os.SystemProperties;
 import android.text.TextUtils;
 import android.util.ArraySet;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+
 import dalvik.system.VMRuntime;
 
 import java.util.ArrayList;
@@ -109,13 +111,4 @@
 
         return VMRuntime.getInstructionSet(abis.primary);
     }
-
-    public static String getPrimaryInstructionSet(AndroidPackage pkg) {
-        if (pkg.getPrimaryCpuAbi() == null) {
-            return getPreferredInstructionSet();
-        }
-
-        return VMRuntime.getInstructionSet(pkg.getPrimaryCpuAbi());
-    }
-
 }
diff --git a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java
index c97d85d..9dc545a 100644
--- a/services/core/java/com/android/server/pm/IntentFilterVerificationState.java
+++ b/services/core/java/com/android/server/pm/IntentFilterVerificationState.java
@@ -17,7 +17,7 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageManager;
-import android.content.pm.parsing.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedIntentInfo;
 import android.util.ArraySet;
 import android.util.Slog;
 
@@ -35,7 +35,7 @@
 
     private int mState;
 
-    private ArrayList<ComponentParseUtils.ParsedActivityIntentInfo> mFilters = new ArrayList<>();
+    private ArrayList<ParsedIntentInfo> mFilters = new ArrayList<>();
     private ArraySet<String> mHosts = new ArraySet<>();
     private int mUserId;
 
@@ -66,7 +66,7 @@
         setState(STATE_VERIFICATION_PENDING);
     }
 
-    public ArrayList<ComponentParseUtils.ParsedActivityIntentInfo> getFilters() {
+    public ArrayList<ParsedIntentInfo> getFilters() {
         return mFilters;
     }
 
@@ -123,7 +123,7 @@
         return false;
     }
 
-    public void addFilter(ComponentParseUtils.ParsedActivityIntentInfo filter) {
+    public void addFilter(ParsedIntentInfo filter) {
         mFilters.add(filter);
         mHosts.addAll(filter.getHostsList());
     }
diff --git a/services/core/java/com/android/server/pm/KeySetManagerService.java b/services/core/java/com/android/server/pm/KeySetManagerService.java
index f9cfee1..dabcc35 100644
--- a/services/core/java/com/android/server/pm/KeySetManagerService.java
+++ b/services/core/java/com/android/server/pm/KeySetManagerService.java
@@ -21,14 +21,13 @@
 import static com.android.server.pm.PackageManagerService.SCAN_INITIAL;
 
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.AndroidPackage;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Base64;
 import android.util.LongSparseArray;
 import android.util.Slog;
 
-import com.android.internal.util.Preconditions;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 3a16217..8031eaa 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -16,7 +16,6 @@
 
 package com.android.server.pm;
 
-import android.Manifest.permission;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.UserIdInt;
@@ -51,7 +50,6 @@
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.ShortcutServiceInternal.ShortcutChangeListener;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
 import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
@@ -74,8 +72,10 @@
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.wm.ActivityTaskManagerInternal;
 
 import java.util.ArrayList;
@@ -135,6 +135,8 @@
 
         private final MyPackageMonitor mPackageMonitor = new MyPackageMonitor();
 
+        private final ShortcutChangeHandler mShortcutChangeHandler;
+
         private final Handler mCallbackHandler;
 
         private PackageInstallerService mPackageInstallerService;
@@ -154,6 +156,8 @@
             mShortcutServiceInternal = Objects.requireNonNull(
                     LocalServices.getService(ShortcutServiceInternal.class));
             mShortcutServiceInternal.addListener(mPackageMonitor);
+            mShortcutChangeHandler = new ShortcutChangeHandler(mUserManagerInternal);
+            mShortcutServiceInternal.addShortcutChangeCallback(mShortcutChangeHandler);
             mCallbackHandler = BackgroundThread.getHandler();
             mDpm = (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
         }
@@ -307,8 +311,8 @@
             final int callingUserId = injectCallingUserId();
 
             if (targetUserId == callingUserId) return true;
-            if (mContext.checkCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS_FULL)
-                    == PackageManager.PERMISSION_GRANTED) {
+            if (injectHasInteractAcrossUsersFullPermission(injectBinderCallingPid(),
+                    injectBinderCallingUid())) {
                 return true;
             }
 
@@ -684,6 +688,15 @@
                     callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
         }
 
+        /**
+         * Returns true if the caller has the "INTERACT_ACROSS_USERS_FULL" permission.
+         */
+        @VisibleForTesting
+        boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
+            return mContext.checkPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    callingPid, callingUid) == PackageManager.PERMISSION_GRANTED;
+        }
+
         @Override
         public ParceledListSlice getShortcuts(String callingPackage, long changedSince,
                 String packageName, List shortcutIds, List<LocusId> locusIds,
@@ -712,12 +725,37 @@
         @Override
         public void registerShortcutChangeCallback(String callingPackage, long changedSince,
                 String packageName, List shortcutIds, List<LocusId> locusIds,
-                ComponentName componentName, int flags, IShortcutChangeCallback callback,
-                int callbackId) {
+                ComponentName componentName, int flags, IShortcutChangeCallback callback) {
+            ensureShortcutPermission(callingPackage);
+
+            if (shortcutIds != null && packageName == null) {
+                throw new IllegalArgumentException(
+                        "To query by shortcut ID, package name must also be set");
+            }
+            if (locusIds != null && packageName == null) {
+                throw new IllegalArgumentException(
+                        "To query by locus ID, package name must also be set");
+            }
+
+            UserHandle user = UserHandle.of(injectCallingUserId());
+            if (mContext.checkCallingOrSelfPermission(
+                    android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
+                    == PackageManager.PERMISSION_GRANTED) {
+                user = null;
+            }
+
+            // TODO: When ShortcutQueryWrapper (ag/10323729) is available, pass that directly.
+            ShortcutChangeHandler.QueryInfo query = new ShortcutChangeHandler.QueryInfo(
+                    changedSince, packageName, shortcutIds, locusIds, componentName, flags, user);
+            mShortcutChangeHandler.addShortcutChangeCallback(callback, query);
         }
 
         @Override
-        public void unregisterShortcutChangeCallback(String callingPackage, int callbackId) {
+        public void unregisterShortcutChangeCallback(String callingPackage,
+                IShortcutChangeCallback callback) {
+            ensureShortcutPermission(callingPackage);
+
+            mShortcutChangeHandler.removeShortcutChangeCallback(callback);
         }
 
         @Override
@@ -997,6 +1035,153 @@
             mCallbackHandler.post(r);
         }
 
+        public static class ShortcutChangeHandler implements LauncherApps.ShortcutChangeCallback {
+
+            static class QueryInfo {
+                final long mChangedSince;
+                final String mPackage;
+                final List<String> mShortcutIds;
+                final List<LocusId> mLocusIds;
+                final ComponentName mActivity;
+                final int mQueryFlags;
+                final UserHandle mCallbackUser;
+
+                QueryInfo(long changedSince, String packageName, List<String> shortcutIds,
+                        List<LocusId> locusIds, ComponentName activity, int flags,
+                        UserHandle callbackUser) {
+                    mChangedSince = changedSince;
+                    mPackage = packageName;
+                    mShortcutIds = shortcutIds;
+                    mLocusIds = locusIds;
+                    mActivity = activity;
+                    mQueryFlags = flags;
+                    mCallbackUser = callbackUser;
+                }
+            }
+
+            private final UserManagerInternal mUserManagerInternal;
+
+            ShortcutChangeHandler(UserManagerInternal userManager) {
+                mUserManagerInternal = userManager;
+            }
+
+            private final RemoteCallbackList<IShortcutChangeCallback> mCallbacks =
+                    new RemoteCallbackList<>();
+
+            public synchronized void addShortcutChangeCallback(IShortcutChangeCallback callback,
+                    QueryInfo query) {
+                mCallbacks.unregister(callback);
+                mCallbacks.register(callback, query);
+            }
+
+            public synchronized void removeShortcutChangeCallback(
+                    IShortcutChangeCallback callback) {
+                mCallbacks.unregister(callback);
+            }
+
+            @Override
+            public void onShortcutsAddedOrUpdated(String packageName, List<ShortcutInfo> shortcuts,
+                    UserHandle user) {
+                onShortcutEvent(packageName, shortcuts, user, false);
+            }
+
+            @Override
+            public void onShortcutsRemoved(String packageName, List<ShortcutInfo> shortcuts,
+                    UserHandle user) {
+                onShortcutEvent(packageName, shortcuts, user, true);
+            }
+
+            private void onShortcutEvent(String packageName,
+                    List<ShortcutInfo> shortcuts, UserHandle user, boolean shortcutsRemoved) {
+                int count = mCallbacks.beginBroadcast();
+
+                for (int i = 0; i < count; i++) {
+                    final IShortcutChangeCallback callback = mCallbacks.getBroadcastItem(i);
+                    final QueryInfo query = (QueryInfo) mCallbacks.getBroadcastCookie(i);
+
+                    if (query.mCallbackUser != null && !hasUserAccess(query.mCallbackUser, user)) {
+                        // Callback owner does not have access to the shortcuts' user.
+                        continue;
+                    }
+
+                    // Filter the list by query, if any matches exists, send via callback.
+                    List<ShortcutInfo> matchedList =
+                            filterShortcutsByQuery(packageName, shortcuts, query);
+                    if (!CollectionUtils.isEmpty(matchedList)) {
+                        try {
+                            if (shortcutsRemoved) {
+                                callback.onShortcutsRemoved(packageName, matchedList, user);
+                            } else {
+                                callback.onShortcutsAddedOrUpdated(packageName, matchedList, user);
+                            }
+                        } catch (RemoteException e) {
+                            // The RemoteCallbackList will take care of removing the dead object.
+                        }
+                    }
+                }
+
+                mCallbacks.finishBroadcast();
+            }
+
+            public static List<ShortcutInfo> filterShortcutsByQuery(String packageName,
+                    List<ShortcutInfo> shortcuts, QueryInfo query) {
+                if (query.mPackage != null && query.mPackage != packageName) {
+                    return null;
+                }
+
+                List<ShortcutInfo> matches = new ArrayList<>();
+
+                final boolean matchDynamic =
+                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_DYNAMIC) != 0;
+                final boolean matchPinned =
+                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_PINNED) != 0;
+                final boolean matchManifest =
+                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_MANIFEST) != 0;
+                final boolean matchCached =
+                        (query.mQueryFlags & ShortcutQuery.FLAG_MATCH_CACHED) != 0;
+                final int shortcutFlags = (matchDynamic ? ShortcutInfo.FLAG_DYNAMIC : 0)
+                        | (matchPinned ? ShortcutInfo.FLAG_PINNED : 0)
+                        | (matchManifest ? ShortcutInfo.FLAG_MANIFEST : 0)
+                        | (matchCached ? ShortcutInfo.FLAG_CACHED : 0);
+
+                for (int i = 0; i < shortcuts.size(); i++) {
+                    final ShortcutInfo si = shortcuts.get(i);
+
+                    if (query.mActivity != null && !query.mActivity.equals(si.getActivity())) {
+                        continue;
+                    }
+
+                    if (query.mChangedSince != 0
+                            && query.mChangedSince > si.getLastChangedTimestamp()) {
+                        continue;
+                    }
+
+                    if (query.mShortcutIds != null && !query.mShortcutIds.contains(si.getId())) {
+                        continue;
+                    }
+
+                    if (query.mLocusIds != null && !query.mLocusIds.contains(si.getLocusId())) {
+                        continue;
+                    }
+
+                    if ((shortcutFlags & si.getFlags()) != 0) {
+                        matches.add(si);
+                    }
+                }
+
+                return matches;
+            }
+
+            private boolean hasUserAccess(UserHandle callbackUser, UserHandle shortcutUser) {
+                final int callbackUserId = callbackUser.getIdentifier();
+                final int shortcutUserId = shortcutUser.getIdentifier();
+
+                if (shortcutUser == callbackUser) return true;
+                return mUserManagerInternal.isProfileAccessible(callbackUserId, shortcutUserId,
+                        null, false);
+            }
+        }
+
         private class MyPackageMonitor extends PackageMonitor implements ShortcutChangeListener {
 
             // TODO Simplify with lambdas.
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index ae7a4a7..2df4a92 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -22,7 +22,6 @@
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.IOtaDexopt;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Environment;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
@@ -35,13 +34,17 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.dex.DexoptOptions;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -118,31 +121,33 @@
         if (mDexoptCommands != null) {
             throw new IllegalStateException("already called prepare()");
         }
-        final List<AndroidPackage> important;
-        final List<AndroidPackage> others;
+        final List<PackageSetting> important;
+        final List<PackageSetting> others;
         synchronized (mPackageManagerService.mLock) {
             // Important: the packages we need to run with ab-ota compiler-reason.
             important = PackageManagerServiceUtils.getPackagesForDexopt(
-                    mPackageManagerService.mPackages.values(), mPackageManagerService,
+                    mPackageManagerService.mSettings.mPackages.values(), mPackageManagerService,
                     DEBUG_DEXOPT);
             // Others: we should optimize this with the (first-)boot compiler-reason.
-            others = new ArrayList<>(mPackageManagerService.mPackages.values());
+            others = new ArrayList<>(mPackageManagerService.mSettings.mPackages.values());
             others.removeAll(important);
+            others.removeIf(PackageManagerServiceUtils.REMOVE_IF_NULL_PKG);
 
             // Pre-size the array list by over-allocating by a factor of 1.5.
             mDexoptCommands = new ArrayList<>(3 * mPackageManagerService.mPackages.size() / 2);
         }
 
-        for (AndroidPackage p : important) {
-            mDexoptCommands.addAll(generatePackageDexopts(p, PackageManagerService.REASON_AB_OTA));
+        for (PackageSetting pkgSetting : important) {
+            mDexoptCommands.addAll(generatePackageDexopts(pkgSetting.pkg, pkgSetting,
+                    PackageManagerService.REASON_AB_OTA));
         }
-        for (AndroidPackage p : others) {
+        for (PackageSetting pkgSetting : others) {
             // We assume here that there are no core apps left.
-            if (p.isCoreApp()) {
+            if (pkgSetting.pkg.isCoreApp()) {
                 throw new IllegalStateException("Found a core app that's not important");
             }
-            mDexoptCommands.addAll(
-                    generatePackageDexopts(p, PackageManagerService.REASON_FIRST_BOOT));
+            mDexoptCommands.addAll(generatePackageDexopts(pkgSetting.pkg, pkgSetting,
+                            PackageManagerService.REASON_FIRST_BOOT));
         }
         completeSize = mDexoptCommands.size();
 
@@ -150,8 +155,8 @@
         if (spaceAvailable < BULK_DELETE_THRESHOLD) {
             Log.i(TAG, "Low on space, deleting oat files in an attempt to free up space: "
                     + PackageManagerServiceUtils.packagesToString(others));
-            for (AndroidPackage pkg : others) {
-                mPackageManagerService.deleteOatArtifactsOfPackage(pkg.getPackageName());
+            for (PackageSetting pkg : others) {
+                mPackageManagerService.deleteOatArtifactsOfPackage(pkg.name);
             }
         }
         long spaceAvailableNow = getAvailableSpace();
@@ -161,16 +166,18 @@
         if (DEBUG_DEXOPT) {
             try {
                 // Output some data about the packages.
-                AndroidPackage lastUsed = Collections.max(important,
-                        (pkg1, pkg2) -> Long.compare(
-                                pkg1.getLatestForegroundPackageUseTimeInMills(),
-                                pkg2.getLatestForegroundPackageUseTimeInMills()));
+                PackageSetting lastUsed = Collections.max(important,
+                        (pkgSetting1, pkgSetting2) -> Long.compare(
+                                pkgSetting1.getPkgState()
+                                        .getLatestForegroundPackageUseTimeInMills(),
+                                pkgSetting2.getPkgState()
+                                        .getLatestForegroundPackageUseTimeInMills()));
                 Log.d(TAG, "A/B OTA: lastUsed time = "
-                        + lastUsed.getLatestForegroundPackageUseTimeInMills());
+                        + lastUsed.getPkgState().getLatestForegroundPackageUseTimeInMills());
                 Log.d(TAG, "A/B OTA: deprioritized packages:");
-                for (AndroidPackage pkg : others) {
-                    Log.d(TAG, "  " + pkg.getPackageName() + " - "
-                            + pkg.getLatestForegroundPackageUseTimeInMills());
+                for (PackageSetting pkgSetting : others) {
+                    Log.d(TAG, "  " + pkgSetting.name + " - "
+                            + pkgSetting.getPkgState().getLatestForegroundPackageUseTimeInMills());
                 }
             } catch (Exception ignored) {
             }
@@ -263,7 +270,7 @@
      * Generate all dexopt commands for the given package.
      */
     private synchronized List<String> generatePackageDexopts(AndroidPackage pkg,
-            int compilationReason) {
+            PackageSetting pkgSetting, int compilationReason) {
         // Intercept and collect dexopt requests
         final List<String> commands = new ArrayList<String>();
         final Installer collectingInstaller = new Installer(mContext, true) {
@@ -333,7 +340,7 @@
         PackageDexOptimizer optimizer = new OTADexoptPackageDexOptimizer(
                 collectingInstaller, mPackageManagerService.mInstallLock, mContext);
 
-        optimizer.performDexOpt(pkg,
+        optimizer.performDexOpt(pkg, pkgSetting,
                 null /* ISAs */,
                 null /* CompilerStats.PackageStats */,
                 mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(
@@ -386,9 +393,12 @@
                 continue;
             }
 
-            final String[] instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(),
-                    pkg.getSecondaryCpuAbi());
-            final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+            PackageSetting pkgSetting = mPackageManagerService.getPackageSetting(pkg.getPackageName());
+            final String[] instructionSets = getAppDexInstructionSets(
+                    AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                    AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
+            final List<String> paths =
+                    AndroidPackageUtils.getAllCodePathsExcludingResourceOnly(pkg);
             final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
             for (String dexCodeInstructionSet : dexCodeInstructionSets) {
                 for (String path : paths) {
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelper.java b/services/core/java/com/android/server/pm/PackageAbiHelper.java
index d7c161c..e355bb9 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelper.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelper.java
@@ -17,11 +17,12 @@
 package com.android.server.pm;
 
 import android.annotation.Nullable;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
 import android.util.Pair;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.io.File;
 import java.util.Set;
@@ -33,7 +34,8 @@
      * Derive and get the location of native libraries for the given package,
      * which varies depending on where and how the package was installed.
      */
-    NativeLibraryPaths getNativeLibraryPaths(AndroidPackage pkg, File appLib32InstallDir);
+    NativeLibraryPaths getNativeLibraryPaths(AndroidPackage pkg, PackageSetting pkgSetting,
+            File appLib32InstallDir);
 
     /**
      * Calculate the abis for a bundled app. These can uniquely be determined from the contents of
@@ -48,9 +50,8 @@
      *
      * If {@code extractLibs} is true, native libraries are extracted from the app if required.
      */
-    Pair<Abis, NativeLibraryPaths> derivePackageAbi(
-            AndroidPackage pkg, String cpuAbiOverride, boolean extractLibs)
-            throws PackageManagerException;
+    Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg, boolean isUpdatedSystemApp,
+            String cpuAbiOverride, boolean extractLibs) throws PackageManagerException;
 
     /**
      * Calculates adjusted ABIs for a set of packages belonging to a shared user so that they all
@@ -113,8 +114,9 @@
             this.secondary = secondary;
         }
 
-        Abis(AndroidPackage pkg) {
-            this(pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi());
+        Abis(AndroidPackage pkg, PackageSetting pkgSetting)  {
+            this(AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                    AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
         }
 
         public void applyTo(ParsedPackage pkg) {
diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
index 482fc49..0bd8b28 100644
--- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
+++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java
@@ -27,9 +27,7 @@
 import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
 
 import android.annotation.Nullable;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Build;
 import android.os.Environment;
 import android.os.FileUtils;
@@ -40,6 +38,8 @@
 
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 
 import dalvik.system.VMRuntime;
 
@@ -131,11 +131,11 @@
     }
 
     @Override
-    public NativeLibraryPaths getNativeLibraryPaths(
-            AndroidPackage pkg, File appLib32InstallDir) {
-        return getNativeLibraryPaths(new Abis(pkg), appLib32InstallDir, pkg.getCodePath(),
-                pkg.getBaseCodePath(), pkg.isSystemApp(),
-                pkg.isUpdatedSystemApp());
+    public NativeLibraryPaths getNativeLibraryPaths(AndroidPackage pkg, PackageSetting pkgSetting,
+            File appLib32InstallDir) {
+        return getNativeLibraryPaths(new Abis(pkg, pkgSetting), appLib32InstallDir,
+                pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(),
+                pkgSetting.getPkgState().isUpdatedSystemApp());
     }
 
     private static NativeLibraryPaths getNativeLibraryPaths(final Abis abis,
@@ -273,7 +273,7 @@
             // ABI that's higher on the list, i.e, a device that's configured to prefer
             // 64 bit apps will see a 64 bit primary ABI,
 
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) == 0) {
+            if (!pkg.isMultiArch()) {
                 Slog.e(PackageManagerService.TAG,
                         "Package " + pkg + " has multiple bundled libs, but is not multiarch.");
             }
@@ -293,18 +293,21 @@
     }
 
     @Override
-    public Pair<Abis, NativeLibraryPaths> derivePackageAbi(
-            AndroidPackage pkg, String cpuAbiOverride, boolean extractLibs)
+    public Pair<Abis, NativeLibraryPaths> derivePackageAbi(AndroidPackage pkg,
+            boolean isUpdatedSystemApp, String cpuAbiOverride, boolean extractLibs)
             throws PackageManagerException {
         // Give ourselves some initial paths; we'll come back for another
         // pass once we've determined ABI below.
-        final NativeLibraryPaths initialLibraryPaths = getNativeLibraryPaths(new Abis(pkg),
+        String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(pkg);
+        String pkgRawSecondaryCpuAbi = AndroidPackageUtils.getRawSecondaryCpuAbi(pkg);
+        final NativeLibraryPaths initialLibraryPaths = getNativeLibraryPaths(
+                new Abis(pkgRawPrimaryCpuAbi, pkgRawSecondaryCpuAbi),
                 PackageManagerService.sAppLib32InstallDir, pkg.getCodePath(),
-                pkg.getBaseCodePath(), pkg.isSystemApp(),
-                pkg.isUpdatedSystemApp());
+                pkg.getBaseCodePath(), pkg.isSystem(),
+                isUpdatedSystemApp);
 
         // We shouldn't attempt to extract libs from system app when it was not updated.
-        if (PackageManagerService.isSystemApp(pkg) && !pkg.isUpdatedSystemApp()) {
+        if (pkg.isSystem() && !isUpdatedSystemApp) {
             extractLibs = false;
         }
 
@@ -317,7 +320,7 @@
 
         NativeLibraryHelper.Handle handle = null;
         try {
-            handle = NativeLibraryHelper.Handle.create(pkg);
+            handle = AndroidPackageUtils.createNativeLibraryHandle(pkg);
             // TODO(multiArch): This can be null for apps that didn't go through the
             // usual installation process. We can calculate it again, like we
             // do during install time.
@@ -329,17 +332,7 @@
             // Null out the abis so that they can be recalculated.
             primaryCpuAbi = null;
             secondaryCpuAbi = null;
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_MULTIARCH) != 0) {
-                // Warn if we've set an abiOverride for multi-lib packages..
-                // By definition, we need to copy both 32 and 64 bit libraries for
-                // such packages.
-                if (pkg.getCpuAbiOverride() != null
-                        && !NativeLibraryHelper.CLEAR_ABI_OVERRIDE.equals(
-                        pkg.getCpuAbiOverride())) {
-                    Slog.w(PackageManagerService.TAG,
-                            "Ignoring abiOverride for multi arch application.");
-                }
-
+            if (pkg.isMultiArch()) {
                 int abi32 = PackageManager.NO_NATIVE_LIBRARIES;
                 int abi64 = PackageManager.NO_NATIVE_LIBRARIES;
                 if (Build.SUPPORTED_32_BIT_ABIS.length > 0) {
@@ -357,7 +350,7 @@
                 }
 
                 // Shared library native code should be in the APK zip aligned
-                if (abi32 >= 0 && pkg.isLibrary() && extractLibs) {
+                if (abi32 >= 0 && AndroidPackageUtils.isLibrary(pkg) && extractLibs) {
                     throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                             "Shared library native lib extraction not supported");
                 }
@@ -384,7 +377,7 @@
 
                 if (abi64 >= 0) {
                     // Shared library native libs should be in the APK zip aligned
-                    if (extractLibs && pkg.isLibrary()) {
+                    if (extractLibs && AndroidPackageUtils.isLibrary(pkg)) {
                         throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                                 "Shared library native lib extraction not supported");
                     }
@@ -437,7 +430,7 @@
 
                 if (copyRet >= 0) {
                     // Shared libraries that have native libs must be multi-architecture
-                    if (pkg.isLibrary()) {
+                    if (AndroidPackageUtils.isLibrary(pkg)) {
                         throw new PackageManagerException(INSTALL_FAILED_INTERNAL_ERROR,
                                 "Shared library with native libs must be multiarch");
                     }
@@ -461,9 +454,8 @@
         final Abis abis = new Abis(primaryCpuAbi, secondaryCpuAbi);
         return new Pair<>(abis,
                 getNativeLibraryPaths(abis, PackageManagerService.sAppLib32InstallDir,
-                        pkg.getCodePath(), pkg.getBaseCodePath(),
-                        pkg.isSystemApp(),
-                        pkg.isUpdatedSystemApp()));
+                        pkg.getCodePath(), pkg.getBaseCodePath(), pkg.isSystem(),
+                        isUpdatedSystemApp));
     }
 
     /**
@@ -484,9 +476,11 @@
     public String getAdjustedAbiForSharedUser(
             Set<PackageSetting> packagesForUser, AndroidPackage scannedPackage) {
         String requiredInstructionSet = null;
-        if (scannedPackage != null && scannedPackage.getPrimaryCpuAbi() != null) {
-            requiredInstructionSet = VMRuntime.getInstructionSet(
-                    scannedPackage.getPrimaryCpuAbi());
+        if (scannedPackage != null) {
+            String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(scannedPackage);
+            if (pkgRawPrimaryCpuAbi != null) {
+                requiredInstructionSet = VMRuntime.getInstructionSet(pkgRawPrimaryCpuAbi);
+            }
         }
 
         PackageSetting requirer = null;
@@ -533,7 +527,7 @@
         } else {
             // requirer == null implies that we're updating all ABIs in the set to
             // match scannedPackage.
-            adjustedAbi = scannedPackage.getPrimaryCpuAbi();
+            adjustedAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(scannedPackage);
         }
         return adjustedAbi;
     }
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 2b42221..e625aef 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -38,13 +38,13 @@
 import static dalvik.system.DexFile.getSafeModeCompilerFilter;
 import static dalvik.system.DexFile.isProfileGuidedCompilerFilter;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.SharedLibraryInfo;
 import android.content.pm.dex.ArtManager;
 import android.content.pm.dex.DexMetadataHelper;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.FileUtils;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -63,6 +63,8 @@
 import com.android.server.pm.dex.DexoptOptions;
 import com.android.server.pm.dex.DexoptUtils;
 import com.android.server.pm.dex.PackageDexUsage;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 
 import dalvik.system.DexFile;
 
@@ -112,7 +114,7 @@
 
     static boolean canOptimizePackage(AndroidPackage pkg) {
         // We do not dexopt a package with no code.
-        if ((pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) == 0) {
+        if (!pkg.isHasCode()) {
             return false;
         }
 
@@ -126,7 +128,7 @@
      * <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are
      * synchronized on {@link #mInstallLock}.
      */
-    int performDexOpt(AndroidPackage pkg,
+    int performDexOpt(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
             String[] instructionSets, CompilerStats.PackageStats packageStats,
             PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
         if (pkg.getUid() == -1) {
@@ -139,7 +141,7 @@
         synchronized (mInstallLock) {
             final long acquireTime = acquireWakeLockLI(pkg.getUid());
             try {
-                return performDexOptLI(pkg, instructionSets,
+                return performDexOptLI(pkg, pkgSetting, instructionSets,
                         packageStats, packageUseInfo, options);
             } finally {
                 releaseWakeLockLI(acquireTime);
@@ -152,19 +154,21 @@
      * It assumes the install lock is held.
      */
     @GuardedBy("mInstallLock")
-    private int performDexOptLI(AndroidPackage pkg,
+    private int performDexOptLI(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
             String[] targetInstructionSets, CompilerStats.PackageStats packageStats,
             PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) {
-        final List<SharedLibraryInfo> sharedLibraries = pkg.getUsesLibraryInfos();
+        final List<SharedLibraryInfo> sharedLibraries = pkgSetting.getPkgState()
+                .getUsesLibraryInfos();
         final String[] instructionSets = targetInstructionSets != null ?
-                targetInstructionSets : getAppDexInstructionSets(pkg.getPrimaryCpuAbi(),
-                pkg.getSecondaryCpuAbi());
+                targetInstructionSets : getAppDexInstructionSets(
+                AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
-        final List<String> paths = pkg.getAllCodePaths();
+        final List<String> paths = AndroidPackageUtils.getAllCodePaths(pkg);
 
         int sharedGid = UserHandle.getSharedAppGid(pkg.getUid());
         if (sharedGid == -1) {
-            Slog.wtf(TAG, "Well this is awkward; package " + pkg.getAppInfoName() + " had UID "
+            Slog.wtf(TAG, "Well this is awkward; package " + pkg.getPackageName() + " had UID "
                     + pkg.getUid(), new Throwable());
             sharedGid = android.os.Process.NOBODY_UID;
         }
@@ -173,7 +177,7 @@
         // For each code path in the package, this array contains the class loader context that
         // needs to be passed to dexopt in order to ensure correct optimizations.
         boolean[] pathsWithCode = new boolean[paths.size()];
-        pathsWithCode[0] = (pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        pathsWithCode[0] = pkg.isHasCode();
         for (int i = 1; i < paths.size(); i++) {
             pathsWithCode[i] = (pkg.getSplitFlags()[i - 1] & ApplicationInfo.FLAG_HAS_CODE) != 0;
         }
@@ -232,10 +236,10 @@
 
             // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct
             // flags.
-            final int dexoptFlags = getDexFlags(pkg, compilerFilter, options);
+            final int dexoptFlags = getDexFlags(pkg, pkgSetting, compilerFilter, options);
 
             for (String dexCodeIsa : dexCodeInstructionSets) {
-                int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter,
+                int newResult = dexOptPath(pkg, pkgSetting, path, dexCodeIsa, compilerFilter,
                         profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid,
                         packageStats, options.isDowngrade(), profileName, dexMetadataPath,
                         options.getCompilationReason());
@@ -260,8 +264,8 @@
      *      DEX_OPT_SKIPPED if the path does not need to be deopt-ed.
      */
     @GuardedBy("mInstallLock")
-    private int dexOptPath(AndroidPackage pkg, String path, String isa,
-            String compilerFilter, boolean profileUpdated, String classLoaderContext,
+    private int dexOptPath(AndroidPackage pkg, @NonNull PackageSetting pkgSetting, String path,
+            String isa, String compilerFilter, boolean profileUpdated, String classLoaderContext,
             int dexoptFlags, int uid, CompilerStats.PackageStats packageStats, boolean downgrade,
             String profileName, String dexMetadataPath, int compilationReason) {
         int dexoptNeeded = getDexoptNeeded(path, isa, compilerFilter, classLoaderContext,
@@ -270,10 +274,11 @@
             return DEX_OPT_SKIPPED;
         }
 
-        String oatDir = getPackageOatDirIfSupported(pkg);
+        String oatDir = getPackageOatDirIfSupported(pkg,
+                pkgSetting.getPkgState().isUpdatedSystemApp());
 
         Log.i(TAG, "Running dexopt (dexoptNeeded=" + dexoptNeeded + ") on: " + path
-                + " pkg=" + pkg.getAppInfoPackageName() + " isa=" + isa
+                + " pkg=" + pkg.getPackageName() + " isa=" + isa
                 + " dexoptFlags=" + printDexoptFlags(dexoptFlags)
                 + " targetFilter=" + compilerFilter + " oatDir=" + oatDir
                 + " classLoaderContext=" + classLoaderContext);
@@ -284,9 +289,10 @@
             // TODO: Consider adding 2 different APIs for primary and secondary dexopt.
             // installd only uses downgrade flag for secondary dex files and ignores it for
             // primary dex files.
+            String seInfo = AndroidPackageUtils.getSeInfo(pkg, pkgSetting);
             mInstaller.dexopt(path, uid, pkg.getPackageName(), isa, dexoptNeeded, oatDir,
                     dexoptFlags, compilerFilter, pkg.getVolumeUuid(), classLoaderContext,
-                    pkg.getSeInfo(), false /* downgrade*/, pkg.getTargetSdkVersion(),
+                    seInfo, false /* downgrade*/, pkg.getTargetSdkVersion(),
                     profileName, dexMetadataPath,
                     getAugmentedReasonName(compilationReason, dexMetadataPath != null));
 
@@ -449,13 +455,14 @@
     /**
      * Dumps the dexopt state of the given package {@code pkg} to the given {@code PrintWriter}.
      */
-    void dumpDexoptState(IndentingPrintWriter pw, AndroidPackage pkg,
+    void dumpDexoptState(IndentingPrintWriter pw, AndroidPackage pkg, PackageSetting pkgSetting,
             PackageDexUsage.PackageUseInfo useInfo) {
-        final String[] instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(),
-                pkg.getSecondaryCpuAbi());
+        final String[] instructionSets = getAppDexInstructionSets(
+                AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
         final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
 
-        final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+        final List<String> paths = AndroidPackageUtils.getAllCodePathsExcludingResourceOnly(pkg);
 
         for (String path : paths) {
             pw.println("path: " + path);
@@ -546,7 +553,7 @@
     private String getRealCompilerFilter(AndroidPackage pkg, String targetCompilerFilter,
             boolean isUsedByOtherApps) {
         // When an app or priv app is configured to run out of box, only verify it.
-        if (pkg.isEmbeddedDexUsed()
+        if (pkg.isUseEmbeddedDex()
                 || (pkg.isPrivileged()
                     && DexManager.isPackageSelectedToRunOob(pkg.getPackageName()))) {
             return "verify";
@@ -562,8 +569,7 @@
         // PackageDexOptimizer#canOptimizePackage or PackageManagerService#getOptimizablePackages
         // but that would have the downside of possibly producing a big odex files which would
         // be ignored anyway.
-        boolean vmSafeModeOrDebuggable = ((pkg.getFlags() & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0)
-                || ((pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+        boolean vmSafeModeOrDebuggable = pkg.isVmSafeMode() || pkg.isDebuggable();
 
         if (vmSafeModeOrDebuggable) {
             return getSafeModeCompilerFilter(targetCompilerFilter);
@@ -583,14 +589,15 @@
     }
 
     private int getDexFlags(ApplicationInfo info, String compilerFilter, DexoptOptions options) {
-        return getDexFlags(info.flags, info.getHiddenApiEnforcementPolicy(),
-                info.splitDependencies, info.requestsIsolatedSplitLoading(), compilerFilter,
-                options);
+        return getDexFlags((info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0,
+                info.getHiddenApiEnforcementPolicy(), info.splitDependencies,
+                info.requestsIsolatedSplitLoading(), compilerFilter, options);
     }
-    private int getDexFlags(AndroidPackage pkg, String compilerFilter,
-            DexoptOptions options) {
-        return getDexFlags(pkg.getFlags(), pkg.getHiddenApiEnforcementPolicy(),
-                pkg.getSplitDependencies(), pkg.requestsIsolatedSplitLoading(), compilerFilter,
+    private int getDexFlags(AndroidPackage pkg, @NonNull PackageSetting pkgSetting,
+            String compilerFilter, DexoptOptions options) {
+        return getDexFlags(pkg.isDebuggable(),
+                AndroidPackageUtils.getHiddenApiEnforcementPolicy(pkg, pkgSetting),
+                pkg.getSplitDependencies(), pkg.isIsolatedSplitLoading(), compilerFilter,
                 options);
     }
 
@@ -598,10 +605,9 @@
      * Computes the dex flags that needs to be pass to installd for the given package and compiler
      * filter.
      */
-    private int getDexFlags(int flags, int hiddenApiEnforcementPolicy,
+    private int getDexFlags(boolean debuggable, int hiddenApiEnforcementPolicy,
             SparseArray<int[]> splitDependencies, boolean requestsIsolatedSplitLoading,
             String compilerFilter, DexoptOptions options) {
-        boolean debuggable = (flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         // Profile guide compiled oat files should not be public unles they are based
         // on profiles from dex metadata archives.
         // The flag isDexoptInstallWithDexMetadata applies only on installs when we know that
@@ -699,8 +705,8 @@
      * not needed or unsupported for the package.
      */
     @Nullable
-    private String getPackageOatDirIfSupported(AndroidPackage pkg) {
-        if (!pkg.canHaveOatDir()) {
+    private String getPackageOatDirIfSupported(AndroidPackage pkg, boolean isUpdatedSystemApp) {
+        if (!AndroidPackageUtils.canHaveOatDir(pkg, isUpdatedSystemApp)) {
             return null;
         }
         File codePath = new File(pkg.getCodePath());
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index 0e554f8..41988d6 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -81,7 +81,6 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.dex.DexMetadataHelper;
-import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ApkLiteParseUtils;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -127,6 +126,7 @@
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.dex.DexManager;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.security.VerityUtils;
 
 import libcore.io.IoUtils;
@@ -1169,12 +1169,13 @@
      */
     private static boolean isIncrementalInstallationAllowed(String packageName) {
         final PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class);
-        final AndroidPackage existingPackage = pmi.getPackage(packageName);
-        if (existingPackage == null) {
+        final PackageSetting existingPkgSetting = pmi.getPackageSetting(packageName);
+        if (existingPkgSetting == null || existingPkgSetting.pkg == null) {
             return true;
         }
 
-        return !PackageManagerService.isSystemApp(existingPackage);
+        return !existingPkgSetting.pkg.isSystem()
+                && !existingPkgSetting.getPkgState().isUpdatedSystemApp();
     }
 
     /**
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ad70345..14964b5 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -104,6 +104,9 @@
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
 import static com.android.internal.util.ArrayUtils.emptyIfNull;
 import static com.android.internal.util.ArrayUtils.filter;
+import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME;
+import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME;
+import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME;
 import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
@@ -179,12 +182,15 @@
 import android.content.pm.PackageManager.ModuleInfoFlags;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
+import android.content.pm.PackageManagerInternal.PrivateResolveFlags;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.ParseFlags;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
+import android.content.pm.PackagePartitions;
+import android.content.pm.PackagePartitions.SystemPartition;
 import android.content.pm.PackageStats;
 import android.content.pm.PackageUserState;
 import android.content.pm.ParceledListSlice;
@@ -206,20 +212,17 @@
 import android.content.pm.dex.ArtManager;
 import android.content.pm.dex.DexMetadataHelper;
 import android.content.pm.dex.IArtManager;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ApkParseUtils;
-import android.content.pm.parsing.ComponentParseUtils;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.PackageInfoUtils;
-import android.content.pm.parsing.ParsedPackage;
-import android.content.pm.parsing.library.PackageBackwardCompatibility;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.ParsingPackageRead;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
 import android.content.res.Resources;
 import android.content.rollback.IRollbackManager;
 import android.database.ContentObserver;
@@ -305,6 +308,7 @@
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
 import com.android.internal.content.PackageHelper;
+import com.android.internal.content.om.OverlayConfig;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.SomeArgs;
 import com.android.internal.os.Zygote;
@@ -337,6 +341,13 @@
 import com.android.server.pm.dex.DexoptOptions;
 import com.android.server.pm.dex.PackageDexUsage;
 import com.android.server.pm.dex.ViewCompiler;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.library.PackageBackwardCompatibility;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.pm.permission.BasePermission;
 import com.android.server.pm.permission.PermissionManagerService;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
@@ -792,22 +803,12 @@
      * specificity (the more generic, the earlier in the list a partition appears).
      */
     @VisibleForTesting(visibility = Visibility.PRIVATE)
-    public static final List<SystemPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
-            Arrays.asList(
-                    new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */,
-                            false /* hasOverlays */),
-                    new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR,
-                            true /* hasOverlays */),
-                    new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM,
-                            true /* hasOverlays */),
-                    new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM,
-                            true /* hasOverlays */),
-                    new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT,
-                            true /* hasOverlays */),
-                    new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
-                            true /* hasOverlays */)));
+    public static final List<ScanPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
+            PackagePartitions.getOrderedPartitions(ScanPartition::new));
 
-    private final List<SystemPartition> mDirsToScanAsSystem;
+    private final List<ScanPartition> mDirsToScanAsSystem;
+
+    private final OverlayConfig mOverlayConfig;
 
     /**
      * Unit tests will instantiate, extend and/or mock to mock dependencies / behaviors.
@@ -1017,13 +1018,13 @@
 
     private final AppsFilter mAppsFilter;
 
-    class PackageParserCallback implements PackageParser.Callback {
+    class PackageParserCallback extends PackageParser2.Callback {
         @Override public final boolean hasFeature(String feature) {
             return PackageManagerService.this.hasSystemFeature(feature, 0);
         }
     }
 
-    final PackageParser.Callback mPackageParserCallback = new PackageParserCallback();
+    final PackageParser2.Callback mPackageParserCallback = new PackageParserCallback();
 
     // Currently known shared libraries.
     final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
@@ -1086,7 +1087,7 @@
     boolean mResolverReplaced = false;
 
     private final @Nullable ComponentName mIntentFilterVerifierComponent;
-    private final @Nullable IntentFilterVerifier<ParsedActivityIntentInfo> mIntentFilterVerifier;
+    private final @Nullable IntentFilterVerifier<ParsedIntentInfo> mIntentFilterVerifier;
 
     private int mIntentFilterVerificationToken = 0;
 
@@ -1147,7 +1148,7 @@
         void receiveVerificationResponse(int verificationId);
     }
 
-    private class IntentVerifierProxy implements IntentFilterVerifier<ParsedActivityIntentInfo> {
+    private class IntentVerifierProxy implements IntentFilterVerifier<ParsedIntentInfo> {
         private Context mContext;
         private ComponentName mIntentFilterVerifierComponent;
         private ArrayList<Integer> mCurrentIntentFilterVerifications = new ArrayList<>();
@@ -1172,11 +1173,11 @@
 
                 String packageName = ivs.getPackageName();
 
-                ArrayList<ParsedActivityIntentInfo> filters = ivs.getFilters();
+                ArrayList<ParsedIntentInfo> filters = ivs.getFilters();
                 final int filterCount = filters.size();
                 ArraySet<String> domainsSet = new ArraySet<>();
                 for (int m=0; m<filterCount; m++) {
-                    ParsedActivityIntentInfo filter = filters.get(m);
+                    ParsedIntentInfo filter = filters.get(m);
                     domainsSet.addAll(filter.getHostsList());
                 }
                 synchronized (mLock) {
@@ -1228,14 +1229,14 @@
 
             final boolean verified = ivs.isVerified();
 
-            ArrayList<ParsedActivityIntentInfo> filters = ivs.getFilters();
+            ArrayList<ParsedIntentInfo> filters = ivs.getFilters();
             final int count = filters.size();
             if (DEBUG_DOMAIN_VERIFICATION) {
                 Slog.i(TAG, "Received verification response " + verificationId
                         + " for " + count + " filters, verified=" + verified);
             }
             for (int n=0; n<count; n++) {
-                ParsedActivityIntentInfo filter = filters.get(n);
+                ParsedIntentInfo filter = filters.get(n);
                 filter.setVerified(verified);
 
                 if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG, "IntentFilter " + filter.toString()
@@ -1348,7 +1349,7 @@
 
         @Override
         public boolean addOneIntentFilterVerification(int verifierUid, int userId, int verificationId,
-                ParsedActivityIntentInfo filter, String packageName) {
+                ParsedIntentInfo filter, String packageName) {
             if (!hasValidDomains(filter)) {
                 return false;
             }
@@ -1377,7 +1378,7 @@
         }
     }
 
-    private static boolean hasValidDomains(ParsedActivityIntentInfo filter) {
+    private static boolean hasValidDomains(ParsedIntentInfo filter) {
         return filter.hasCategory(Intent.CATEGORY_BROWSABLE)
                 && (filter.hasDataScheme(IntentFilter.SCHEME_HTTP) ||
                         filter.hasDataScheme(IntentFilter.SCHEME_HTTPS));
@@ -2039,7 +2040,7 @@
                 mInstantAppRegistry.onPackageInstalledLPw(res.pkg, res.newUsers);
             }
 
-            final String packageName = res.pkg.getAppInfoPackageName();
+            final String packageName = res.pkg.getPackageName();
 
             // Determine the set of users who are adding this package for
             // the first time vs. those who are seeing an update.
@@ -2089,7 +2090,7 @@
                 // Send added for users that see the package for the first time
                 // sendPackageAddedForNewUsers also deals with system apps
                 int appId = UserHandle.getAppId(res.uid);
-                boolean isSystem = res.pkg.isSystemApp();
+                boolean isSystem = res.pkg.isSystem();
                 sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
                         virtualPreload /*startReceiver*/, appId, firstUserIds, firstInstantUserIds);
 
@@ -2153,7 +2154,7 @@
                             null /*package*/, null /*extras*/, 0 /*flags*/,
                             packageName /*targetPackage*/,
                             null /*finishedReceiver*/, updateUserIds, instantUserIds);
-                } else if (launchedForRestore && !isSystemApp(res.pkg)) {
+                } else if (launchedForRestore && !res.pkg.isSystem()) {
                     // First-install and we did a restore, so we're responsible for the
                     // first-launch broadcast.
                     if (DEBUG_BACKUP) {
@@ -2165,14 +2166,14 @@
                 }
 
                 // Send broadcast package appeared if external for all users
-                if (isExternal(res.pkg)) {
+                if (res.pkg.isExternalStorage()) {
                     if (!update) {
                         final StorageManager storage = mInjector.getStorageManager();
                         VolumeInfo volume =
                                 storage.findVolumeByUuid(
                                         res.pkg.getStorageUuid().toString());
                         int packageExternalStorageType =
-                                getPackageExternalStorageType(volume, isExternal(res.pkg));
+                                getPackageExternalStorageType(volume, res.pkg.isExternalStorage());
                         // If the package was installed externally, log it.
                         if (packageExternalStorageType != StorageEnums.UNKNOWN) {
                             FrameworkStatsLog.write(
@@ -2505,15 +2506,18 @@
                 packageName -> {
                     synchronized (m.mInstallLock) {
                         final AndroidPackage pkg;
+                        final PackageSetting ps;
                         final SharedUserSetting sharedUser;
+                        final String oldSeInfo;
                         synchronized (m.mLock) {
-                            PackageSetting ps = m.mSettings.getPackageLPr(packageName);
+                            ps = m.mSettings.getPackageLPr(packageName);
                             if (ps == null) {
                                 Slog.e(TAG, "Failed to find package setting " + packageName);
                                 return;
                             }
                             pkg = ps.pkg;
-                            sharedUser = ps.sharedUser;
+                            sharedUser = ps.getSharedUser();
+                            oldSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
                         }
 
                         if (pkg == null) {
@@ -2523,10 +2527,10 @@
                         final String newSeInfo = SELinuxMMAC.getSeInfo(pkg, sharedUser,
                                 m.mInjector.getCompatibility());
 
-                        if (!newSeInfo.equals(pkg.getSeInfo())) {
+                        if (!newSeInfo.equals(oldSeInfo)) {
                             Slog.i(TAG, "Updating seInfo for package " + packageName + " from: "
-                                    + pkg.getSeInfo() + " to: " + newSeInfo);
-                            pkg.mutate().setSeInfo(newSeInfo);
+                                    + oldSeInfo + " to: " + newSeInfo);
+                            ps.getPkgState().setOverrideSeInfo(newSeInfo);
                             m.prepareAppDataAfterInstallLIF(pkg);
                         }
                     }
@@ -2588,66 +2592,44 @@
         }
     }
 
-    @VisibleForTesting(visibility = Visibility.PRIVATE)
-    public static class SystemPartition {
-        public final File folder;
+    @VisibleForTesting
+    public static class ScanPartition extends SystemPartition {
+        @ScanFlags
         public final int scanFlag;
-        public final File appFolder;
-        @Nullable
-        public final File privAppFolder;
-        @Nullable
-        public final File overlayFolder;
 
-
-        private static boolean shouldScanPrivApps(@ScanFlags int scanFlags) {
-            if ((scanFlags & SCAN_AS_OEM) != 0) {
-                return false;
-            }
-            if (scanFlags == 0) {  // /system partition
-                return true;
-            }
-            if ((scanFlags
-                    & (SCAN_AS_VENDOR | SCAN_AS_ODM | SCAN_AS_PRODUCT | SCAN_AS_SYSTEM_EXT)) != 0) {
-                return true;
-            }
-            if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
-                return true;
-            }
-            return false;
+        public ScanPartition(@NonNull SystemPartition partition) {
+            super(partition);
+            scanFlag = scanFlagForPartition(partition);
         }
 
-        private SystemPartition(File folder, int scanFlag, boolean hasOverlays) {
-            this.folder = folder;
-            this.scanFlag = scanFlag;
-            this.appFolder = toCanonical(new File(folder, "app"));
-            this.privAppFolder = shouldScanPrivApps(scanFlag)
-                    ? toCanonical(new File(folder, "priv-app"))
-                    : null;
-            this.overlayFolder = hasOverlays ? toCanonical(new File(folder, "overlay")) : null;
+        /**
+         * Creates a partition containing the same folders as the original partition but with a
+         * different root folder. The new partition will include the scan flags of the original
+         * partition along with any specified additional scan flags.
+         */
+        public ScanPartition(@NonNull File folder, @NonNull ScanPartition original,
+                @ScanFlags int additionalScanFlag) {
+            super(folder, original);
+            this.scanFlag = original.scanFlag | additionalScanFlag;
         }
 
-        public boolean containsPrivApp(File scanFile) {
-            return FileUtils.contains(privAppFolder, scanFile);
-        }
-
-        public boolean containsApp(File scanFile) {
-            return FileUtils.contains(appFolder, scanFile);
-        }
-
-        public boolean containsPath(String path) {
-            return path.startsWith(folder.getPath() + "/");
-        }
-
-        public boolean containsPrivPath(String path) {
-            return privAppFolder != null && path.startsWith(privAppFolder.getPath() + "/");
-        }
-
-        private static File toCanonical(File dir) {
-            try {
-                return dir.getCanonicalFile();
-            } catch (IOException e) {
-                // failed to look up canonical path, continue with original one
-                return dir;
+        private static int scanFlagForPartition(PackagePartitions.SystemPartition partition) {
+            switch (partition.type) {
+                case PackagePartitions.PARTITION_SYSTEM:
+                    return 0;
+                case PackagePartitions.PARTITION_VENDOR:
+                    return SCAN_AS_VENDOR;
+                case PackagePartitions.PARTITION_ODM:
+                    return SCAN_AS_ODM;
+                case PackagePartitions.PARTITION_OEM:
+                    return SCAN_AS_OEM;
+                case PackagePartitions.PARTITION_PRODUCT:
+                    return SCAN_AS_PRODUCT;
+                case PackagePartitions.PARTITION_SYSTEM_EXT:
+                    return SCAN_AS_SYSTEM_EXT;
+                default:
+                    throw new IllegalStateException("Unable to determine scan flag for "
+                            + partition.folder);
             }
         }
     }
@@ -2751,7 +2733,7 @@
         mDirsToScanAsSystem = new ArrayList<>();
         mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS);
         mDirsToScanAsSystem.addAll(mApexManager.getActiveApexInfos().stream()
-                .map(ai -> resolveApexToSystemPartition(ai))
+                .map(PackageManagerService::resolveApexToScanPartition)
                 .filter(Objects::nonNull).collect(Collectors.toList()));
         Slog.d(TAG,
                 "Directories scanned as system partitions: [" + mDirsToScanAsSystem.stream().map(
@@ -2887,12 +2869,8 @@
             final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
             final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
 
-            PackageParser packageParser = new PackageParser();
-            packageParser.setSeparateProcesses(mSeparateProcesses);
-            packageParser.setOnlyCoreApps(mOnlyCore);
-            packageParser.setDisplayMetrics(mMetrics);
-            packageParser.setCacheDir(mCacheDir);
-            packageParser.setCallback(mPackageParserCallback);
+            PackageParser2 packageParser = new PackageParser2(mSeparateProcesses, mOnlyCore,
+                    mMetrics, mCacheDir, mPackageParserCallback);
 
             ExecutorService executorService = ParallelPackageParser.makeExecutorService();
             // Collect vendor/product/system_ext overlay packages. (Do this before scanning
@@ -2900,11 +2878,11 @@
             // For security and version matching reason, only consider overlay packages if they
             // reside in the right directory.
             for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
-                final SystemPartition partition = mDirsToScanAsSystem.get(i);
-                if (partition.overlayFolder == null) {
+                final ScanPartition partition = mDirsToScanAsSystem.get(i);
+                if (partition.getOverlayFolder() == null) {
                     continue;
                 }
-                scanDirTracedLI(partition.overlayFolder, systemParseFlags,
+                scanDirTracedLI(partition.getOverlayFolder(), systemParseFlags,
                         systemScanFlags | partition.scanFlag, 0,
                         packageParser, executorService);
             }
@@ -2917,17 +2895,22 @@
                         "Failed to load frameworks package; check log for warnings");
             }
             for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
-                final SystemPartition partition = mDirsToScanAsSystem.get(i);
-                if (partition.privAppFolder != null) {
-                    scanDirTracedLI(partition.privAppFolder, systemParseFlags,
+                final ScanPartition partition = mDirsToScanAsSystem.get(i);
+                if (partition.getPrivAppFolder() != null) {
+                    scanDirTracedLI(partition.getPrivAppFolder(), systemParseFlags,
                             systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0,
                             packageParser, executorService);
                 }
-                scanDirTracedLI(partition.appFolder, systemParseFlags,
+                scanDirTracedLI(partition.getAppFolder(), systemParseFlags,
                         systemScanFlags | partition.scanFlag, 0,
                         packageParser, executorService);
             }
 
+            // Parse overlay configuration files to set default enable state, mutability, and
+            // priority of system overlays.
+            mOverlayConfig = OverlayConfig.initializeSystemInstance(
+                    consumer -> mPmInternal.forEachPackage(
+                            pkg -> consumer.accept(pkg, pkg.isSystem())));
 
             // Prune any system packages that no longer exist.
             final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
@@ -3020,8 +3003,11 @@
                     + (systemPackagesCount == 0 ? 0 : systemScanTime / systemPackagesCount)
                     + " , cached: " + cachedSystemApps);
             if (mIsUpgrade && systemPackagesCount > 0) {
-                MetricsLogger.histogram(null, "ota_package_manager_system_app_avg_scan_time",
-                        ((int) systemScanTime) / systemPackagesCount);
+                //CHECKSTYLE:OFF IndentationCheck
+                FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
+                    BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME,
+                    systemScanTime / systemPackagesCount);
+                //CHECKSTYLE:ON IndentationCheck
             }
             if (!mOnlyCore) {
                 EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START,
@@ -3069,7 +3055,7 @@
                         // special privileges
                         removePackageLI(pkg, true);
                         try {
-                            final File codePath = new File(pkg.getAppInfoCodePath());
+                            final File codePath = new File(pkg.getCodePath());
                             scanPackageTracedLI(codePath, 0, scanFlags, 0, null);
                         } catch (PackageManagerException e) {
                             Slog.e(TAG, "Failed to parse updated, ex-system package: "
@@ -3105,7 +3091,7 @@
                         @ParseFlags int reparseFlags = 0;
                         @ScanFlags int rescanFlags = 0;
                         for (int i1 = 0, size = mDirsToScanAsSystem.size(); i1 < size; i1++) {
-                            SystemPartition partition = mDirsToScanAsSystem.get(i1);
+                            final ScanPartition partition = mDirsToScanAsSystem.get(i1);
                             if (partition.containsPrivApp(scanFile)) {
                                 reparseFlags = systemParseFlags;
                                 rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
@@ -3148,8 +3134,12 @@
                         + (dataPackagesCount == 0 ? 0 : dataScanTime / dataPackagesCount)
                         + " , cached: " + cachedNonSystemApps);
                 if (mIsUpgrade && dataPackagesCount > 0) {
-                    MetricsLogger.histogram(null, "ota_package_manager_data_app_avg_scan_time",
-                            ((int) dataScanTime) / dataPackagesCount);
+                    //CHECKSTYLE:OFF IndentationCheck
+                    FrameworkStatsLog.write(
+                        FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
+                        BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME,
+                        dataScanTime / dataPackagesCount);
+                    //CHECKSTYLE:OFF IndentationCheck
                 }
             }
             mExpectingBetter.clear();
@@ -3174,7 +3164,7 @@
 
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
-            updateAllSharedLibrariesLocked(null, Collections.unmodifiableMap(mPackages));
+            updateAllSharedLibrariesLocked(null, null, Collections.unmodifiableMap(mPackages));
 
             for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
                 // NOTE: We ignore potential failures here during a system scan (like
@@ -3202,7 +3192,7 @@
 
             // Now that we know all the packages we are keeping,
             // read and update their last usage times.
-            mPackageUsage.read(mPackages);
+            mPackageUsage.read(mSettings.mPackages);
             mCompilerStats.read();
 
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
@@ -3410,8 +3400,10 @@
             }
             mDexManager.load(userPackages);
             if (mIsUpgrade) {
-                MetricsLogger.histogram(null, "ota_package_manager_init_time",
-                        (int) (SystemClock.uptimeMillis() - startTime));
+                FrameworkStatsLog.write(
+                        FrameworkStatsLog.BOOT_TIME_EVENT_DURATION_REPORTED,
+                        BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_INIT_TIME,
+                        SystemClock.uptimeMillis() - startTime);
             }
         } // synchronized (mLock)
         } // synchronized (mInstallLock)
@@ -3501,7 +3493,8 @@
      * APK will be installed and the package will be disabled. To recover from this situation,
      * the user will need to go into system settings and re-enable the package.
      */
-    private boolean enableCompressedPackage(AndroidPackage stubPkg) {
+    private boolean enableCompressedPackage(AndroidPackage stubPkg,
+            @NonNull PackageSetting stubPkgSetting) {
         final int parseFlags = mDefParseFlags | PackageParser.PARSE_CHATTY
                 | PackageParser.PARSE_ENFORCE_CODE;
         synchronized (mInstallLock) {
@@ -3512,7 +3505,7 @@
                 synchronized (mLock) {
                     prepareAppDataAfterInstallLIF(pkg);
                     try {
-                        updateSharedLibrariesLocked(pkg, null,
+                        updateSharedLibrariesLocked(pkg, stubPkgSetting, null, null,
                                 Collections.unmodifiableMap(mPackages));
                     } catch (PackageManagerException e) {
                         Slog.e(TAG, "updateAllSharedLibrariesLPw failed: ", e);
@@ -4035,15 +4028,13 @@
                 }
 
                 ArraySet<String> domains = null;
-                if (pkg.getActivities() != null) {
-                    for (ParsedActivity a : pkg.getActivities()) {
-                        for (ParsedActivityIntentInfo filter : a.intents) {
-                            if (hasValidDomains(filter)) {
-                                if (domains == null) {
-                                    domains = new ArraySet<>();
-                                }
-                                domains.addAll(filter.getHostsList());
+                for (ParsedActivity a : pkg.getActivities()) {
+                    for (ParsedIntentInfo filter : a.getIntents()) {
+                        if (hasValidDomains(filter)) {
+                            if (domains == null) {
+                                domains = new ArraySet<>();
                             }
+                            domains.addAll(filter.getHostsList());
                         }
                     }
                 }
@@ -4171,7 +4162,7 @@
                     ? Collections.emptySet() : permissionsState.getPermissions(userId);
 
             PackageInfo packageInfo = PackageInfoUtils.generate(p, gids, flags,
-                    ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId);
+                    ps.firstInstallTime, ps.lastUpdateTime, permissions, state, userId, ps);
 
             if (packageInfo == null) {
                 return null;
@@ -4233,7 +4224,7 @@
                 throw new SecurityException("Package " + packageName + " is currently frozen!");
             }
 
-            if (!userKeyUnlocked && !ps.pkg.isEncryptionAware()) {
+            if (!userKeyUnlocked && !AndroidPackageUtils.isEncryptionAware(ps.pkg)) {
                 throw new SecurityException("Package " + packageName + " is not encryption aware!");
             }
         }
@@ -4314,7 +4305,7 @@
             }
 
             AndroidPackage p = mPackages.get(packageName);
-            if (matchFactoryOnly && p != null && !isSystemApp(p)) {
+            if (matchFactoryOnly && p != null && !p.isSystem()) {
                 return null;
             }
             if (DEBUG_PACKAGE_INFO)
@@ -4369,9 +4360,9 @@
                 return false;
             }
             final boolean visibleToInstantApp =
-                    (activity.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                    (activity.getFlags() & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
             final boolean explicitlyVisibleToInstantApp =
-                    (activity.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
+                    (activity.getFlags() & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && explicitlyVisibleToInstantApp;
         } else if (type == TYPE_RECEIVER) {
             final ParsedActivity activity = mComponentResolver.getReceiver(component);
@@ -4379,20 +4370,18 @@
                 return false;
             }
             final boolean visibleToInstantApp =
-                    (activity.flags & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
+                    (activity.getFlags() & ActivityInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
             final boolean explicitlyVisibleToInstantApp =
-                    (activity.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
+                    (activity.getFlags() & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && !explicitlyVisibleToInstantApp;
         } else if (type == TYPE_SERVICE) {
             final ParsedService service = mComponentResolver.getService(component);
             return service != null
-                    ? (service.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
-                    : false;
+                    && (service.getFlags() & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
         } else if (type == TYPE_PROVIDER) {
             final ParsedProvider provider = mComponentResolver.getProvider(component);
             return provider != null
-                    ? (provider.getFlags() & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
-                    : false;
+                    && (provider.getFlags() & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0;
         } else if (type == TYPE_UNKNOWN) {
             return isComponentVisibleToInstantApp(component);
         }
@@ -4599,7 +4588,7 @@
         // reader
         synchronized (mLock) {
             final AndroidPackage p = mPackages.get(packageName);
-            if (p != null && p.isMatch(flags)) {
+            if (p != null && AndroidPackageUtils.isMatchForSystemOnly(p, flags)) {
                 PackageSetting ps = getPackageSettingInternal(p.getPackageName(), callingUid);
                 if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
                     return -1;
@@ -4629,7 +4618,7 @@
         // reader
         synchronized (mLock) {
             final AndroidPackage p = mPackages.get(packageName);
-            if (p != null && p.isMatch(flags)) {
+            if (p != null && AndroidPackageUtils.isMatchForSystemOnly(p, flags)) {
                 PackageSetting ps = getPackageSetting(p.getPackageName());
                 if (shouldFilterApplicationLocked(ps, callingUid, userId)) {
                     return null;
@@ -4681,7 +4670,7 @@
                 return null;
             }
             ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(ps.pkg, flags,
-                    ps.readUserState(userId), userId);
+                    ps.readUserState(userId), userId, ps);
             if (ai != null) {
                 ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
             }
@@ -4733,7 +4722,7 @@
                 }
                 // Note: isEnabledLP() does not apply here - always return info
                 ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(
-                        p, flags, ps.readUserState(userId), userId);
+                        p, flags, ps.readUserState(userId), userId, ps);
                 if (ai != null) {
                     ai.packageName = resolveExternalPackageNameLPr(p);
                 }
@@ -5117,7 +5106,7 @@
                     return null;
                 }
                 return PackageInfoUtils.generateActivityInfo(pkg,
-                        a, flags, ps.readUserState(userId), userId);
+                        a, flags, ps.readUserState(userId), userId, ps);
             }
             if (mResolveComponentName.equals(component)) {
                 return PackageParser.generateActivityInfo(
@@ -5165,8 +5154,8 @@
                     ps, callingUid, component, TYPE_ACTIVITY, callingUserId)) {
                 return false;
             }
-            for (int i=0; i<a.intents.size(); i++) {
-                if (a.intents.get(i).match(intent.getAction(), resolvedType, intent.getScheme(),
+            for (int i=0; i< a.getIntents().size(); i++) {
+                if (a.getIntents().get(i).match(intent.getAction(), resolvedType, intent.getScheme(),
                         intent.getData(), intent.getCategories(), TAG) >= 0) {
                     return true;
                 }
@@ -5204,7 +5193,7 @@
                     return null;
                 }
                 return PackageInfoUtils.generateActivityInfo(pkg,
-                        a, flags, ps.readUserState(userId), userId);
+                        a, flags, ps.readUserState(userId), userId, ps);
             }
         }
         return null;
@@ -5425,7 +5414,7 @@
                     return null;
                 }
                 return PackageInfoUtils.generateServiceInfo(pkg,
-                        s, flags, ps.readUserState(userId), userId);
+                        s, flags, ps.readUserState(userId), userId, ps);
             }
         }
         return null;
@@ -5459,7 +5448,7 @@
                     return null;
                 }
                 PackageUserState state = ps.readUserState(userId);
-                return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, userId);
+                return PackageInfoUtils.generateProviderInfo(pkg, p, flags, state, userId, ps);
             }
         }
         return null;
@@ -6128,8 +6117,8 @@
     @Override
     public ResolveInfo resolveIntent(Intent intent, String resolvedType,
             int flags, int userId) {
-        return resolveIntentInternal(intent, resolvedType, flags, userId, false,
-                Binder.getCallingUid());
+        return resolveIntentInternal(intent, resolvedType, flags, 0 /*privateResolveFlags*/,
+                userId, false, Binder.getCallingUid());
     }
 
     /**
@@ -6137,8 +6126,9 @@
      * However, if {@code resolveForStart} is {@code true}, all instant apps are visible
      * since we need to allow the system to start any installed application.
      */
-    private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType,
-            int flags, int userId, boolean resolveForStart, int filterCallingUid) {
+    private ResolveInfo resolveIntentInternal(Intent intent, String resolvedType, int flags,
+            @PrivateResolveFlags int privateResolveFlags, int userId, boolean resolveForStart,
+            int filterCallingUid) {
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "resolveIntent");
 
@@ -6150,11 +6140,13 @@
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, filterCallingUid, userId, resolveForStart, true /*allowDynamicSplits*/);
+                    flags, privateResolveFlags, filterCallingUid, userId, resolveForStart,
+                    true /*allowDynamicSplits*/);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
-                    chooseBestActivity(intent, resolvedType, flags, query, userId);
+                    chooseBestActivity(
+                            intent, resolvedType, flags, privateResolveFlags, query, userId);
             return bestChoice;
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -6312,7 +6304,7 @@
     }
 
     private ResolveInfo chooseBestActivity(Intent intent, String resolvedType,
-            int flags, List<ResolveInfo> query, int userId) {
+            int flags, int privateResolveFlags, List<ResolveInfo> query, int userId) {
         if (query != null) {
             final int N = query.size();
             if (N == 1) {
@@ -6354,6 +6346,10 @@
                         }
                     }
                 }
+                if ((privateResolveFlags
+                        & PackageManagerInternal.RESOLVE_NON_RESOLVER_ONLY) != 0) {
+                    return null;
+                }
                 ri = new ResolveInfo(mResolveInfo);
                 ri.activityInfo = new ActivityInfo(ri.activityInfo);
                 ri.activityInfo.labelRes = ResolverActivity.getLabelRes(intent.getAction());
@@ -6767,13 +6763,13 @@
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
         return queryIntentActivitiesInternal(
-                intent, resolvedType, flags, Binder.getCallingUid(), userId,
-                false /*resolveForStart*/, true /*allowDynamicSplits*/);
+                intent, resolvedType, flags, 0 /*privateResolveFlags*/, Binder.getCallingUid(),
+                userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
     }
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, int flags, int filterCallingUid, int userId,
-            boolean resolveForStart, boolean allowDynamicSplits) {
+            String resolvedType, int flags, @PrivateResolveFlags int privateResolveFlags,
+            int filterCallingUid, int userId, boolean resolveForStart, boolean allowDynamicSplits) {
         if (!mUserManager.exists(userId)) return Collections.emptyList();
         final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
         mPermissionManager.enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -6858,7 +6854,7 @@
 
                 // Check for results in the current profile.
                 result = filterIfNotSystemUser(mComponentResolver.queryActivities(
-                        intent, resolvedType, flags, userId), userId);
+                        intent, resolvedType, flags, privateResolveFlags, userId), userId);
                 addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                         false /*skipPackageCheck*/);
                 // Check for cross profile results.
@@ -6957,7 +6953,7 @@
                         | PackageManager.GET_RESOLVED_FILTER
                         | PackageManager.MATCH_INSTANT
                         | PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY,
-                    userId);
+                    0, userId);
             for (int i = instantApps.size() - 1; i >= 0; --i) {
                 final ResolveInfo info = instantApps.get(i);
                 final String packageName = info.activityInfo.packageName;
@@ -7061,7 +7057,7 @@
             return null;
         }
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
-                resolvedType, flags, parentUserId);
+                resolvedType, flags, 0, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
             return null;
@@ -7246,8 +7242,9 @@
         failureActivityIntent.setPackage(packageName);
         // IMPORTANT: disallow dynamic splits to avoid an infinite loop
         final List<ResolveInfo> result = queryIntentActivitiesInternal(
-                failureActivityIntent, null /*resolvedType*/, 0 /*flags*/, filterCallingUid, userId,
-                false /*resolveForStart*/, false /*allowDynamicSplits*/);
+                failureActivityIntent, null /*resolvedType*/, 0 /*flags*/,
+                0 /*privateResolveFlags*/, filterCallingUid, userId, false /*resolveForStart*/,
+                false /*allowDynamicSplits*/);
         final int NR = result.size();
         if (NR > 0) {
             for (int i = 0; i < NR; i++) {
@@ -7502,7 +7499,7 @@
             String resolvedType, int flags, int sourceUserId) {
         int targetUserId = filter.getTargetUserId();
         List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
-                resolvedType, flags, targetUserId);
+                resolvedType, flags, 0, targetUserId);
         if (resultTargetUser != null && isUserEnabled(targetUserId)) {
             // If all the matches in the target profile are suspended, return null.
             for (int i = resultTargetUser.size() - 1; i >= 0; i--) {
@@ -8289,7 +8286,7 @@
                             continue;
                         }
                         ai = PackageInfoUtils.generateApplicationInfo(ps.pkg, effectiveFlags,
-                                ps.readUserState(userId), userId);
+                                ps.readUserState(userId), userId, ps);
                         if (ai != null) {
                             ai.packageName = resolveExternalPackageNameLPr(ps.pkg);
                         }
@@ -8315,7 +8312,7 @@
                             continue;
                         }
                         ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(p, flags,
-                                ps.readUserState(userId), userId);
+                                ps.readUserState(userId), userId, ps);
                         if (ai != null) {
                             ai.packageName = resolveExternalPackageNameLPr(p);
                             list.add(ai);
@@ -8468,13 +8465,13 @@
                 final boolean matchesAware = ((flags & MATCH_DIRECT_BOOT_AWARE) != 0)
                         && p.isDirectBootAware();
 
-                if ((p.getFlags() & ApplicationInfo.FLAG_PERSISTENT) != 0
-                        && (!mSafeMode || isSystemApp(p))
+                if (p.isPersistent()
+                        && (!mSafeMode || p.isSystem())
                         && (matchesUnaware || matchesAware)) {
                     PackageSetting ps = mSettings.mPackages.get(p.getPackageName());
                     if (ps != null) {
                         ApplicationInfo ai = PackageInfoUtils.generateApplicationInfo(p, flags,
-                                ps.readUserState(userId), userId);
+                                ps.readUserState(userId), userId, ps);
                         if (ai != null) {
                             finalList.add(ai);
                         }
@@ -8580,7 +8577,7 @@
                 return null;
             }
             final ParsedInstrumentation i = mInstrumentation.get(component);
-            return PackageInfoUtils.generateInstrumentationInfo(i, pkg, flags);
+            return PackageInfoUtils.generateInstrumentationInfo(i, pkg, flags, callingUserId, ps);
         }
     }
 
@@ -8593,11 +8590,12 @@
         if (shouldFilterApplicationLocked(ps, callingUid, callingUserId)) {
             return ParceledListSlice.emptyList();
         }
-        return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags));
+        return new ParceledListSlice<>(queryInstrumentationInternal(targetPackage, flags,
+                callingUserId));
     }
 
     private @NonNull List<InstrumentationInfo> queryInstrumentationInternal(String targetPackage,
-            int flags) {
+            int flags, int userId) {
         ArrayList<InstrumentationInfo> finalList = new ArrayList<>();
 
         // reader
@@ -8607,10 +8605,12 @@
                 final ParsedInstrumentation p = i.next();
                 if (targetPackage == null
                         || targetPackage.equals(p.getTargetPackage())) {
-                    AndroidPackage pkg = mPackages.get(p.getPackageName());
+                    String packageName = p.getPackageName();
+                    AndroidPackage pkg = mPackages.get(packageName);
+                    PackageSetting pkgSetting = getPackageSetting(packageName);
                     if (pkg != null) {
                         InstrumentationInfo ii = PackageInfoUtils.generateInstrumentationInfo(p,
-                                pkg, flags);
+                                pkg, flags, userId, pkgSetting);
                         if (ii != null) {
                             finalList.add(ii);
                         }
@@ -8623,7 +8623,7 @@
     }
 
     private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags,
-            long currentTime, PackageParser packageParser, ExecutorService executorService) {
+            long currentTime, PackageParser2 packageParser, ExecutorService executorService) {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]");
         try {
             scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService);
@@ -8633,7 +8633,7 @@
     }
 
     private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime,
-            PackageParser packageParser, ExecutorService executorService) {
+            PackageParser2 packageParser, ExecutorService executorService) {
         final File[] files = scanDir.listFiles();
         if (ArrayUtils.isEmpty(files)) {
             Log.d(TAG, "No files in app dir " + scanDir);
@@ -8737,7 +8737,8 @@
 
         try {
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "collectCertificates");
-            ApkParseUtils.collectCertificates(parsedPackage, skipVerify);
+            parsedPackage.setSigningDetails(
+                    ParsingPackageUtils.collectCertificates(parsedPackage, skipVerify));
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
         } finally {
@@ -8791,16 +8792,13 @@
     private AndroidPackage scanPackageLI(File scanFile, int parseFlags, int scanFlags,
             long currentTime, UserHandle user) throws PackageManagerException {
         if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile);
-        PackageParser pp = new PackageParser();
-        pp.setSeparateProcesses(mSeparateProcesses);
-        pp.setOnlyCoreApps(mOnlyCore);
-        pp.setDisplayMetrics(mMetrics);
-        pp.setCallback(mPackageParserCallback);
+        PackageParser2 pp = new PackageParser2(mSeparateProcesses, mOnlyCore, mMetrics, null,
+                mPackageParserCallback);
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         final ParsedPackage parsedPackage;
         try {
-            parsedPackage = pp.parseParsedPackage(scanFile, parseFlags, false);
+            parsedPackage = pp.parsePackage(scanFile, parseFlags, false);
         } catch (PackageParserException e) {
             throw PackageManagerException.from(e);
         } finally {
@@ -8886,18 +8884,6 @@
         final boolean pkgAlreadyExists;
         PackageSetting pkgSetting;
 
-        // NOTE: installPackageLI() has the same code to setup the package's
-        // application info. This probably should be done lower in the call
-        // stack [such as scanPackageOnly()]. However, we verify the application
-        // info prior to that [in scanPackageNew()] and thus have to setup
-        // the application info early.
-        // TODO(b/135203078): Remove all of these application info calls
-        parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid())
-                .setApplicationInfoCodePath(parsedPackage.getCodePath())
-                .setApplicationInfoResourcePath(parsedPackage.getCodePath())
-                .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath())
-                .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths());
-
         synchronized (mLock) {
             renamedPkgName = mSettings.getRenamedPackageLPr(parsedPackage.getRealPackage());
             final String realPkgName = getRealPackageName(parsedPackage, renamedPkgName);
@@ -8950,8 +8936,8 @@
                     final ScanRequest request = new ScanRequest(parsedPackage, sharedUserSetting,
                             null, disabledPkgSetting /* pkgSetting */,
                             null /* disabledPkgSetting */, null /* originalPkgSetting */,
-                            null, parseFlags, scanFlags, isPlatformPackage, user);
-                    applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage);
+                            null, parseFlags, scanFlags, isPlatformPackage, user, null);
+                    applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage, true);
                     final ScanResult scanResult =
                             scanPackageOnlyLI(request, mInjector, mFactoryTest, -1L);
                     if (scanResult.existingSettingCopied && scanResult.request.pkgSetting != null) {
@@ -9085,7 +9071,7 @@
         }
 
         final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, scanFlags
-                | SCAN_UPDATE_SIGNATURE, currentTime, user);
+                | SCAN_UPDATE_SIGNATURE, currentTime, user, null);
         if (scanResult.success) {
             synchronized (mLock) {
                 boolean appIdCreated = false;
@@ -9225,9 +9211,15 @@
             return;
         }
 
-        List<AndroidPackage> pkgs;
+        List<PackageSetting> pkgSettings;
         synchronized (mLock) {
-            pkgs = PackageManagerServiceUtils.getPackagesForDexopt(mPackages.values(), this);
+            pkgSettings = PackageManagerServiceUtils.getPackagesForDexopt(
+                    mSettings.mPackages.values(), this);
+        }
+
+        List<AndroidPackage> pkgs = new ArrayList<>(pkgSettings.size());
+        for (int index = 0; index < pkgSettings.size(); index++) {
+            pkgs.add(pkgSettings.get(index).pkg);
         }
 
         final long startTime = System.nanoTime();
@@ -9272,7 +9264,7 @@
 
             boolean useProfileForDexopt = false;
 
-            if ((isFirstBoot() || isDeviceUpgrading()) && isSystemApp(pkg)) {
+            if ((isFirstBoot() || isDeviceUpgrading()) && pkg.isSystem()) {
                 // Copy over initial preopt profiles since we won't get any JIT samples for methods
                 // that are already compiled.
                 File profileFile = new File(getPrebuildProfilePath(pkg));
@@ -9426,16 +9418,16 @@
 
     @GuardedBy("mLock")
     private void notifyPackageUseLocked(String packageName, int reason) {
-        final AndroidPackage p = mPackages.get(packageName);
-        if (p == null) {
+        final PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
+        if (pkgSetting == null) {
             return;
         }
-        p.mutate().setLastPackageUsageTimeInMills(reason, System.currentTimeMillis());
+        pkgSetting.getPkgState().setLastPackageUsageTimeInMills(reason, System.currentTimeMillis());
     }
 
     @Override
-    public void notifyDexLoad(String loadingPackageName, List<String> classLoaderNames,
-            List<String> classPaths, String loaderIsa) {
+    public void notifyDexLoad(String loadingPackageName, Map<String, String> classLoaderContextMap,
+            String loaderIsa) {
         int userId = UserHandle.getCallingUserId();
         ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId);
         if (ai == null) {
@@ -9443,7 +9435,7 @@
                 + loadingPackageName + ", user=" + userId);
             return;
         }
-        mDexManager.notifyDexLoad(ai, classLoaderNames, classPaths, loaderIsa, userId);
+        mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId);
     }
 
     @Override
@@ -9558,19 +9550,21 @@
     // if the package can now be considered up to date for the given filter.
     private int performDexOptInternal(DexoptOptions options) {
         AndroidPackage p;
+        PackageSetting pkgSetting;
         synchronized (mLock) {
             p = mPackages.get(options.getPackageName());
-            if (p == null) {
+            pkgSetting = mSettings.getPackageLPr(options.getPackageName());
+            if (p == null || pkgSetting == null) {
                 // Package could not be found. Report failure.
                 return PackageDexOptimizer.DEX_OPT_FAILED;
             }
-            mPackageUsage.maybeWriteAsync(mPackages);
+            mPackageUsage.maybeWriteAsync(mSettings.mPackages);
             mCompilerStats.maybeWriteAsync();
         }
         long callingId = Binder.clearCallingIdentity();
         try {
             synchronized (mInstallLock) {
-                return performDexOptInternalWithDependenciesLI(p, options);
+                return performDexOptInternalWithDependenciesLI(p, pkgSetting, options);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -9590,7 +9584,7 @@
     }
 
     private int performDexOptInternalWithDependenciesLI(AndroidPackage p,
-            DexoptOptions options) {
+            @NonNull PackageSetting pkgSetting, DexoptOptions options) {
         // Select the dex optimizer based on the force parameter.
         // Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
         //       allocate an object here.
@@ -9605,9 +9599,10 @@
         // at boot, or background job), the passed 'targetCompilerFilter' stays the same,
         // and the first package that uses the library will dexopt it. The
         // others will see that the compiled code for the library is up to date.
-        Collection<SharedLibraryInfo> deps = findSharedLibraries(p);
-        final String[] instructionSets = getAppDexInstructionSets(p.getPrimaryCpuAbi(),
-                p.getSecondaryCpuAbi());
+        Collection<SharedLibraryInfo> deps = findSharedLibraries(pkgSetting);
+        final String[] instructionSets = getAppDexInstructionSets(
+                AndroidPackageUtils.getPrimaryCpuAbi(p, pkgSetting),
+                AndroidPackageUtils.getSecondaryCpuAbi(p, pkgSetting));
         if (!deps.isEmpty()) {
             DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(),
                     options.getCompilationReason(), options.getCompilerFilter(),
@@ -9615,12 +9610,14 @@
                     options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY);
             for (SharedLibraryInfo info : deps) {
                 AndroidPackage depPackage = null;
+                PackageSetting depPackageSetting = null;
                 synchronized (mLock) {
                     depPackage = mPackages.get(info.getPackageName());
+                    depPackageSetting = mSettings.getPackageLPr(info.getPackageName());
                 }
-                if (depPackage != null) {
+                if (depPackage != null && depPackageSetting != null) {
                     // TODO: Analyze and investigate if we (should) profile libraries.
-                    pdo.performDexOpt(depPackage, instructionSets,
+                    pdo.performDexOpt(depPackage, depPackageSetting, instructionSets,
                             getOrCreateCompilerPackageStats(depPackage),
                             mDexManager.getPackageUseInfoOrDefault(depPackage.getPackageName()),
                             libraryOptions);
@@ -9629,7 +9626,8 @@
                 }
             }
         }
-        return pdo.performDexOpt(p, instructionSets,
+
+        return pdo.performDexOpt(p, pkgSetting, instructionSets,
                 getOrCreateCompilerPackageStats(p),
                 mDexManager.getPackageUseInfoOrDefault(p.getPackageName()), options);
     }
@@ -9672,11 +9670,11 @@
         }
     }
 
-    private static List<SharedLibraryInfo> findSharedLibraries(AndroidPackage p) {
-        if (p.getUsesLibraryInfos() != null) {
+    private static List<SharedLibraryInfo> findSharedLibraries(PackageSetting pkgSetting) {
+        if (!pkgSetting.getPkgState().getUsesLibraryInfos().isEmpty()) {
             ArrayList<SharedLibraryInfo> retValue = new ArrayList<>();
             Set<String> collectedNames = new HashSet<>();
-            for (SharedLibraryInfo info : p.getUsesLibraryInfos()) {
+            for (SharedLibraryInfo info : pkgSetting.getPkgState().getUsesLibraryInfos()) {
                 findSharedLibrariesRecursive(info, retValue, collectedNames);
             }
             return retValue;
@@ -9699,15 +9697,16 @@
         }
     }
 
-    List<AndroidPackage> findSharedNonSystemLibraries(AndroidPackage pkg) {
-        List<SharedLibraryInfo> deps = findSharedLibraries(pkg);
+    List<PackageSetting> findSharedNonSystemLibraries(PackageSetting pkgSetting) {
+        List<SharedLibraryInfo> deps = findSharedLibraries(pkgSetting);
         if (!deps.isEmpty()) {
-            ArrayList<AndroidPackage> retValue = new ArrayList<>();
+            List<PackageSetting> retValue = new ArrayList<>();
             synchronized (mLock) {
                 for (SharedLibraryInfo info : deps) {
-                    AndroidPackage depPackage = mPackages.get(info.getPackageName());
-                    if (depPackage != null) {
-                        retValue.add(depPackage);
+                    PackageSetting depPackageSetting =
+                            mSettings.getPackageLPr(info.getPackageName());
+                    if (depPackageSetting != null && depPackageSetting.pkg != null) {
+                        retValue.add(depPackageSetting);
                     }
                 }
             }
@@ -9779,7 +9778,7 @@
     }
 
     public void shutdown() {
-        mPackageUsage.writeNow(mPackages);
+        mPackageUsage.writeNow(mSettings.mPackages);
         mCompilerStats.writeNow();
         mDexManager.writePackageDexUsageNow();
         PackageWatchdog.getInstance(mContext).writeNow();
@@ -9825,9 +9824,11 @@
         enforceSystemOrRoot("forceDexOpt");
 
         AndroidPackage pkg;
+        PackageSetting pkgSetting;
         synchronized (mLock) {
             pkg = mPackages.get(packageName);
-            if (pkg == null) {
+            pkgSetting = mSettings.getPackageLPr(packageName);
+            if (pkg == null || pkgSetting == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
         }
@@ -9837,8 +9838,7 @@
 
             // Whoever is calling forceDexOpt wants a compiled package.
             // Don't use profiles since that may cause compilation to be skipped.
-            final int res = performDexOptInternalWithDependenciesLI(
-                    pkg,
+            final int res = performDexOptInternalWithDependenciesLI(pkg, pkgSetting,
                     new DexoptOptions(packageName,
                             getDefaultCompilerFilter(),
                             DexoptOptions.DEXOPT_FORCE | DexoptOptions.DEXOPT_BOOT_COMPLETE));
@@ -9974,7 +9974,7 @@
         // Or:
         // - Package manager is in a state where package isn't scanned yet. This will
         //   get called again after scanning to fix the dependencies.
-        if (pkg.isLibrary()) {
+        if (AndroidPackageUtils.isLibrary(pkg)) {
             if (pkg.getStaticSharedLibName() != null) {
                 SharedLibraryInfo definedLibrary = getSharedLibraryInfoLPr(
                         pkg.getStaticSharedLibName(), pkg.getStaticSharedLibVersion());
@@ -9995,40 +9995,44 @@
 
     @GuardedBy("mLock")
     private void addSharedLibraryLPr(AndroidPackage pkg, Set<String> usesLibraryFiles,
-            SharedLibraryInfo libInfo, AndroidPackage changingLib) {
+            SharedLibraryInfo libInfo, @Nullable AndroidPackage changingLib,
+            @Nullable PackageSetting changingLibSetting) {
         if (libInfo.getPath() != null) {
             usesLibraryFiles.add(libInfo.getPath());
             return;
         }
-        AndroidPackage p = mPackages.get(libInfo.getPackageName());
+        AndroidPackage pkgForCodePaths = mPackages.get(libInfo.getPackageName());
+        PackageSetting pkgSetting = mSettings.getPackageLPr(libInfo.getPackageName());
         if (changingLib != null && changingLib.getPackageName().equals(libInfo.getPackageName())) {
             // If we are doing this while in the middle of updating a library apk,
             // then we need to make sure to use that new apk for determining the
             // dependencies here.  (We haven't yet finished committing the new apk
             // to the package manager state.)
-            if (p == null || p.getPackageName().equals(changingLib.getPackageName())) {
-                p = changingLib;
+            if (pkgForCodePaths == null
+                    || pkgForCodePaths.getPackageName().equals(changingLib.getPackageName())) {
+                pkgForCodePaths = changingLib;
+                pkgSetting = changingLibSetting;
             }
         }
-        if (p != null) {
-            usesLibraryFiles.addAll(p.getAllCodePaths());
+        if (pkgForCodePaths != null) {
+            usesLibraryFiles.addAll(AndroidPackageUtils.getAllCodePaths(pkgForCodePaths));
             // If the package provides libraries, add the dependency to them.
-            applyDefiningSharedLibraryUpdateLocked(pkg, libInfo, (definingLibrary, dependency) -> {
-                definingLibrary.addDependency(dependency);
-            });
-            if (p.getUsesLibraryFiles() != null) {
-                Collections.addAll(usesLibraryFiles, p.getUsesLibraryFiles());
+            applyDefiningSharedLibraryUpdateLocked(pkg, libInfo, SharedLibraryInfo::addDependency);
+            if (pkgSetting != null) {
+                usesLibraryFiles.addAll(pkgSetting.getPkgState().getUsesLibraryFiles());
             }
         }
     }
 
     @GuardedBy("mLock")
-    private void updateSharedLibrariesLocked(AndroidPackage pkg,
-            AndroidPackage changingLib, Map<String, AndroidPackage> availablePackages)
-                    throws PackageManagerException {
-        final ArrayList<SharedLibraryInfo> sharedLibraryInfos =
-                collectSharedLibraryInfos(pkg, availablePackages, mSharedLibraries, null);
-        executeSharedLibrariesUpdateLPr(pkg, changingLib, sharedLibraryInfos);
+    private void updateSharedLibrariesLocked(AndroidPackage pkg, PackageSetting pkgSetting,
+            @Nullable AndroidPackage changingLib, @Nullable PackageSetting changingLibSetting,
+            Map<String, AndroidPackage> availablePackages)
+            throws PackageManagerException {
+        final ArrayList<SharedLibraryInfo> sharedLibraryInfos = collectSharedLibraryInfos(
+                pkgSetting.pkg, availablePackages, mSharedLibraries, null);
+        executeSharedLibrariesUpdateLPr(pkg, pkgSetting, changingLib, changingLibSetting,
+                sharedLibraryInfos);
     }
 
     private static ArrayList<SharedLibraryInfo> collectSharedLibraryInfos(AndroidPackage pkg,
@@ -10043,18 +10047,18 @@
         // that libraries are searched in the correct order) and must have no
         // duplicates.
         ArrayList<SharedLibraryInfo> usesLibraryInfos = null;
-        if (pkg.getUsesLibraries() != null) {
+        if (!pkg.getUsesLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesLibraries(), null, null,
                     pkg.getPackageName(), true, pkg.getTargetSdkVersion(), null,
                     availablePackages, existingLibraries, newLibraries);
         }
-        if (pkg.getUsesStaticLibraries() != null) {
+        if (!pkg.getUsesStaticLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesStaticLibraries(),
                     pkg.getUsesStaticLibrariesVersions(), pkg.getUsesStaticLibrariesCertDigests(),
                     pkg.getPackageName(), true, pkg.getTargetSdkVersion(), usesLibraryInfos,
                     availablePackages, existingLibraries, newLibraries);
         }
-        if (pkg.getUsesOptionalLibraries() != null) {
+        if (!pkg.getUsesOptionalLibraries().isEmpty()) {
             usesLibraryInfos = collectSharedLibraryInfos(pkg.getUsesOptionalLibraries(),
                     null, null, pkg.getPackageName(), false, pkg.getTargetSdkVersion(),
                     usesLibraryInfos, availablePackages, existingLibraries, newLibraries);
@@ -10063,25 +10067,27 @@
     }
 
     private void executeSharedLibrariesUpdateLPr(AndroidPackage pkg,
-            AndroidPackage changingLib, ArrayList<SharedLibraryInfo> usesLibraryInfos) {
+            @NonNull PackageSetting pkgSetting, @Nullable AndroidPackage changingLib,
+            @Nullable PackageSetting changingLibSetting,
+            ArrayList<SharedLibraryInfo> usesLibraryInfos) {
         // If the package provides libraries, clear their old dependencies.
         // This method will set them up again.
         applyDefiningSharedLibraryUpdateLocked(pkg, null, (definingLibrary, dependency) -> {
             definingLibrary.clearDependencies();
         });
         if (usesLibraryInfos != null) {
-            pkg.mutate().setUsesLibraryInfos(usesLibraryInfos);
+            pkgSetting.getPkgState().setUsesLibraryInfos(usesLibraryInfos);
             // Use LinkedHashSet to preserve the order of files added to
             // usesLibraryFiles while eliminating duplicates.
             Set<String> usesLibraryFiles = new LinkedHashSet<>();
             for (SharedLibraryInfo libInfo : usesLibraryInfos) {
-                addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib);
+                addSharedLibraryLPr(pkg, usesLibraryFiles, libInfo, changingLib,
+                        changingLibSetting);
             }
-            pkg.mutate().setUsesLibraryFiles(usesLibraryFiles.toArray(
-                    new String[usesLibraryFiles.size()]));
+            pkgSetting.getPkgState().setUsesLibraryFiles(new ArrayList<>(usesLibraryFiles));
         } else {
-            pkg.mutate().setUsesLibraryInfos(null)
-                    .setUsesLibraryFiles(null);
+            pkgSetting.getPkgState().setUsesLibraryInfos(Collections.emptyList())
+                    .setUsesLibraryFiles(Collections.emptyList());
         }
     }
 
@@ -10197,27 +10203,32 @@
 
     @GuardedBy("mLock")
     private ArrayList<AndroidPackage> updateAllSharedLibrariesLocked(
-            AndroidPackage updatedPkg,
+            @Nullable AndroidPackage updatedPkg, @Nullable PackageSetting updatedPkgSetting,
             Map<String, AndroidPackage> availablePackages) {
         ArrayList<AndroidPackage> resultList = null;
         // Set of all descendants of a library; used to eliminate cycles
         ArraySet<String> descendants = null;
         // The current list of packages that need updating
-        ArrayList<AndroidPackage> needsUpdating = null;
-        if (updatedPkg != null) {
+        List<Pair<AndroidPackage, PackageSetting>> needsUpdating = null;
+        if (updatedPkg != null && updatedPkgSetting != null) {
             needsUpdating = new ArrayList<>(1);
-            needsUpdating.add(updatedPkg);
+            needsUpdating.add(Pair.create(updatedPkg, updatedPkgSetting));
         }
         do {
-            final AndroidPackage changingPkg =
+            final Pair<AndroidPackage, PackageSetting> changingPkgPair =
                     (needsUpdating == null) ? null : needsUpdating.remove(0);
+            final AndroidPackage changingPkg = changingPkgPair != null
+                    ? changingPkgPair.first : null;
+            final PackageSetting changingPkgSetting = changingPkgPair != null
+                    ? changingPkgPair.second : null;
             for (int i = mPackages.size() - 1; i >= 0; --i) {
                 final AndroidPackage pkg = mPackages.valueAt(i);
+                final PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.getPackageName());
                 if (changingPkg != null
                         && !hasString(pkg.getUsesLibraries(), changingPkg.getLibraryNames())
                         && !hasString(pkg.getUsesOptionalLibraries(), changingPkg.getLibraryNames())
                         && !ArrayUtils.contains(pkg.getUsesStaticLibraries(),
-                                changingPkg.getStaticSharedLibName())) {
+                        changingPkg.getStaticSharedLibName())) {
                     continue;
                 }
                 if (resultList == null) {
@@ -10231,19 +10242,20 @@
                     }
                     if (!descendants.contains(pkg.getPackageName())) {
                         descendants.add(pkg.getPackageName());
-                        needsUpdating.add(pkg);
+                        needsUpdating.add(Pair.create(pkg, pkgSetting));
                     }
                 }
                 try {
-                    updateSharedLibrariesLocked(pkg, changingPkg, availablePackages);
+                    updateSharedLibrariesLocked(pkg, pkgSetting, changingPkg,
+                            changingPkgSetting, availablePackages);
                 } catch (PackageManagerException e) {
                     // If a system app update or an app and a required lib missing we
                     // delete the package and for updated system apps keep the data as
                     // it is better for the user to reinstall than to be in an limbo
                     // state. Also libs disappearing under an app should never happen
                     // - just in case.
-                    if (!pkg.isSystem() || pkg.isUpdatedSystemApp()) {
-                        final int flags = pkg.isUpdatedSystemApp()
+                    if (!pkg.isSystem() || pkgSetting.getPkgState().isUpdatedSystemApp()) {
+                        final int flags = pkgSetting.getPkgState().isUpdatedSystemApp()
                                 ? PackageManager.DELETE_KEEP_DATA : 0;
                         deletePackageLIF(pkg.getPackageName(), null, true,
                                 mUserManager.getUserIds(), flags, null,
@@ -10259,10 +10271,11 @@
     @GuardedBy({"mInstallLock", "mLock"})
     private ScanResult scanPackageTracedLI(ParsedPackage parsedPackage,
             final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
-            @Nullable UserHandle user) throws PackageManagerException {
+            @Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException {
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage");
         try {
-            return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user);
+            return scanPackageNewLI(parsedPackage, parseFlags, scanFlags, currentTime, user,
+                    cpuAbiOverride);
         } finally {
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
         }
@@ -10337,6 +10350,9 @@
         @Nullable public final UserHandle user;
         /** Whether or not the platform package is being scanned */
         public final boolean isPlatformPackage;
+        /** Override value for package ABI if set during install */
+        @Nullable
+        public final String cpuAbiOverride;
         public ScanRequest(
                 @NonNull ParsedPackage parsedPackage,
                 @Nullable SharedUserSetting sharedUserSetting,
@@ -10348,7 +10364,8 @@
                 @ParseFlags int parseFlags,
                 @ScanFlags int scanFlags,
                 boolean isPlatformPackage,
-                @Nullable UserHandle user) {
+                @Nullable UserHandle user,
+                @Nullable String cpuAbiOverride) {
             this.parsedPackage = parsedPackage;
             this.oldPkg = oldPkg;
             this.pkgSetting = pkgSetting;
@@ -10361,6 +10378,7 @@
             this.scanFlags = scanFlags;
             this.isPlatformPackage = isPlatformPackage;
             this.user = user;
+            this.cpuAbiOverride = cpuAbiOverride;
         }
     }
 
@@ -10468,7 +10486,7 @@
     @GuardedBy({"mInstallLock", "mLock"})
     private ScanResult scanPackageNewLI(@NonNull ParsedPackage parsedPackage,
             final @ParseFlags int parseFlags, @ScanFlags int scanFlags, long currentTime,
-            @Nullable UserHandle user) throws PackageManagerException {
+            @Nullable UserHandle user, String cpuAbiOverride) throws PackageManagerException {
 
         final String renamedPkgName = mSettings.getRenamedPackageLPr(
                 parsedPackage.getRealPackage());
@@ -10489,7 +10507,13 @@
 
         scanFlags = adjustScanFlags(scanFlags, pkgSetting, disabledPkgSetting, user, parsedPackage);
         synchronized (mLock) {
-            applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage);
+            boolean isUpdatedSystemApp;
+            if (pkgSetting != null) {
+                isUpdatedSystemApp = pkgSetting.getPkgState().isUpdatedSystemApp();
+            } else {
+                isUpdatedSystemApp = disabledPkgSetting != null;
+            }
+            applyPolicy(parsedPackage, parseFlags, scanFlags, mPlatformPackage, isUpdatedSystemApp);
             assertPackageIsValid(parsedPackage, parseFlags, scanFlags);
 
             SharedUserSetting sharedUserSetting = null;
@@ -10509,7 +10533,8 @@
             final ScanRequest request = new ScanRequest(parsedPackage, sharedUserSetting,
                     pkgSetting == null ? null : pkgSetting.pkg, pkgSetting, disabledPkgSetting,
                     originalPkgSetting, realPkgName, parseFlags, scanFlags,
-                    Objects.equals(parsedPackage.getPackageName(), platformPackageName), user);
+                    Objects.equals(parsedPackage.getPackageName(), platformPackageName), user,
+                    cpuAbiOverride);
             return scanPackageOnlyLI(request, mInjector, mFactoryTest, currentTime);
         }
     }
@@ -10611,7 +10636,8 @@
         }
 
         if (reconciledPkg.collectedSharedLibraryInfos != null) {
-            executeSharedLibrariesUpdateLPr(pkg, null, reconciledPkg.collectedSharedLibraryInfos);
+            executeSharedLibrariesUpdateLPr(pkg, pkgSetting, null, null,
+                    reconciledPkg.collectedSharedLibraryInfos);
         }
 
         final KeySetManagerService ksms = mSettings.mKeySetManagerService;
@@ -10624,7 +10650,7 @@
         }
         pkgSetting.signatures.mSigningDetails = reconciledPkg.signingDetails;
 
-        if (pkg.getAdoptPermissions() != null) {
+        if (!pkg.getAdoptPermissions().isEmpty()) {
             // This package wants to adopt ownership of permissions from
             // another package.
             for (int i = pkg.getAdoptPermissions().size() - 1; i >= 0; i--) {
@@ -10678,8 +10704,7 @@
     /** Returns {@code true} if the package has been renamed. Otherwise, {@code false}. */
     private static boolean isPackageRenamed(@NonNull AndroidPackage pkg,
             @Nullable String renamedPkgName) {
-        return pkg.getOriginalPackages() != null
-                && pkg.getOriginalPackages().contains(renamedPkgName);
+        return pkg.getOriginalPackages().contains(renamedPkgName);
     }
 
     /**
@@ -10731,8 +10756,7 @@
      */
     private static void ensurePackageRenamed(@NonNull ParsedPackage parsedPackage,
             @NonNull String renamedPackageName) {
-        if (parsedPackage.getOriginalPackages() == null
-                || !parsedPackage.getOriginalPackages().contains(renamedPackageName)
+        if (!parsedPackage.getOriginalPackages().contains(renamedPackageName)
                 || parsedPackage.getPackageName().equals(renamedPackageName)) {
             return;
         }
@@ -10761,19 +10785,21 @@
                 }
 
                 ps.primaryCpuAbiString = adjustedAbi;
-                if (ps.pkg != null && !TextUtils.equals(adjustedAbi, ps.pkg.getPrimaryCpuAbi())) {
-                    ps.pkg.mutate().setPrimaryCpuAbi(adjustedAbi);
-                    if (DEBUG_ABI_SELECTION) {
-                        Slog.i(TAG,
-                                "Adjusting ABI for " + ps.name + " to " + adjustedAbi
-                                        + " (scannedPackage="
-                                        + (scannedPackage != null ? scannedPackage : "null")
-                                        + ")");
+                if (ps.pkg != null) {
+                    if (!TextUtils.equals(adjustedAbi,
+                            AndroidPackageUtils.getRawPrimaryCpuAbi(ps.pkg))) {
+                        if (DEBUG_ABI_SELECTION) {
+                            Slog.i(TAG,
+                                    "Adjusting ABI for " + ps.name + " to " + adjustedAbi
+                                            + " (scannedPackage="
+                                            + (scannedPackage != null ? scannedPackage : "null")
+                                            + ")");
+                        }
+                        if (changedAbiCodePath == null) {
+                            changedAbiCodePath = new ArrayList<>();
+                        }
+                        changedAbiCodePath.add(ps.codePathString);
                     }
-                    if (changedAbiCodePath == null) {
-                        changedAbiCodePath = new ArrayList<>();
-                    }
-                    changedAbiCodePath.add(ps.codePathString);
                 }
             }
         }
@@ -10783,6 +10809,8 @@
     /**
      * Sets the enabled state of components configured through {@link SystemConfig}.
      * This modifies the {@link PackageSetting} object.
+     *
+     * TODO(b/135203078): Move this to package parsing
      **/
     static void configurePackageComponents(AndroidPackage pkg) {
         final ArrayMap<String, Boolean> componentsEnabledStates = SystemConfig.getInstance()
@@ -10793,7 +10821,7 @@
 
         for (int i = ArrayUtils.size(pkg.getActivities()) - 1; i >= 0; i--) {
             final ParsedActivity component = pkg.getActivities().get(i);
-            final Boolean enabled = componentsEnabledStates.get(component.className);
+            final Boolean enabled = componentsEnabledStates.get(component.getName());
             if (enabled != null) {
                 component.setEnabled(enabled);
             }
@@ -10801,7 +10829,7 @@
 
         for (int i = ArrayUtils.size(pkg.getReceivers()) - 1; i >= 0; i--) {
             final ParsedActivity component = pkg.getReceivers().get(i);
-            final Boolean enabled = componentsEnabledStates.get(component.className);
+            final Boolean enabled = componentsEnabledStates.get(component.getName());
             if (enabled != null) {
                 component.setEnabled(enabled);
             }
@@ -10809,7 +10837,7 @@
 
         for (int i = ArrayUtils.size(pkg.getProviders()) - 1; i >= 0; i--) {
             final ParsedProvider component = pkg.getProviders().get(i);
-            final Boolean enabled = componentsEnabledStates.get(component.className);
+            final Boolean enabled = componentsEnabledStates.get(component.getName());
             if (enabled != null) {
                 component.setEnabled(enabled);
             }
@@ -10817,7 +10845,7 @@
 
         for (int i = ArrayUtils.size(pkg.getServices()) - 1; i >= 0; i--) {
             final ParsedService component = pkg.getServices().get(i);
-            final Boolean enabled = componentsEnabledStates.get(component.className);
+            final Boolean enabled = componentsEnabledStates.get(component.getName());
             if (enabled != null) {
                 component.setEnabled(enabled);
             }
@@ -10865,8 +10893,8 @@
         }
 
         // Initialize package source and resource directories
-        final File destCodeFile = new File(parsedPackage.getAppInfoCodePath());
-        final File destResourceFile = new File(parsedPackage.getAppInfoResourcePath());
+        final File destCodeFile = new File(parsedPackage.getCodePath());
+        final File destResourceFile = new File(parsedPackage.getCodePath());
 
         // We keep references to the derived CPU Abis from settings in oder to reuse
         // them in the case where we're not upgrading or booting for the first time.
@@ -10895,10 +10923,13 @@
         }
 
         String[] usesStaticLibraries = null;
-        if (parsedPackage.getUsesStaticLibraries() != null) {
+        if (!parsedPackage.getUsesStaticLibraries().isEmpty()) {
             usesStaticLibraries = new String[parsedPackage.getUsesStaticLibraries().size()];
             parsedPackage.getUsesStaticLibraries().toArray(usesStaticLibraries);
         }
+        // TODO(b/135203078): Remove appInfoFlag usage in favor of individually assigned booleans
+        //  to avoid adding something that's unsupported due to lack of state, since it's called
+        //  with null.
         final boolean createNewPackage = (pkgSetting == null);
         if (createNewPackage) {
             final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
@@ -10907,16 +10938,18 @@
             pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),
                     originalPkgSetting, disabledPkgSetting, realPkgName, sharedUserSetting,
                     destCodeFile, destResourceFile, parsedPackage.getNativeLibraryRootDir(),
-                    parsedPackage.getPrimaryCpuAbi(), parsedPackage.getSecondaryCpuAbi(),
-                    parsedPackage.getVersionCode(), parsedPackage.getFlags(),
-                    parsedPackage.getPrivateFlags(), user, true /*allowInstall*/, instantApp,
+                    AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
+                    AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
+                    parsedPackage.getVersionCode(),
+                    PackageInfoWithoutStateUtils.appInfoFlags(parsedPackage),
+                    PackageInfoWithoutStateUtils.appInfoPrivateFlags(parsedPackage),
+                    user, true /*allowInstall*/, instantApp,
                     virtualPreload, UserManagerService.getInstance(), usesStaticLibraries,
-                    parsedPackage.getUsesStaticLibrariesVersions());
+                    parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups());
         } else {
             // make a deep copy to avoid modifying any existing system state.
             pkgSetting = new PackageSetting(pkgSetting);
-            // TODO(b/135203078): Remove entirely. Set package directly.
-            parsedPackage.setPackageSettingCallback(pkgSetting);
+            pkgSetting.pkg = parsedPackage;
 
             // REMOVE SharedUserSetting from method; update in a separate call.
             //
@@ -10925,10 +10958,13 @@
             // to null here, only to reset them at a later point.
             Settings.updatePackageSetting(pkgSetting, disabledPkgSetting, sharedUserSetting,
                     destCodeFile, destResourceFile, parsedPackage.getNativeLibraryDir(),
-                    parsedPackage.getPrimaryCpuAbi(), parsedPackage.getSecondaryCpuAbi(),
-                    parsedPackage.getFlags(), parsedPackage.getPrivateFlags(),
+                    AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
+                    AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
+                    PackageInfoWithoutStateUtils.appInfoFlags(parsedPackage),
+                    PackageInfoWithoutStateUtils.appInfoPrivateFlags(parsedPackage),
                     UserManagerService.getInstance(),
-                    usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions());
+                    usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
+                    parsedPackage.getMimeGroups());
         }
         if (createNewPackage && originalPkgSetting != null) {
             // This is the initial transition from the original package, so,
@@ -10954,35 +10990,28 @@
         if (disabledPkgSetting != null
                 || (0 != (scanFlags & SCAN_NEW_INSTALL)
                 && pkgSetting != null && pkgSetting.isSystem())) {
-            parsedPackage.mutate().setUpdatedSystemApp(true);
+            pkgSetting.getPkgState().setUpdatedSystemApp(true);
         }
 
         parsedPackage
                 .setSeInfo(SELinuxMMAC.getSeInfo(parsedPackage, sharedUserSetting,
                         injector.getCompatibility()))
                 .setSeInfoUser(SELinuxUtil.assignSeinfoUser(pkgSetting.readUserState(
-                        userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId)))
-                .setProcessName(fixProcessName(parsedPackage.getPackageName(),
-                        parsedPackage.getProcessName()));
-
-        if (!isPlatformPackage) {
-            // Get all of our default paths setup
-            parsedPackage.initForUser(UserHandle.USER_SYSTEM);
-        }
+                        userId == UserHandle.USER_ALL ? UserHandle.USER_SYSTEM : userId)));
 
         if (parsedPackage.isSystem()) {
             configurePackageComponents(parsedPackage);
         }
 
-        final String cpuAbiOverride = deriveAbiOverride(parsedPackage.getCpuAbiOverride(),
-                pkgSetting);
+        final String cpuAbiOverride = deriveAbiOverride(request.cpuAbiOverride, pkgSetting);
 
         if ((scanFlags & SCAN_NEW_INSTALL) == 0) {
             if (needToDeriveAbi) {
                 Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "derivePackageAbi");
-                final boolean extractNativeLibs = !parsedPackage.isLibrary();
+                final boolean extractNativeLibs = !AndroidPackageUtils.isLibrary(parsedPackage);
                 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths> derivedAbi =
-                        packageAbiHelper.derivePackageAbi(parsedPackage, cpuAbiOverride,
+                        packageAbiHelper.derivePackageAbi(parsedPackage,
+                                pkgSetting.getPkgState().isUpdatedSystemApp(), cpuAbiOverride,
                                 extractNativeLibs);
                 derivedAbi.first.applyTo(parsedPackage);
                 derivedAbi.second.applyTo(parsedPackage);
@@ -10991,14 +11020,16 @@
                 // Some system apps still use directory structure for native libraries
                 // in which case we might end up not detecting abi solely based on apk
                 // structure. Try to detect abi based on directory structure.
-                if (isSystemApp(parsedPackage) && !parsedPackage.isUpdatedSystemApp() &&
-                        parsedPackage.getPrimaryCpuAbi() == null) {
+
+                String pkgRawPrimaryCpuAbi = AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage);
+                if (parsedPackage.isSystem() && !pkgSetting.getPkgState().isUpdatedSystemApp() &&
+                        pkgRawPrimaryCpuAbi == null) {
                     final PackageAbiHelper.Abis abis = packageAbiHelper.getBundledAppAbis(
                             parsedPackage);
                     abis.applyTo(parsedPackage);
                     abis.applyTo(pkgSetting);
                     final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
-                            packageAbiHelper.getNativeLibraryPaths(parsedPackage,
+                            packageAbiHelper.getNativeLibraryPaths(parsedPackage, pkgSetting,
                                     sAppLib32InstallDir);
                     nativeLibraryPaths.applyTo(parsedPackage);
                 }
@@ -11010,13 +11041,16 @@
                         .setSecondaryCpuAbi(secondaryCpuAbiFromSettings);
 
                 final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
-                        packageAbiHelper.getNativeLibraryPaths(parsedPackage, sAppLib32InstallDir);
+                        packageAbiHelper.getNativeLibraryPaths(parsedPackage,
+                                pkgSetting, sAppLib32InstallDir);
                 nativeLibraryPaths.applyTo(parsedPackage);
 
                 if (DEBUG_ABI_SELECTION) {
                     Slog.i(TAG, "Using ABIS and native lib paths from settings : " +
-                            parsedPackage.getPackageName() + " " + parsedPackage.getPrimaryCpuAbi()
-                            + ", " + parsedPackage.getSecondaryCpuAbi());
+                            parsedPackage.getPackageName() + " " +
+                            AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage)
+                            + ", " 
+                            + AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
                 }
             }
         } else {
@@ -11033,7 +11067,8 @@
             // ABIs we determined during compilation, but the path will depend on the final
             // package path (after the rename away from the stage path).
             final PackageAbiHelper.NativeLibraryPaths nativeLibraryPaths =
-                    packageAbiHelper.getNativeLibraryPaths(parsedPackage, sAppLib32InstallDir);
+                    packageAbiHelper.getNativeLibraryPaths(parsedPackage, pkgSetting,
+                            sAppLib32InstallDir);
             nativeLibraryPaths.applyTo(parsedPackage);
         }
 
@@ -11051,20 +11086,16 @@
         // would've already compiled the app without taking the package setting into
         // account.
         if ((scanFlags & SCAN_NO_DEX) == 0 && (scanFlags & SCAN_NEW_INSTALL) != 0) {
-            if (cpuAbiOverride == null && parsedPackage.getPackageName() != null) {
+            if (cpuAbiOverride == null) {
                 Slog.w(TAG, "Ignoring persisted ABI override " + cpuAbiOverride +
                         " for package " + parsedPackage.getPackageName());
             }
         }
 
-        pkgSetting.primaryCpuAbiString = parsedPackage.getPrimaryCpuAbi();
-        pkgSetting.secondaryCpuAbiString = parsedPackage.getSecondaryCpuAbi();
+        pkgSetting.primaryCpuAbiString = AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage);
+        pkgSetting.secondaryCpuAbiString = AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage);
         pkgSetting.cpuAbiOverrideString = cpuAbiOverride;
 
-        // Copy the derived override back to the parsed package, so that we can
-        // update the package settings accordingly.
-        parsedPackage.setCpuAbiOverride(cpuAbiOverride);
-
         if (DEBUG_ABI_SELECTION) {
             Slog.d(TAG, "Resolved nativeLibraryRoot for " + parsedPackage.getPackageName()
                     + " to root=" + parsedPackage.getNativeLibraryRootDir() + ", isa="
@@ -11077,8 +11108,8 @@
 
         if (DEBUG_ABI_SELECTION) {
             Log.d(TAG, "Abis for package[" + parsedPackage.getPackageName() + "] are" +
-                    " primary=" + parsedPackage.getPrimaryCpuAbi() +
-                    " secondary=" + parsedPackage.getSecondaryCpuAbi());
+                    " primary=" + AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage) +
+                    " secondary=" + AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage));
         }
 
         if ((scanFlags & SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
@@ -11120,13 +11151,13 @@
         }
         pkgSetting.setTimeStamp(scanFileTime);
         // TODO(b/135203078): Remove, move to constructor
-        parsedPackage.setPackageSettingCallback(pkgSetting);
-        pkgSetting.pkgFlags = parsedPackage.getFlags();
+        pkgSetting.pkg = parsedPackage;
+        pkgSetting.pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting);
         if (parsedPackage.getLongVersionCode() != pkgSetting.versionCode) {
             pkgSetting.versionCode = parsedPackage.getLongVersionCode();
         }
         // Update volume if needed
-        final String volumeUuid = parsedPackage.getApplicationInfoVolumeUuid();
+        final String volumeUuid = parsedPackage.getVolumeUuid();
         if (!Objects.equals(volumeUuid, pkgSetting.volumeUuid)) {
             Slog.i(PackageManagerService.TAG,
                     "Update" + (pkgSetting.isSystem() ? " system" : "")
@@ -11138,14 +11169,15 @@
 
         SharedLibraryInfo staticSharedLibraryInfo = null;
         if (!TextUtils.isEmpty(parsedPackage.getStaticSharedLibName())) {
-            staticSharedLibraryInfo = SharedLibraryInfo.createForStatic(parsedPackage);
+            staticSharedLibraryInfo =
+                    AndroidPackageUtils.createSharedLibraryForStatic(parsedPackage);
         }
         List<SharedLibraryInfo> dynamicSharedLibraryInfos = null;
         if (!ArrayUtils.isEmpty(parsedPackage.getLibraryNames())) {
             dynamicSharedLibraryInfos = new ArrayList<>(parsedPackage.getLibraryNames().size());
             for (String name : parsedPackage.getLibraryNames()) {
                 dynamicSharedLibraryInfos.add(
-                        SharedLibraryInfo.createForDynamic(parsedPackage, name));
+                        AndroidPackageUtils.createSharedLibraryForDynamic(parsedPackage, name));
             }
         }
 
@@ -11183,7 +11215,7 @@
      */
     private static void assertCodePolicy(AndroidPackage pkg)
             throws PackageManagerException {
-        final boolean shouldHaveCode = (pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0;
+        final boolean shouldHaveCode = pkg.isHasCode();
         if (shouldHaveCode && !apkHasCode(pkg.getBaseCodePath())) {
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     "Package " + pkg.getBaseCodePath() + " code is missing");
@@ -11209,7 +11241,8 @@
      * ideally be static, but, it requires locks to read system state.
      */
     private static void applyPolicy(ParsedPackage parsedPackage, final @ParseFlags int parseFlags,
-            final @ScanFlags int scanFlags, AndroidPackage platformPkg) {
+            final @ScanFlags int scanFlags, AndroidPackage platformPkg,
+            boolean isUpdatedSystemApp) {
         if ((scanFlags & SCAN_AS_SYSTEM) != 0) {
             parsedPackage.setSystem(true);
             // TODO(b/135203078): Can this be done in PackageParser? Or just inferred when the flag
@@ -11218,7 +11251,7 @@
                 parsedPackage.setAllComponentsDirectBootAware(true);
             }
             if (compressedFileExists(parsedPackage.getCodePath())) {
-                parsedPackage.setIsStub(true);
+                parsedPackage.setStub(true);
             }
         } else {
             parsedPackage
@@ -11253,14 +11286,14 @@
                 ) == PackageManager.SIGNATURE_MATCH))
         );
 
-        if (!isSystemApp(parsedPackage)) {
+        if (!parsedPackage.isSystem()) {
             // Only system apps can use these features.
             parsedPackage.clearOriginalPackages()
                     .setRealPackage(null)
                     .clearAdoptPermissions();
         }
 
-        PackageBackwardCompatibility.modifySharedLibraries(parsedPackage);
+        PackageBackwardCompatibility.modifySharedLibraries(parsedPackage, isUpdatedSystemApp);
     }
 
     private static @NonNull <T> T assertNotNull(@Nullable T object, String message)
@@ -11271,19 +11304,19 @@
         return object;
     }
 
-    private <T extends ComponentParseUtils.ParsedMainComponent>
+    private <T extends ParsedMainComponent>
             void assertPackageProcesses(AndroidPackage pkg, List<T> components,
-            ArrayMap<String, ComponentParseUtils.ParsedProcess> procs, String compName)
+            Map<String, ParsedProcess> procs, String compName)
             throws PackageManagerException {
         if (components == null) {
             return;
         }
         for (int i = components.size() - 1; i >= 0; i--) {
-            final ComponentParseUtils.ParsedMainComponent<?> component = components.get(i);
+            final ParsedMainComponent component = components.get(i);
             if (!procs.containsKey(component.getProcessName())) {
                 throw new PackageManagerException(
                         INSTALL_FAILED_PROCESS_NOT_DEFINED,
-                        "Can't install because " + compName + " " + component.className
+                        "Can't install because " + compName + " " + component.getClassName()
                                 + "'s process attribute " + component.getProcessName()
                                 + " (in package " + pkg.getPackageName()
                                 + ") is not included in the <processes> list");
@@ -11307,8 +11340,7 @@
             assertCodePolicy(pkg);
         }
 
-        if (pkg.getAppInfoCodePath() == null ||
-                pkg.getAppInfoResourcePath() == null) {
+        if (pkg.getCodePath() == null) {
             // Bail out. The resource and code paths haven't been set.
             throw new PackageManagerException(INSTALL_FAILED_INVALID_APK,
                     "Code and resource paths haven't been set correctly");
@@ -11391,49 +11423,49 @@
                 }
 
                 // Static shared libs cannot declare activities
-                if (pkg.getActivities() != null && !pkg.getActivities().isEmpty()) {
+                if (!pkg.getActivities().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare activities");
                 }
 
                 // Static shared libs cannot declare services
-                if (pkg.getServices() != null && !pkg.getServices().isEmpty()) {
+                if (!pkg.getServices().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare services");
                 }
 
                 // Static shared libs cannot declare providers
-                if (pkg.getProviders() != null && !pkg.getProviders().isEmpty()) {
+                if (!pkg.getProviders().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare content providers");
                 }
 
                 // Static shared libs cannot declare receivers
-                if (pkg.getReceivers() != null && !pkg.getReceivers().isEmpty()) {
+                if (!pkg.getReceivers().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare broadcast receivers");
                 }
 
                 // Static shared libs cannot declare permission groups
-                if (pkg.getPermissionGroups() != null && !pkg.getPermissionGroups().isEmpty()) {
+                if (!pkg.getPermissionGroups().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare permission groups");
                 }
 
                 // Static shared libs cannot declare features
-                if (pkg.getFeatures() != null && !pkg.getFeatures().isEmpty()) {
+                if (!pkg.getFeatures().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare features");
                 }
 
                 // Static shared libs cannot declare permissions
-                if (pkg.getPermissions() != null && !pkg.getPermissions().isEmpty()) {
+                if (!pkg.getPermissions().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare permissions");
                 }
 
                 // Static shared libs cannot declare protected broadcasts
-                if (pkg.getProtectedBroadcasts() != null) {
+                if (!pkg.getProtectedBroadcasts().isEmpty()) {
                     throw new PackageManagerException(
                             "Static shared libs cannot declare protected broadcasts");
                 }
@@ -11495,12 +11527,11 @@
                                     + " and requiring known paths " + known.codePathString
                                     + " & " + known.resourcePathString);
                         }
-                        if (!pkg.getAppInfoCodePath().equals(known.codePathString)
-                                || !pkg.getAppInfoResourcePath().equals(
-                                        known.resourcePathString)) {
+                        if (!pkg.getCodePath().equals(known.codePathString)
+                                || !pkg.getCodePath().equals(known.resourcePathString)) {
                             throw new PackageManagerException(INSTALL_FAILED_PACKAGE_CHANGED,
                                     "Application package " + pkg.getPackageName()
-                                    + " found at " + pkg.getAppInfoCodePath()
+                                    + " found at " + pkg.getCodePath()
                                     + " but expected at " + known.codePathString
                                     + "; ignoring.");
                         }
@@ -11522,8 +11553,8 @@
 
             // If this package has defined explicit processes, then ensure that these are
             // the only processes used by its components.
-            final ArrayMap<String, ComponentParseUtils.ParsedProcess> procs = pkg.getProcesses();
-            if (procs != null) {
+            final Map<String, ParsedProcess> procs = pkg.getProcesses();
+            if (!procs.isEmpty()) {
                 if (!procs.containsKey(pkg.getProcessName())) {
                     throw new PackageManagerException(
                             INSTALL_FAILED_PROCESS_NOT_DEFINED,
@@ -11570,50 +11601,17 @@
                     // We are scanning a system overlay. This can be the first scan of the
                     // system/vendor/oem partition, or an update to the system overlay.
                     if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
-                        // This must be an update to a system overlay.
-                        final PackageSetting previousPkg = assertNotNull(
-                                mSettings.getPackageLPr(pkg.getPackageName()),
-                                "previous package state not present");
-
-                        // previousPkg.pkg may be null: the package will be not be scanned if the
-                        // package manager knows there is a newer version on /data.
-                        // TODO[b/79435695]: Find a better way to keep track of the "static"
-                        // property for RROs instead of having to parse packages on /system
-                        AndroidPackage ppkg = previousPkg.pkg;
-                        if (ppkg == null) {
-                            try {
-                                final PackageParser pp = new PackageParser();
-                                // TODO(b/135203078): Do we really need to parse here? Maybe use
-                                //  a shortened path?
-                                ppkg = pp.parseParsedPackage(previousPkg.codePath,
-                                        parseFlags | PackageParser.PARSE_IS_SYSTEM_DIR,
-                                        false)
-                                        .hideAsFinal();
-                            } catch (PackageParserException e) {
-                                Slog.w(TAG, "failed to parse " + previousPkg.codePath, e);
-                            }
-                        }
-
-                        // Static overlays cannot be updated.
-                        if (ppkg != null && ppkg.isOverlayIsStatic()) {
+                        // This must be an update to a system overlay. Immutable overlays cannot be
+                        // upgraded.
+                        Objects.requireNonNull(mOverlayConfig,
+                                "Parsing non-system dir before overlay configs are initialized");
+                        if (!mOverlayConfig.isMutable(pkg.getPackageName())) {
                             throw new PackageManagerException("Overlay "
                                     + pkg.getPackageName()
                                     + " is static and cannot be upgraded.");
-                        // Non-static overlays cannot be converted to static overlays.
-                        } else if (pkg.isOverlayIsStatic()) {
-                            throw new PackageManagerException("Overlay "
-                                    + pkg.getPackageName()
-                                    + " cannot be upgraded into a static overlay.");
                         }
                     }
                 } else {
-                    // The overlay is a non-system overlay. Non-system overlays cannot be static.
-                    if (pkg.isOverlayIsStatic()) {
-                        throw new PackageManagerException("Overlay "
-                                + pkg.getPackageName()
-                                + " is static but not pre-installed.");
-                    }
-
                     // A non-preloaded overlay packages must have targetSdkVersion >= Q, or be
                     // signed with the platform certificate. Check this in increasing order of
                     // computational cost.
@@ -11810,14 +11808,16 @@
                         reconciledPkg.getCombinedAvailablePackages();
                 try {
                     // Shared libraries for the package need to be updated.
-                    updateSharedLibrariesLocked(pkg, null, combinedSigningDetails);
+                    updateSharedLibrariesLocked(pkg, pkgSetting, null, null,
+                            combinedSigningDetails);
                 } catch (PackageManagerException e) {
                     Slog.e(TAG, "updateSharedLibrariesLPr failed: ", e);
                 }
                 // Update all applications that use this library. Skip when booting
                 // since this will be done after all packages are scaned.
                 if ((scanFlags & SCAN_BOOTING) == 0) {
-                    clientLibPkgs = updateAllSharedLibrariesLocked(pkg, combinedSigningDetails);
+                    clientLibPkgs = updateAllSharedLibrariesLocked(pkg, pkgSetting,
+                            combinedSigningDetails);
                 }
             }
         }
@@ -11842,7 +11842,7 @@
         if (clientLibPkgs != null) {
             for (int i=0; i<clientLibPkgs.size(); i++) {
                 AndroidPackage clientPkg = clientLibPkgs.get(i);
-                killApplication(clientPkg.getAppInfoPackageName(),
+                killApplication(clientPkg.getPackageName(),
                         clientPkg.getUid(), "update lib");
             }
         }
@@ -11856,7 +11856,7 @@
             // Add the new setting to mSettings
             mSettings.insertPackageSettingLPw(pkgSetting, pkg);
             // Add the new setting to mPackages
-            mPackages.put(pkg.getAppInfoPackageName(), pkg);
+            mPackages.put(pkg.getPackageName(), pkg);
             if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) {
                 mApexManager.registerApkInApex(pkg);
             }
@@ -11904,7 +11904,7 @@
                 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
             }
 
-            if (pkg.getProtectedBroadcasts() != null) {
+            if (!pkg.getProtectedBroadcasts().isEmpty()) {
                 synchronized (mProtectedBroadcasts) {
                     mProtectedBroadcasts.addAll(pkg.getProtectedBroadcasts());
                 }
@@ -11936,8 +11936,8 @@
             // Set up information for custom user intent resolution activity.
             mResolveActivity.applicationInfo = pkg.toAppInfoWithoutState();
             mResolveActivity.name = mCustomResolverComponentName.getClassName();
-            mResolveActivity.packageName = pkg.getAppInfoPackageName();
-            mResolveActivity.processName = pkg.getAppInfoProcessName();
+            mResolveActivity.packageName = pkg.getPackageName();
+            mResolveActivity.processName = pkg.getProcessName();
             mResolveActivity.launchMode = ActivityInfo.LAUNCH_MULTIPLE;
             mResolveActivity.flags = ActivityInfo.FLAG_EXCLUDE_FROM_RECENTS |
                     ActivityInfo.FLAG_FINISH_ON_CLOSE_SYSTEM_DIALOGS;
@@ -12055,21 +12055,19 @@
         }
 
         r = null;
-        if ((pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0) {
+        if (pkg.isSystem()) {
             // Only system apps can hold shared libraries.
-            if (pkg.getLibraryNames() != null) {
-                final int libraryNamesSize = pkg.getLibraryNames().size();
-                for (i = 0; i < libraryNamesSize; i++) {
-                    String name = pkg.getLibraryNames().get(i);
-                    if (removeSharedLibraryLPw(name, 0)) {
-                        if (DEBUG_REMOVE && chatty) {
-                            if (r == null) {
-                                r = new StringBuilder(256);
-                            } else {
-                                r.append(' ');
-                            }
-                            r.append(name);
+            final int libraryNamesSize = pkg.getLibraryNames().size();
+            for (i = 0; i < libraryNamesSize; i++) {
+                String name = pkg.getLibraryNames().get(i);
+                if (removeSharedLibraryLPw(name, 0)) {
+                    if (DEBUG_REMOVE && chatty) {
+                        if (r == null) {
+                            r = new StringBuilder(256);
+                        } else {
+                            r.append(' ');
                         }
+                        r.append(name);
                     }
                 }
             }
@@ -12480,18 +12478,12 @@
             if (pkgSetting == null || !pkgSetting.isSystem()) {
                 return;
             }
-            AndroidPackage pkg = pkgSetting.pkg;
-            if (pkg != null) {
-                pkg.mutate().setHiddenUntilInstalled(hidden);
-            }
+            pkgSetting.getPkgState().setHiddenUntilInstalled(hidden);
             final PackageSetting disabledPs = mSettings.getDisabledSystemPkgLPr(packageName);
             if (disabledPs == null) {
                 return;
             }
-            pkg = disabledPs.pkg;
-            if (pkg != null) {
-                pkg.mutate().setHiddenUntilInstalled(hidden);
-            }
+            disabledPs.getPkgState().setHiddenUntilInstalled(hidden);
         }
     }
 
@@ -13513,15 +13505,15 @@
             ArrayList<IntentFilter> result = new ArrayList<>();
             for (int n=0; n<count; n++) {
                 ParsedActivity activity = pkg.getActivities().get(n);
-                if (activity.intents != null && activity.intents.size() > 0) {
-                    result.addAll(activity.intents);
+                if (activity.getIntents() != null && activity.getIntents().size() > 0) {
+                    result.addAll(activity.getIntents());
                 }
             }
             return new ParceledListSlice<IntentFilter>(result) {
                 @Override
                 protected void writeElement(IntentFilter parcelable, Parcel dest, int callFlags) {
                     // IntentFilter has final Parcelable methods, so redirect to the subclass
-                    ((ParsedActivityIntentInfo) parcelable).writeIntentInfoToParcel(dest,
+                    ((ParsedIntentInfo) parcelable).writeIntentInfoToParcel(dest,
                             callFlags);
                 }
             };
@@ -13706,9 +13698,8 @@
         // package has not opted out of backup participation.
         final boolean update = res.removedInfo != null
                 && res.removedInfo.removedPackage != null;
-        final int flags = (res.pkg == null) ? 0 : res.pkg.getFlags();
-        boolean doRestore = !update
-                && ((flags & ApplicationInfo.FLAG_ALLOW_BACKUP) != 0);
+        boolean allowBackup = res.pkg != null && res.pkg.isAllowBackup();
+        boolean doRestore = !update && allowBackup;
 
         // Set up the post-install work request bookkeeping.  This will be used
         // and cleaned up by the post-install event handling regardless of whether
@@ -13776,7 +13767,7 @@
             try {
                 if (bm.isUserReadyForBackup(userId)) {
                     bm.restoreAtInstallForUser(
-                            userId, res.pkg.getAppInfoPackageName(), token);
+                            userId, res.pkg.getPackageName(), token);
                 } else {
                     Slog.w(TAG, "User " + userId + " is not ready. Restore at install "
                             + "didn't take place.");
@@ -13804,8 +13795,7 @@
         IRollbackManager rm = IRollbackManager.Stub.asInterface(
                 ServiceManager.getService(Context.ROLLBACK_SERVICE));
 
-        final String packageName = res.pkg.getAppInfoPackageName();
-        final String seInfo = res.pkg.getSeInfo();
+        final String packageName = res.pkg.getPackageName();
         final int[] allUsers = mUserManager.getUserIds();
         final int[] installedUsers;
 
@@ -13829,6 +13819,7 @@
                 || (data.args.installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0);
 
         if (ps != null && doSnapshotOrRestore) {
+            final String seInfo = AndroidPackageUtils.getSeInfo(res.pkg, ps);
             try {
                 rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
                         seInfo, token);
@@ -13864,7 +13855,7 @@
                 if (data.res.returnCode != PackageManager.INSTALL_SUCCEEDED) {
                     continue;
                 }
-                if (packageName.equals(data.res.pkg.getAppInfoPackageName())) {
+                if (packageName.equals(data.res.pkg.getPackageName())) {
                     // right package; but is it for the right user?
                     for (int uIndex = 0; uIndex < data.res.newUsers.length; uIndex++) {
                         if (userId == data.res.newUsers[uIndex]) {
@@ -14000,20 +13991,18 @@
         final String fromUuid;
         final String toUuid;
         final String packageName;
-        final String dataAppName;
         final int appId;
         final String seinfo;
         final int targetSdkVersion;
         final String fromCodePath;
 
         public MoveInfo(int moveId, String fromUuid, String toUuid, String packageName,
-                String dataAppName, int appId, String seinfo, int targetSdkVersion,
+                int appId, String seinfo, int targetSdkVersion,
                 String fromCodePath) {
             this.moveId = moveId;
             this.fromUuid = fromUuid;
             this.toUuid = toUuid;
             this.packageName = packageName;
-            this.dataAppName = dataAppName;
             this.appId = appId;
             this.seinfo = seinfo;
             this.targetSdkVersion = targetSdkVersion;
@@ -14249,7 +14238,7 @@
 
                 if (dataOwnerPkg != null) {
                     if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
-                            dataOwnerPkg.getFlags())) {
+                            dataOwnerPkg.isDebuggable())) {
                         try {
                             checkDowngrade(dataOwnerPkg, pkgLite);
                         } catch (PackageManagerException e) {
@@ -14262,7 +14251,7 @@
                 if (installedPkg != null) {
                     if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
                         // Check for updated system application.
-                        if ((installedPkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0) {
+                        if (installedPkg.isSystem()) {
                             return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
                         } else {
                             // If current upgrade specifies particular preference
@@ -14273,7 +14262,7 @@
                                 // App explictly prefers external. Let policy decide
                             } else {
                                 // Prefer previous location
-                                if (isExternal(installedPkg)) {
+                                if (installedPkg.isExternalStorage()) {
                                     return PackageHelper.RECOMMEND_INSTALL_EXTERNAL;
                                 }
                                 return PackageHelper.RECOMMEND_INSTALL_INTERNAL;
@@ -15049,14 +15038,6 @@
             parsedPackage.setSplitCodePaths(FileUtils.rewriteAfterRename(beforeCodeFile,
                     afterCodeFile, parsedPackage.getSplitCodePaths()));
 
-            // Reflect the rename in app info
-            // TODO(b/135203078): Remove all of these application info calls
-            parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid())
-                    .setApplicationInfoCodePath(parsedPackage.getCodePath())
-                    .setApplicationInfoResourcePath(parsedPackage.getCodePath())
-                    .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath())
-                    .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths());
-
             return true;
         }
 
@@ -15137,7 +15118,7 @@
             synchronized (mInstaller) {
                 try {
                     mInstaller.moveCompleteApp(move.fromUuid, move.toUuid, move.packageName,
-                            move.dataAppName, move.appId, move.seinfo, move.targetSdkVersion,
+                            move.appId, move.seinfo, move.targetSdkVersion,
                             move.fromCodePath);
                 } catch (InstallerException e) {
                     Slog.w(TAG, "Failed to move app", e);
@@ -15145,7 +15126,8 @@
                 }
             }
 
-            codeFile = new File(Environment.getDataAppDirectory(move.toUuid), move.dataAppName);
+            final String toPathName = new File(move.fromCodePath).getName();
+            codeFile = new File(Environment.getDataAppDirectory(move.toUuid), toPathName);
             resourceFile = codeFile;
             if (DEBUG_INSTALL) Slog.d(TAG, "codeFile after move is " + codeFile);
 
@@ -15166,14 +15148,6 @@
                 return false;
             }
 
-            // Reflect the move in app info
-            // TODO(b/135203078): Remove all of these application info calls
-            parsedPackage.setApplicationVolumeUuid(parsedPackage.getVolumeUuid())
-                    .setApplicationInfoCodePath(parsedPackage.getCodePath())
-                    .setApplicationInfoResourcePath(parsedPackage.getCodePath())
-                    .setApplicationInfoBaseResourcePath(parsedPackage.getBaseCodePath())
-                    .setApplicationInfoSplitResourcePaths(parsedPackage.getSplitCodePaths());
-
             return true;
         }
 
@@ -15197,8 +15171,9 @@
         }
 
         private boolean cleanUp(String volumeUuid) {
+            final String toPathName = new File(move.fromCodePath).getName();
             final File codeFile = new File(Environment.getDataAppDirectory(volumeUuid),
-                    move.dataAppName);
+                    toPathName);
             Slog.d(TAG, "Cleaning up " + move.packageName + " on " + volumeUuid);
             final int[] userIds = mUserManager.getUserIds();
             synchronized (mInstallLock) {
@@ -15207,10 +15182,13 @@
 
                 // We purposefully exclude FLAG_STORAGE_EXTERNAL here, since
                 // this task was only focused on moving data on internal storage.
+                // We don't want ART profiles cleared, because they don't move,
+                // so we would be deleting the only copy (b/149200535).
+                final int flags = FLAG_STORAGE_DE | FLAG_STORAGE_CE
+                        | Installer.FLAG_CLEAR_APP_DATA_KEEP_ART_PROFILES;
                 for (int userId : userIds) {
                     try {
-                        mInstaller.destroyAppData(volumeUuid, move.packageName, userId,
-                                StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE, 0);
+                        mInstaller.destroyAppData(volumeUuid, move.packageName, userId, flags, 0);
                     } catch (InstallerException e) {
                         Slog.w(TAG, String.valueOf(e));
                     }
@@ -15366,7 +15344,7 @@
             final PackageSetting ps = mSettings.mPackages.get(pkgName);
             final int userId = installArgs.user.getIdentifier();
             if (ps != null) {
-                if (isSystemApp(pkg)) {
+                if (pkg.isSystem()) {
                     if (DEBUG_INSTALL) {
                         Slog.d(TAG, "Implicitly enabling system package on upgrade: " + pkgName);
                     }
@@ -15395,8 +15373,8 @@
                 }
 
                 // Retrieve the overlays for shared libraries of the package.
-                if (pkg.getUsesLibraryInfos() != null) {
-                    for (SharedLibraryInfo sharedLib : pkg.getUsesLibraryInfos()) {
+                if (!ps.getPkgState().getUsesLibraryInfos().isEmpty()) {
+                    for (SharedLibraryInfo sharedLib : ps.getPkgState().getUsesLibraryInfos()) {
                         for (int currentUserId : UserManagerService.getInstance().getUserIds()) {
                             if (!sharedLib.isDynamic()) {
                                 // TODO(146804378): Support overlaying static shared libraries
@@ -15868,13 +15846,13 @@
         if (scanResult.staticSharedLibraryInfo != null) {
             return Collections.singletonList(scanResult.staticSharedLibraryInfo);
         }
-        final boolean hasDynamicLibraries =
-                (parsedPackage.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0
+        final boolean hasDynamicLibraries = parsedPackage.isSystem()
                         && scanResult.dynamicSharedLibraryInfos != null;
         if (!hasDynamicLibraries) {
             return null;
         }
-        final boolean isUpdatedSystemApp = parsedPackage.isUpdatedSystemApp();
+        final boolean isUpdatedSystemApp = scanResult.pkgSetting.getPkgState()
+                .isUpdatedSystemApp();
         // We may not yet have disabled the updated package yet, so be sure to grab the
         // current setting if that's the case.
         final PackageSetting updatedSystemPs = isUpdatedSystemApp
@@ -15971,10 +15949,13 @@
                         // which means we are replacing another update that is already
                         // installed.  We need to make sure to delete the older one's .apk.
                         res.removedInfo.args = createInstallArgsForExisting(
-                                oldPackage.getAppInfoCodePath(),
-                                oldPackage.getAppInfoResourcePath(),
-                                getAppDexInstructionSets(oldPackage.getPrimaryCpuAbi(),
-                                        oldPackage.getSecondaryCpuAbi()));
+                                oldPackage.getCodePath(),
+                                oldPackage.getCodePath(),
+                                getAppDexInstructionSets(
+                                        AndroidPackageUtils.getPrimaryCpuAbi(oldPackage,
+                                                deletedPkgSetting),
+                                        AndroidPackageUtils.getSecondaryCpuAbi(oldPackage,
+                                                deletedPkgSetting)));
                     } else {
                         res.removedInfo.args = null;
                     }
@@ -15993,14 +15974,14 @@
 
                     // If deleted package lived in a container, give users a chance to
                     // relinquish resources before killing.
-                    if (oldPackage.isForwardLocked() || isExternal(oldPackage)) {
+                    if (oldPackage.isExternalStorage()) {
                         if (DEBUG_INSTALL) {
                             Slog.i(TAG, "upgrading pkg " + oldPackage
                                     + " is ASEC-hosted -> UNAVAILABLE");
                         }
                         final int[] uidArray = new int[]{oldPackage.getUid()};
                         final ArrayList<String> pkgList = new ArrayList<>(1);
-                        pkgList.add(oldPackage.getAppInfoPackageName());
+                        pkgList.add(oldPackage.getPackageName());
                         sendResourcesChangedBroadcast(false, true, pkgList, uidArray, null);
                     }
 
@@ -16107,7 +16088,7 @@
                     final ScanResult result = scanPackageTracedLI(
                             prepareResult.packageToScan, prepareResult.parseFlags,
                             prepareResult.scanFlags, System.currentTimeMillis(),
-                            request.args.user);
+                            request.args.user, request.args.abiOverride);
                     if (null != preparedScans.put(result.pkgSetting.pkg.getPackageName(), result)) {
                         request.installResult.setError(
                                 PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE,
@@ -16240,7 +16221,7 @@
             final boolean performDexopt =
                     (!instantApp || Global.getInt(mContext.getContentResolver(),
                     Global.INSTANT_APP_DEXOPT_ENABLED, 0) != 0)
-                    && ((pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) == 0)
+                    && !pkg.isDebuggable()
                     && (!onIncremental);
 
             if (performDexopt) {
@@ -16260,7 +16241,7 @@
                         REASON_INSTALL,
                         DexoptOptions.DEXOPT_BOOT_COMPLETE
                                 | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE);
-                mPackageDexOptimizer.performDexOpt(pkg,
+                mPackageDexOptimizer.performDexOpt(pkg, reconciledPkg.pkgSetting,
                         null /* instructionSets */,
                         getOrCreateCompilerPackageStats(pkg),
                         mDexManager.getPackageUseInfoOrDefault(packageName),
@@ -16377,16 +16358,14 @@
                 | PackageParser.PARSE_ENFORCE_CODE
                 | (onExternal ? PackageParser.PARSE_EXTERNAL_STORAGE : 0);
 
-        PackageParser pp = new PackageParser();
-        pp.setSeparateProcesses(mSeparateProcesses);
-        pp.setDisplayMetrics(mMetrics);
-        pp.setCallback(mPackageParserCallback);
+        PackageParser2 pp = new PackageParser2(mSeparateProcesses, false, mMetrics, null,
+                mPackageParserCallback);
 
         Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage");
         ParsedPackage parsedPackage;
         try {
-            parsedPackage = pp.parseParsedPackage(tmpPackageFile, parseFlags, false);
-            DexMetadataHelper.validatePackageDexMetadata(parsedPackage);
+            parsedPackage = pp.parsePackage(tmpPackageFile, parseFlags, false);
+            AndroidPackageUtils.validatePackageDexMetadata(parsedPackage);
         } catch (PackageParserException e) {
             throw new PrepareFailure("Failed parse during installPackageLI", e);
         } finally {
@@ -16421,16 +16400,8 @@
             }
         }
 
-        // If package doesn't declare API override, mark that we have an install
-        // time CPU ABI override.
-        // TODO(b/135203078): Isn't this always true because cpuAbiOverride isn't assigned during
-        //  parsing?
-        if (TextUtils.isEmpty(parsedPackage.getCpuAbiOverride())) {
-            parsedPackage.setCpuAbiOverride(args.abiOverride);
-        }
-
         String pkgName = res.name = parsedPackage.getPackageName();
-        if ((parsedPackage.getFlags() & ApplicationInfo.FLAG_TEST_ONLY) != 0) {
+        if (parsedPackage.isTestOnly()) {
             if ((installFlags & PackageManager.INSTALL_ALLOW_TEST) == 0) {
                 throw new PrepareFailure(INSTALL_FAILED_TEST_ONLY, "installPackageLI");
             }
@@ -16442,7 +16413,8 @@
                 parsedPackage.setSigningDetails(args.signingDetails);
             } else {
                 // TODO(b/136132412): skip for Incremental installation
-                ApkParseUtils.collectCertificates(parsedPackage, false /* skipVerify */);
+                parsedPackage.setSigningDetails(
+                        ParsingPackageUtils.collectCertificates(parsedPackage, false /* skipVerify */));
             }
         } catch (PackageParserException e) {
             throw new PrepareFailure("Failed collect during installPackageLI", e);
@@ -16464,8 +16436,7 @@
             // Check if installing already existing package
             if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
                 String oldName = mSettings.getRenamedPackageLPr(pkgName);
-                if (parsedPackage.getOriginalPackages() != null
-                        && parsedPackage.getOriginalPackages().contains(oldName)
+                if (parsedPackage.getOriginalPackages().contains(oldName)
                         && mPackages.containsKey(oldName)) {
                     // This package is derived from an original package,
                     // and this device has been updating from that original
@@ -16500,7 +16471,7 @@
                                         + " target SDK " + oldTargetSdk + " does.");
                     }
                     // Prevent persistent apps from being updated
-                    if (((oldPackage.getFlags() & ApplicationInfo.FLAG_PERSISTENT) != 0)
+                    if (oldPackage.isPersistent()
                             && ((installFlags & PackageManager.INSTALL_STAGED) == 0)) {
                         throw new PrepareFailure(PackageManager.INSTALL_FAILED_INVALID_APK,
                                 "Package " + oldPackage.getPackageName() + " is a persistent app. "
@@ -16555,7 +16526,7 @@
                 }
 
                 if (ps.pkg != null) {
-                    systemApp = (ps.pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0;
+                    systemApp = ps.pkg.isSystem();
                 }
                 res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
             }
@@ -16567,12 +16538,12 @@
                 final BasePermission bp = mPermissionManager.getPermissionTEMP(perm.getName());
 
                 // Don't allow anyone but the system to define ephemeral permissions.
-                if ((perm.protectionLevel & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
+                if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_FLAG_INSTANT) != 0
                         && !systemApp) {
                     Slog.w(TAG, "Non-System package " + parsedPackage.getPackageName()
                             + " attempting to delcare ephemeral permission "
                             + perm.getName() + "; Removing ephemeral.");
-                    perm.protectionLevel &= ~PermissionInfo.PROTECTION_FLAG_INSTANT;
+                    perm.setProtectionLevel(perm.getProtectionLevel() & ~PermissionInfo.PROTECTION_FLAG_INSTANT);
                 }
 
                 // Check whether the newly-scanned package wants to define an already-defined perm
@@ -16633,14 +16604,14 @@
                         // type as this would allow a privilege escalation where an app adds a
                         // normal/signature permission in other app's group and later redefines
                         // it as dangerous leading to the group auto-grant.
-                        if ((perm.protectionLevel & PermissionInfo.PROTECTION_MASK_BASE)
+                        if ((perm.getProtectionLevel() & PermissionInfo.PROTECTION_MASK_BASE)
                                 == PermissionInfo.PROTECTION_DANGEROUS) {
                             if (bp != null && !bp.isRuntime()) {
                                 Slog.w(TAG, "Package " + parsedPackage.getPackageName()
                                         + " trying to change a non-runtime permission "
                                         + perm.getName()
                                         + " to runtime; keeping old protection level");
-                                perm.protectionLevel = bp.getProtectionLevel();
+                                perm.setProtectionLevel(bp.getProtectionLevel());
                             }
                         }
                     }
@@ -16683,12 +16654,22 @@
             scanFlags |= SCAN_NO_DEX;
 
             try {
-                String abiOverride = (TextUtils.isEmpty(parsedPackage.getCpuAbiOverride())
-                        ? args.abiOverride : parsedPackage.getCpuAbiOverride());
-                final boolean extractNativeLibs = !parsedPackage.isLibrary();
+                final boolean extractNativeLibs = !AndroidPackageUtils.isLibrary(parsedPackage);
+                PackageSetting pkgSetting;
+                synchronized (mLock) {
+                    pkgSetting = mSettings.getPackageLPr(pkgName);
+                }
+                String abiOverride =
+                        (pkgSetting == null || TextUtils.isEmpty(pkgSetting.cpuAbiOverrideString)
+                        ? args.abiOverride : pkgSetting.cpuAbiOverrideString);
+                boolean isUpdatedSystemAppFromExistingSetting = pkgSetting != null
+                        && pkgSetting.getPkgState().isUpdatedSystemApp();
+                AndroidPackage oldPackage = mPackages.get(pkgName);
+                boolean isUpdatedSystemAppInferred = oldPackage != null && oldPackage.isSystem();
                 final Pair<PackageAbiHelper.Abis, PackageAbiHelper.NativeLibraryPaths>
-                        derivedAbi = mInjector.getAbiHelper().derivePackageAbi(
-                                parsedPackage, abiOverride, extractNativeLibs);
+                        derivedAbi = mInjector.getAbiHelper().derivePackageAbi(parsedPackage,
+                        isUpdatedSystemAppFromExistingSetting || isUpdatedSystemAppInferred,
+                        abiOverride, extractNativeLibs);
                 derivedAbi.first.applyTo(parsedPackage);
                 derivedAbi.second.applyTo(parsedPackage);
             } catch (PackageManagerException pme) {
@@ -16863,14 +16844,14 @@
                     res.removedInfo.installReasons.put(userId, ps.getInstallReason(userId));
                 }
 
-                sysPkg = (isSystemApp(oldPackage));
+                sysPkg = oldPackage.isSystem();
                 if (sysPkg) {
                     // Set the system/privileged/oem/vendor/product flags as needed
-                    final boolean privileged = isPrivilegedApp(oldPackage);
-                    final boolean oem = isOemApp(oldPackage);
-                    final boolean vendor = isVendorApp(oldPackage);
-                    final boolean product = isProductApp(oldPackage);
-                    final boolean odm = isOdmApp(oldPackage);
+                    final boolean privileged = oldPackage.isPrivileged();
+                    final boolean oem = oldPackage.isOem();
+                    final boolean vendor = oldPackage.isVendor();
+                    final boolean product = oldPackage.isProduct();
+                    final boolean odm = oldPackage.isOdm();
                     final @ParseFlags int systemParseFlags = parseFlags;
                     final @ScanFlags int systemScanFlags = scanFlags
                             | SCAN_AS_SYSTEM
@@ -16885,7 +16866,7 @@
                                 + ", old=" + oldPackage);
                     }
                     res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-                    parsedPackage.setUpdatedSystemApp(true);
+                    ps.getPkgState().setUpdatedSystemApp(true);
                     targetParseFlags = systemParseFlags;
                     targetScanFlags = systemScanFlags;
                 } else { // non system replace
@@ -17052,7 +17033,7 @@
         Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS);
         msg.obj = new IFVerificationParams(
                 pkg.getPackageName(),
-                hasDomainURLs(pkg),
+                pkg.isHasDomainUrls(),
                 pkg.getActivities(),
                 replacing,
                 userId,
@@ -17104,11 +17085,12 @@
             // examine handling policy even if not re-verifying.
             boolean needToVerify = false;
             for (ParsedActivity a : activities) {
-                for (ParsedActivityIntentInfo filter : a.intents) {
+                for (ParsedIntentInfo filter : a.getIntents()) {
                     if (filter.handlesWebUris(true)) {
                         handlesWebUris = true;
                     }
-                    if (filter.needsVerification() && needsNetworkVerificationLPr(filter)) {
+                    if (filter.needsVerification()
+                            && needsNetworkVerificationLPr(a.getPackageName())) {
                         if (DEBUG_DOMAIN_VERIFICATION) {
                             Slog.d(TAG,
                                     "Intent filter needs verification, so processing all filters");
@@ -17128,8 +17110,9 @@
             if (needToVerify) {
                 final int verificationId = mIntentFilterVerificationToken++;
                 for (ParsedActivity a : activities) {
-                    for (ParsedActivityIntentInfo filter : a.intents) {
-                        if (filter.handlesWebUris(true) && needsNetworkVerificationLPr(filter)) {
+                    for (ParsedIntentInfo filter : a.getIntents()) {
+                        if (filter.handlesWebUris(true)
+                                && needsNetworkVerificationLPr(a.getPackageName())) {
                             if (DEBUG_DOMAIN_VERIFICATION) Slog.d(TAG,
                                     "Verification needed for IntentFilter:" + filter.toString());
                             mIntentFilterVerifier.addOneIntentFilterVerification(
@@ -17164,9 +17147,7 @@
     }
 
     @GuardedBy("mLock")
-    private boolean needsNetworkVerificationLPr(ParsedActivityIntentInfo filter) {
-        final String packageName = filter.getPackageName();
-
+    private boolean needsNetworkVerificationLPr(String packageName) {
         IntentFilterVerificationInfo ivi = mSettings.getIntentFilterVerificationLPr(
                 packageName);
         if (ivi == null) {
@@ -17185,47 +17166,10 @@
         }
     }
 
-    private static boolean isExternal(AndroidPackage pkg) {
-        return (pkg.getFlags() & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
-    }
-
     private static boolean isExternal(PackageSetting ps) {
         return (ps.pkgFlags & ApplicationInfo.FLAG_EXTERNAL_STORAGE) != 0;
     }
 
-    static boolean isSystemApp(AndroidPackage pkg) {
-        return (pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0;
-    }
-
-    private static boolean isPrivilegedApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
-    }
-
-    private static boolean isOemApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;
-    }
-
-    private static boolean isVendorApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;
-    }
-
-    private static boolean isProductApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
-    }
-
-    private static boolean isSystemExtApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags()
-                & ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT) != 0;
-    }
-
-    private static boolean isOdmApp(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_ODM) != 0;
-    }
-
-    private static boolean hasDomainURLs(AndroidPackage pkg) {
-        return (pkg.getPrivateFlags() & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
-    }
-
     private static boolean isSystemApp(PackageSetting ps) {
         return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
@@ -17235,7 +17179,7 @@
     }
 
     private VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) {
-        if (isExternal(pkg)) {
+        if (pkg.isExternalStorage()) {
             if (TextUtils.isEmpty(pkg.getVolumeUuid())) {
                 return mSettings.getExternalVersion();
             } else {
@@ -17695,10 +17639,11 @@
             final AndroidPackage stubPkg =
                     (disabledSystemPs == null) ? null : disabledSystemPs.pkg;
             if (stubPkg != null && stubPkg.isStub()) {
+                final PackageSetting stubPs;
                 synchronized (mLock) {
                     // restore the enabled state of the stub; the state is overwritten when
                     // the stub is uninstalled
-                    final PackageSetting stubPs = mSettings.mPackages.get(stubPkg.getPackageName());
+                    stubPs = mSettings.getPackageLPr(stubPkg.getPackageName());
                     if (stubPs != null) {
                         stubPs.setEnabled(origEnabledState, userId, "android");
                     }
@@ -17709,7 +17654,7 @@
                         Slog.i(TAG, "Enabling system stub after removal; pkg: "
                                 + stubPkg.getPackageName());
                     }
-                    enableCompressedPackage(stubPkg);
+                    enableCompressedPackage(stubPkg, stubPs);
                 }
             }
         }
@@ -17971,14 +17916,13 @@
         }
     }
 
-    private static @Nullable SystemPartition resolveApexToSystemPartition(
+    private static @Nullable ScanPartition resolveApexToScanPartition(
             ApexManager.ActiveApexInfo apexInfo) {
         for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
-            SystemPartition sp = SYSTEM_PARTITIONS.get(i);
+            ScanPartition sp = SYSTEM_PARTITIONS.get(i);
             if (apexInfo.preInstalledApexPath.getAbsolutePath().startsWith(
                     sp.folder.getAbsolutePath())) {
-                return new SystemPartition(apexInfo.apexDirectory,
-                        sp.scanFlag | SCAN_AS_APK_IN_APEX, false /* hasOverlays */);
+                return new ScanPartition(apexInfo.apexDirectory, sp, SCAN_AS_APK_IN_APEX);
             }
         }
         return null;
@@ -18079,7 +18023,7 @@
                 | PackageParser.PARSE_IS_SYSTEM_DIR;
         @ScanFlags int scanFlags = SCAN_AS_SYSTEM;
         for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) {
-            SystemPartition partition = mDirsToScanAsSystem.get(i);
+            ScanPartition partition = mDirsToScanAsSystem.get(i);
             if (partition.containsPath(codePathString)) {
                 scanFlags |= partition.scanFlag;
                 if (partition.containsPrivPath(codePathString)) {
@@ -18093,9 +18037,12 @@
         final AndroidPackage pkg =
                 scanPackageTracedLI(codePath, parseFlags, scanFlags, 0 /*currentTime*/, null);
 
+        PackageSetting pkgSetting = mSettings.getPackageLPr(pkg.getPackageName());
+
         try {
             // update shared libraries for the newly re-installed system package
-            updateSharedLibrariesLocked(pkg, null, Collections.unmodifiableMap(mPackages));
+            updateSharedLibrariesLocked(pkg, pkgSetting, null, null,
+                    Collections.unmodifiableMap(mPackages));
         } catch (PackageManagerException e) {
             Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
         }
@@ -18429,15 +18376,7 @@
                     FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL);
             clearDefaultBrowserIfNeededForUser(ps.name, nextUserId);
             removeKeystoreDataIfNeeded(mInjector.getUserManagerInternal(), nextUserId, ps.appId);
-            final SparseBooleanArray changedUsers = new SparseBooleanArray();
-            clearPackagePreferredActivitiesLPw(ps.name, changedUsers, nextUserId);
-            if (changedUsers.size() > 0) {
-                updateDefaultHomeNotLocked(changedUsers);
-                postPreferredActivityChangedBroadcast(nextUserId);
-                synchronized (mLock) {
-                    scheduleWritePackageRestrictionsLocked(nextUserId);
-                }
-            }
+            clearPackagePreferredActivities(ps.name, nextUserId);
             mPermissionManager.resetRuntimePermissions(pkg, nextUserId);
         }
 
@@ -18534,10 +18473,11 @@
 
         // Try finding details about the requested package
         AndroidPackage pkg;
+        PackageSetting ps;
         synchronized (mLock) {
             pkg = mPackages.get(packageName);
+            ps = mSettings.mPackages.get(packageName);
             if (pkg == null) {
-                final PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps != null) {
                     pkg = ps.pkg;
                 }
@@ -18564,7 +18504,7 @@
         } else {
             flags = 0;
         }
-        prepareAppDataContentsLIF(pkg, userId, flags);
+        prepareAppDataContentsLIF(pkg, ps, userId, flags);
 
         return true;
     }
@@ -18926,13 +18866,19 @@
             }
         }
         int callingUserId = UserHandle.getCallingUserId();
+        clearPackagePreferredActivities(packageName, callingUserId);
+    }
+
+    /** This method takes a specific user id as well as UserHandle.USER_ALL. */
+    private void clearPackagePreferredActivities(String packageName, int userId) {
         final SparseBooleanArray changedUsers = new SparseBooleanArray();
-        clearPackagePreferredActivitiesLPw(packageName, changedUsers, callingUserId);
+
+        clearPackagePreferredActivitiesLPw(packageName, changedUsers, userId);
         if (changedUsers.size() > 0) {
             updateDefaultHomeNotLocked(changedUsers);
-            postPreferredActivityChangedBroadcast(callingUserId);
+            postPreferredActivityChangedBroadcast(userId);
             synchronized (mLock) {
-                scheduleWritePackageRestrictionsLocked(callingUserId);
+                scheduleWritePackageRestrictionsLocked(userId);
             }
         }
     }
@@ -20015,7 +19961,7 @@
             if (isSystemStub
                     && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                             || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
-                if (!enableCompressedPackage(deletedPkg)) {
+                if (!enableCompressedPackage(deletedPkg, pkgSetting)) {
                     return;
                 }
             }
@@ -20032,7 +19978,7 @@
                 // We're dealing with a component level state change
                 // First, verify that this is a valid class name.
                 AndroidPackage pkg = pkgSetting.pkg;
-                if (pkg == null || !pkg.hasComponentClassName(className)) {
+                if (pkg == null || !AndroidPackageUtils.hasComponentClassName(pkg, className)) {
                     if (pkg != null &&
                             pkg.getTargetSdkVersion() >=
                                     Build.VERSION_CODES.JELLY_BEAN) {
@@ -21265,24 +21211,27 @@
         ipw.println();
         ipw.println("Dexopt state:");
         ipw.increaseIndent();
-        Collection<AndroidPackage> packages;
+        Collection<PackageSetting> pkgSettings;
         if (packageName != null) {
-            AndroidPackage targetPackage = mPackages.get(packageName);
-            if (targetPackage != null) {
-                packages = Collections.singletonList(targetPackage);
+            PackageSetting targetPkgSetting = mSettings.mPackages.get(packageName);
+            if (targetPkgSetting != null) {
+                pkgSettings = Collections.singletonList(targetPkgSetting);
             } else {
                 ipw.println("Unable to find package: " + packageName);
                 return;
             }
         } else {
-            packages = mPackages.values();
+            pkgSettings = mSettings.mPackages.values();
         }
 
-        for (AndroidPackage pkg : packages) {
-            ipw.println("[" + pkg.getPackageName() + "]");
+        for (PackageSetting pkgSetting : pkgSettings) {
+            if (pkgSetting.pkg == null) {
+                continue;
+            }
+            ipw.println("[" + pkgSetting.name + "]");
             ipw.increaseIndent();
-            mPackageDexOptimizer.dumpDexoptState(ipw, pkg,
-                    mDexManager.getPackageUseInfoOrDefault(pkg.getPackageName()));
+            mPackageDexOptimizer.dumpDexoptState(ipw, pkgSetting.pkg, pkgSetting,
+                    mDexManager.getPackageUseInfoOrDefault(pkgSetting.pkg.getPackageName()));
             ipw.decreaseIndent();
         }
     }
@@ -21388,7 +21337,7 @@
         final int[] packageUids = new int[size];
         for (int i = 0; i < size; i++) {
             final AndroidPackage pkg = packages.get(i);
-            packageNames[i] = pkg.getAppInfoPackageName();
+            packageNames[i] = pkg.getPackageName();
             packageUids[i] = pkg.getUid();
         }
         sendResourcesChangedBroadcast(mediaStatus, replacing, packageNames, packageUids,
@@ -21785,6 +21734,7 @@
         }
 
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
+        StorageManagerInternal smInternal = mInjector.getStorageManagerInternal();
         for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
             final int flags;
             if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
@@ -21798,6 +21748,13 @@
             if (ps.getInstalled(user.id)) {
                 // TODO: when user data is locked, mark that we're still dirty
                 prepareAppDataLIF(pkg, user.id, flags);
+
+                if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+                    // Prepare app data on external storage; currently this is used to
+                    // setup any OBB dirs that were created by the installer correctly.
+                    int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
+                    smInternal.prepareAppDataAfterInstall(pkg.getPackageName(), uid);
+                }
             }
         }
     }
@@ -21844,16 +21801,17 @@
 
         final int appId = UserHandle.getAppId(pkg.getUid());
 
-        Preconditions.checkNotNull(pkg.getSeInfo());
+        String pkgSeInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
 
-        final String seInfo =
-                pkg.getSeInfo() + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : "");
+        Preconditions.checkNotNull(pkgSeInfo);
+
+        final String seInfo = pkgSeInfo + (pkg.getSeInfoUser() != null ? pkg.getSeInfoUser() : "");
         long ceDataInode = -1;
         try {
             ceDataInode = mInstaller.createAppData(volumeUuid, packageName, userId, flags,
                     appId, seInfo, pkg.getTargetSdkVersion());
         } catch (InstallerException e) {
-            if (pkg.isSystemApp()) {
+            if (pkg.isSystem()) {
                 logCriticalInfo(Log.ERROR, "Failed to create app data for " + packageName
                         + ", but trying to recover: " + e);
                 destroyAppDataLeafLIF(pkg, userId, flags);
@@ -21898,18 +21856,20 @@
             }
         }
 
-        prepareAppDataContentsLeafLIF(pkg, userId, flags);
+        prepareAppDataContentsLeafLIF(pkg, ps, userId, flags);
     }
 
-    private void prepareAppDataContentsLIF(AndroidPackage pkg, int userId, int flags) {
+    private void prepareAppDataContentsLIF(AndroidPackage pkg, @Nullable PackageSetting pkgSetting,
+            int userId, int flags) {
         if (pkg == null) {
             Slog.wtf(TAG, "Package was null!", new Throwable());
             return;
         }
-        prepareAppDataContentsLeafLIF(pkg, userId, flags);
+        prepareAppDataContentsLeafLIF(pkg, pkgSetting, userId, flags);
     }
 
-    private void prepareAppDataContentsLeafLIF(AndroidPackage pkg, int userId, int flags) {
+    private void prepareAppDataContentsLeafLIF(AndroidPackage pkg,
+            @Nullable PackageSetting pkgSetting, int userId, int flags) {
         final String volumeUuid = pkg.getVolumeUuid();
         final String packageName = pkg.getPackageName();
 
@@ -21917,7 +21877,8 @@
             // Create a native library symlink only if we have native libraries
             // and if the native libraries are 32 bit libraries. We do not provide
             // this symlink for 64 bit libraries.
-            if (pkg.getPrimaryCpuAbi() != null && !VMRuntime.is64BitAbi(pkg.getPrimaryCpuAbi())) {
+            String primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting);
+            if (primaryCpuAbi != null && !VMRuntime.is64BitAbi(primaryCpuAbi)) {
                 final String nativeLibPath = pkg.getNativeLibraryDir();
                 try {
                     mInstaller.linkNativeLibraryDirectory(volumeUuid, packageName,
@@ -22106,7 +22067,7 @@
                     || shouldFilterApplicationLocked(ps, callingUid, user.getIdentifier())) {
                 throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
             }
-            if (pkg.isSystemApp()) {
+            if (pkg.isSystem()) {
                 throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
                         "Cannot move system application");
             }
@@ -22132,7 +22093,7 @@
                 throw new PackageManagerException(MOVE_FAILED_INTERNAL_ERROR,
                         "Package already moved to " + volumeUuid);
             }
-            if (pkg.isInternal() && isPackageDeviceAdminOnAnyUser(packageName)) {
+            if (!pkg.isExternalStorage() && isPackageDeviceAdminOnAnyUser(packageName)) {
                 throw new PackageManagerException(MOVE_FAILED_DEVICE_ADMIN,
                         "Device admin cannot be moved");
             }
@@ -22142,17 +22103,21 @@
                         "Failed to move already frozen package");
             }
 
-            isCurrentLocationExternal = isExternal(pkg);
+            isCurrentLocationExternal = pkg.isExternalStorage();
             codeFile = new File(pkg.getCodePath());
             installSource = ps.installSource;
             packageAbiOverride = ps.cpuAbiOverrideString;
             appId = UserHandle.getAppId(pkg.getUid());
-            seinfo = pkg.getSeInfo();
+            seinfo = AndroidPackageUtils.getSeInfo(pkg, ps);
             label = String.valueOf(pm.getApplicationLabel(pkg.toAppInfoWithoutState()));
             targetSdkVersion = pkg.getTargetSdkVersion();
             freezer = freezePackage(packageName, "movePackageInternal");
             installedUserIds = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
-            fromCodePath = pkg.getCodePath();
+            if (codeFile.getParentFile().getName().startsWith(RANDOM_DIR_PREFIX)) {
+                fromCodePath = codeFile.getParentFile().getAbsolutePath();
+            } else {
+                fromCodePath = codeFile.getAbsolutePath();
+            }
         }
 
         final Bundle extras = new Bundle();
@@ -22279,9 +22244,8 @@
                 }
             }).start();
 
-            final String dataAppName = codeFile.getName();
             move = new MoveInfo(moveId, currentVolumeUuid, volumeUuid, packageName,
-                    dataAppName, appId, seinfo, targetSdkVersion, fromCodePath);
+                    appId, seinfo, targetSdkVersion, fromCodePath);
         } else {
             move = null;
         }
@@ -22322,15 +22286,15 @@
 
         final StorageManager storage = mInjector.getStorageManager();;
         VolumeInfo volume = storage.findVolumeByUuid(pkg.getStorageUuid().toString());
-        int packageExternalStorageType = getPackageExternalStorageType(volume, isExternal(pkg));
+        int packageExternalStorageType = getPackageExternalStorageType(volume, pkg.isExternalStorage());
 
-        if (!isPreviousLocationExternal && isExternal(pkg)) {
+        if (!isPreviousLocationExternal && pkg.isExternalStorage()) {
             // Move from internal to external storage.
             FrameworkStatsLog.write(FrameworkStatsLog.APP_MOVED_STORAGE_REPORTED,
                     packageExternalStorageType,
                     FrameworkStatsLog.APP_MOVED_STORAGE_REPORTED__MOVE_TYPE__TO_EXTERNAL,
                     packageName);
-        } else if (isPreviousLocationExternal && !isExternal(pkg)) {
+        } else if (isPreviousLocationExternal && !pkg.isExternalStorage()) {
             // Move from external to internal storage.
             FrameworkStatsLog.write(FrameworkStatsLog.APP_MOVED_STORAGE_REPORTED,
                     packageExternalStorageType,
@@ -23054,7 +23018,7 @@
         }
 
         @Override
-        public Object getDisabledSystemPackage(@NonNull String packageName) {
+        public PackageSetting getDisabledSystemPackage(@NonNull String packageName) {
             synchronized (mLock) {
                 return mSettings.getDisabledSystemPkgLPr(packageName);
             }
@@ -23324,7 +23288,7 @@
         public List<ResolveInfo> queryIntentActivities(
                 Intent intent, String resolvedType, int flags, int filterCallingUid, int userId) {
             return PackageManagerService.this
-                    .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
+                    .queryIntentActivitiesInternal(intent, resolvedType, flags, 0, filterCallingUid,
                             userId, false /*resolveForStart*/, true /*allowDynamicSplits*/);
         }
 
@@ -23404,7 +23368,7 @@
         }
 
         @Override
-        public boolean isEnabledAndMatches(ParsedComponent component, int flags, int userId) {
+        public boolean isEnabledAndMatches(ParsedMainComponent component, int flags, int userId) {
             synchronized (mLock) {
                 AndroidPackage pkg = getPackage(component.getPackageName());
                 return mSettings.isEnabledAndMatchLPr(pkg, component, flags, userId);
@@ -23496,11 +23460,7 @@
         public boolean isPackagePersistent(String packageName) {
             synchronized (mLock) {
                 AndroidPackage pkg = mPackages.get(packageName);
-                return pkg != null
-                        ? ((pkg.getFlags() & (ApplicationInfo.FLAG_SYSTEM
-                                        | ApplicationInfo.FLAG_PERSISTENT)) ==
-                                (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_PERSISTENT))
-                        : false;
+                return pkg != null && pkg.isSystem() && pkg.isPersistent();
             }
         }
 
@@ -23610,9 +23570,11 @@
 
         @Override
         public ResolveInfo resolveIntent(Intent intent, String resolvedType,
-                int flags, int userId, boolean resolveForStart, int filterCallingUid) {
+                int flags, int privateResolveFlags, int userId, boolean resolveForStart,
+                int filterCallingUid) {
             return resolveIntentInternal(
-                    intent, resolvedType, flags, userId, resolveForStart, filterCallingUid);
+                    intent, resolvedType, flags, privateResolveFlags, userId, resolveForStart,
+                    filterCallingUid);
         }
 
         @Override
@@ -23729,6 +23691,15 @@
         }
 
         @Override
+        public void forEachPackageSetting(Consumer<PackageSetting> actionLocked) {
+            synchronized (mLock) {
+                for (int index = 0; index < mSettings.mPackages.size(); index++) {
+                    actionLocked.accept(mSettings.mPackages.valueAt(index));
+                }
+            }
+        }
+
+        @Override
         public void forEachInstalledPackage(@NonNull Consumer<AndroidPackage> actionLocked,
                 @UserIdInt int userId) {
             PackageManagerService.this.forEachInstalledPackage(actionLocked, userId);
@@ -23932,6 +23903,11 @@
             msg.obj = verificationResult;
             mHandler.sendMessage(msg);
         }
+
+        @Override
+        public List<String> getMimeGroup(String packageName, String mimeGroup) {
+            return PackageManagerService.this.getMimeGroup(packageName, mimeGroup);
+        }
     }
 
     @GuardedBy("mLock")
@@ -24219,15 +24195,18 @@
     boolean canHaveOatDir(String packageName) {
         synchronized (mLock) {
             AndroidPackage p = mPackages.get(packageName);
-            if (p == null) {
+            PackageSetting pkgSetting = mSettings.getPackageLPr(packageName);
+            if (p == null || pkgSetting == null) {
                 return false;
             }
-            return p.canHaveOatDir();
+            return AndroidPackageUtils.canHaveOatDir(p,
+                    pkgSetting.getPkgState().isUpdatedSystemApp());
         }
     }
 
-    private String getOatDir(AndroidPackage pkg) {
-        if (!pkg.canHaveOatDir()) {
+    private String getOatDir(AndroidPackage pkg, @NonNull PackageSetting pkgSetting) {
+        if (!AndroidPackageUtils.canHaveOatDir(pkg,
+                pkgSetting.getPkgState().isUpdatedSystemApp())) {
             return null;
         }
         File codePath = new File(pkg.getCodePath());
@@ -24242,13 +24221,16 @@
         final List<String> codePaths;
         final String oatDir;
         final AndroidPackage pkg;
+        final PackageSetting pkgSetting;
         synchronized (mLock) {
             pkg = mPackages.get(packageName);
+            pkgSetting = mSettings.getPackageLPr(packageName);
         }
-        instructionSets = getAppDexInstructionSets(pkg.getPrimaryCpuAbi(),
-                pkg.getSecondaryCpuAbi());
-        codePaths = pkg.getAllCodePaths();
-        oatDir = getOatDir(pkg);
+        instructionSets = getAppDexInstructionSets(
+                AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting),
+                AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting));
+        codePaths = AndroidPackageUtils.getAllCodePaths(pkg);
+        oatDir = getOatDir(pkg, pkgSetting);
 
         for (String codePath : codePaths) {
             for (String isa : instructionSets) {
@@ -24275,8 +24257,8 @@
                 if (PackageManagerServiceUtils
                         .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis,
                                 downgradeTimeThresholdMillis, packageUseInfo,
-                                pkg.getLatestPackageUseTimeInMills(),
-                                pkg.getLatestForegroundPackageUseTimeInMills())) {
+                                ps.getPkgState().getLatestPackageUseTimeInMills(),
+                                ps.getPkgState().getLatestForegroundPackageUseTimeInMills())) {
                     unusedPackages.add(pkg.getPackageName());
                 }
             }
@@ -24367,6 +24349,38 @@
         }
     }
 
+    private void applyMimeGroupChanges(String packageName, String mimeGroup) {
+        if (mComponentResolver.updateMimeGroup(packageName, mimeGroup)) {
+            clearPackagePreferredActivities(packageName, UserHandle.USER_ALL);
+        }
+
+        mPmInternal.writeSettings(false);
+    }
+
+    @Override
+    public void setMimeGroup(String packageName, String mimeGroup, List<String> mimeTypes) {
+        boolean changed = mSettings.mPackages.get(packageName)
+                .setMimeGroup(mimeGroup, mimeTypes);
+
+        if (changed) {
+            applyMimeGroupChanges(packageName, mimeGroup);
+        }
+    }
+
+    @Override
+    public void clearMimeGroup(String packageName, String mimeGroup) {
+        boolean changed = mSettings.mPackages.get(packageName).clearMimeGroup(mimeGroup);
+
+        if (changed) {
+            applyMimeGroupChanges(packageName, mimeGroup);
+        }
+    }
+
+    @Override
+    public List<String> getMimeGroup(String packageName, String mimeGroup) {
+        return mSettings.mPackages.get(packageName).getMimeGroup(mimeGroup);
+    }
+
     static class ActiveInstallSession {
         private final String mPackageName;
         private final File mStagedDir;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index a9035b2..91afd84 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -40,8 +40,7 @@
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.ResolveInfo;
 import android.content.pm.Signature;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ApkParseUtils;
+import android.content.pm.parsing.ParsingPackageUtils;
 import android.os.Build;
 import android.os.Debug;
 import android.os.Environment;
@@ -66,6 +65,7 @@
 import com.android.server.EventLogTags;
 import com.android.server.pm.dex.DexManager;
 import com.android.server.pm.dex.PackageDexUsage;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionsState;
 
 import dalvik.system.VMRuntime;
@@ -94,6 +94,8 @@
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.function.Predicate;
 import java.util.zip.GZIPInputStream;
 
@@ -105,6 +107,9 @@
 public class PackageManagerServiceUtils {
     private final static long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000;
 
+    public final static Predicate<PackageSetting> REMOVE_IF_NULL_PKG =
+            pkgSetting -> pkgSetting.pkg == null;
+
     private static ArraySet<String> getPackageNamesForIntent(Intent intent, int userId) {
         List<ResolveInfo> ris = null;
         try {
@@ -124,40 +129,43 @@
     // Sort a list of apps by their last usage, most recently used apps first. The order of
     // packages without usage data is undefined (but they will be sorted after the packages
     // that do have usage data).
-    public static void sortPackagesByUsageDate(List<AndroidPackage> pkgs,
+    public static void sortPackagesByUsageDate(List<PackageSetting> pkgSettings,
             PackageManagerService packageManagerService) {
         if (!packageManagerService.isHistoricalPackageUsageAvailable()) {
             return;
         }
 
-        Collections.sort(pkgs, (pkg1, pkg2) ->
-                Long.compare(pkg2.getLatestForegroundPackageUseTimeInMills(),
-                        pkg1.getLatestForegroundPackageUseTimeInMills()));
+        Collections.sort(pkgSettings, (pkgSetting1, pkgSetting2) ->
+                Long.compare(
+                        pkgSetting2.getPkgState().getLatestForegroundPackageUseTimeInMills(),
+                        pkgSetting1.getPkgState().getLatestForegroundPackageUseTimeInMills())
+        );
     }
 
     // Apply the given {@code filter} to all packages in {@code packages}. If tested positive, the
     // package will be removed from {@code packages} and added to {@code result} with its
     // dependencies. If usage data is available, the positive packages will be sorted by usage
     // data (with {@code sortTemp} as temporary storage).
-    private static void applyPackageFilter(Predicate<AndroidPackage> filter,
-            Collection<AndroidPackage> result,
-            Collection<AndroidPackage> packages,
-            @NonNull List<AndroidPackage> sortTemp,
+    private static void applyPackageFilter(
+            Predicate<PackageSetting> filter,
+            Collection<PackageSetting> result,
+            Collection<PackageSetting> packages,
+            @NonNull List<PackageSetting> sortTemp,
             PackageManagerService packageManagerService) {
-        for (AndroidPackage pkg : packages) {
-            if (filter.test(pkg)) {
-                sortTemp.add(pkg);
+        for (PackageSetting pkgSetting : packages) {
+            if (filter.test(pkgSetting)) {
+                sortTemp.add(pkgSetting);
             }
         }
 
         sortPackagesByUsageDate(sortTemp, packageManagerService);
         packages.removeAll(sortTemp);
 
-        for (AndroidPackage pkg : sortTemp) {
-            result.add(pkg);
+        for (PackageSetting pkgSetting : sortTemp) {
+            result.add(pkgSetting);
 
-            Collection<AndroidPackage> deps =
-                    packageManagerService.findSharedNonSystemLibraries(pkg);
+            List<PackageSetting> deps =
+                    packageManagerService.findSharedNonSystemLibraries(pkgSetting);
             if (!deps.isEmpty()) {
                 deps.removeAll(result);
                 result.addAll(deps);
@@ -170,74 +178,79 @@
 
     // Sort apps by importance for dexopt ordering. Important apps are given
     // more priority in case the device runs out of space.
-    public static List<AndroidPackage> getPackagesForDexopt(
-            Collection<AndroidPackage> packages,
+    public static List<PackageSetting> getPackagesForDexopt(
+            Collection<PackageSetting> packages,
             PackageManagerService packageManagerService) {
         return getPackagesForDexopt(packages, packageManagerService, DEBUG_DEXOPT);
     }
 
-    public static List<AndroidPackage> getPackagesForDexopt(
-            Collection<AndroidPackage> packages,
+    public static List<PackageSetting> getPackagesForDexopt(
+            Collection<PackageSetting> pkgSettings,
             PackageManagerService packageManagerService,
             boolean debug) {
-        ArrayList<AndroidPackage> remainingPkgs = new ArrayList<>(packages);
-        LinkedList<AndroidPackage> result = new LinkedList<>();
-        ArrayList<AndroidPackage> sortTemp = new ArrayList<>(remainingPkgs.size());
+        List<PackageSetting> result = new LinkedList<>();
+        ArrayList<PackageSetting> remainingPkgSettings = new ArrayList<>(pkgSettings);
+
+        // First, remove all settings without available packages
+        remainingPkgSettings.removeIf(REMOVE_IF_NULL_PKG);
+
+        ArrayList<PackageSetting> sortTemp = new ArrayList<>(remainingPkgSettings.size());
 
         // Give priority to core apps.
-        applyPackageFilter((pkg) -> pkg.isCoreApp(), result, remainingPkgs, sortTemp,
+        applyPackageFilter(pkgSetting -> pkgSetting.pkg.isCoreApp(), result, remainingPkgSettings, sortTemp,
                 packageManagerService);
 
         // Give priority to system apps that listen for pre boot complete.
         Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED);
         final ArraySet<String> pkgNames = getPackageNamesForIntent(intent, UserHandle.USER_SYSTEM);
-        applyPackageFilter((pkg) -> pkgNames.contains(pkg.getPackageName()), result, remainingPkgs,
-                sortTemp, packageManagerService);
+        applyPackageFilter(pkgSetting -> pkgNames.contains(pkgSetting.name), result,
+                remainingPkgSettings, sortTemp, packageManagerService);
 
         // Give priority to apps used by other apps.
         DexManager dexManager = packageManagerService.getDexManager();
-        applyPackageFilter((pkg) ->
-                dexManager.getPackageUseInfoOrDefault(pkg.getPackageName())
+        applyPackageFilter(pkgSetting ->
+                dexManager.getPackageUseInfoOrDefault(pkgSetting.name)
                         .isAnyCodePathUsedByOtherApps(),
-                result, remainingPkgs, sortTemp, packageManagerService);
+                result, remainingPkgSettings, sortTemp, packageManagerService);
 
         // Filter out packages that aren't recently used, add all remaining apps.
         // TODO: add a property to control this?
-        Predicate<AndroidPackage> remainingPredicate;
-        if (!remainingPkgs.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) {
+        Predicate<PackageSetting> remainingPredicate;
+        if (!remainingPkgSettings.isEmpty() && packageManagerService.isHistoricalPackageUsageAvailable()) {
             if (debug) {
                 Log.i(TAG, "Looking at historical package use");
             }
             // Get the package that was used last.
-            AndroidPackage lastUsed = Collections.max(remainingPkgs, (pkg1, pkg2) ->
-                    Long.compare(pkg1.getLatestForegroundPackageUseTimeInMills(),
-                            pkg2.getLatestForegroundPackageUseTimeInMills()));
+            PackageSetting lastUsed = Collections.max(remainingPkgSettings,
+                    (pkgSetting1, pkgSetting2) -> Long.compare(
+                            pkgSetting1.getPkgState().getLatestForegroundPackageUseTimeInMills(),
+                            pkgSetting2.getPkgState().getLatestForegroundPackageUseTimeInMills()));
             if (debug) {
-                Log.i(TAG, "Taking package " + lastUsed.getPackageName()
+                Log.i(TAG, "Taking package " + lastUsed.name
                         + " as reference in time use");
             }
-            long estimatedPreviousSystemUseTime =
-                    lastUsed.getLatestForegroundPackageUseTimeInMills();
+            long estimatedPreviousSystemUseTime = lastUsed.getPkgState()
+                    .getLatestForegroundPackageUseTimeInMills();
             // Be defensive if for some reason package usage has bogus data.
             if (estimatedPreviousSystemUseTime != 0) {
                 final long cutoffTime = estimatedPreviousSystemUseTime - SEVEN_DAYS_IN_MILLISECONDS;
-                remainingPredicate =
-                        (pkg) -> pkg.getLatestForegroundPackageUseTimeInMills() >= cutoffTime;
+                remainingPredicate = pkgSetting -> pkgSetting.getPkgState()
+                        .getLatestForegroundPackageUseTimeInMills() >= cutoffTime;
             } else {
                 // No meaningful historical info. Take all.
-                remainingPredicate = (pkg) -> true;
+                remainingPredicate = pkgSetting -> true;
             }
-            sortPackagesByUsageDate(remainingPkgs, packageManagerService);
+            sortPackagesByUsageDate(remainingPkgSettings, packageManagerService);
         } else {
             // No historical info. Take all.
-            remainingPredicate = (pkg) -> true;
+            remainingPredicate = pkgSetting -> true;
         }
-        applyPackageFilter(remainingPredicate, result, remainingPkgs, sortTemp,
+        applyPackageFilter(remainingPredicate, result, remainingPkgSettings, sortTemp,
                 packageManagerService);
 
         if (debug) {
             Log.i(TAG, "Packages to be dexopted: " + packagesToString(result));
-            Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgs));
+            Log.i(TAG, "Packages skipped from dexopt: " + packagesToString(remainingPkgSettings));
         }
 
         return result;
@@ -290,13 +303,13 @@
         }
     }
 
-    public static String packagesToString(Collection<AndroidPackage> c) {
+    public static String packagesToString(List<PackageSetting> pkgSettings) {
         StringBuilder sb = new StringBuilder();
-        for (AndroidPackage pkg : c) {
+        for (int index = 0; index < pkgSettings.size(); index++) {
             if (sb.length() > 0) {
                 sb.append(", ");
             }
-            sb.append(pkg.getPackageName());
+            sb.append(pkgSettings.get(index).name);
         }
         return sb.toString();
     }
@@ -543,23 +556,16 @@
      */
     private static boolean matchSignatureInSystem(PackageSetting pkgSetting,
             PackageSetting disabledPkgSetting) {
-        try {
-            ApkParseUtils.collectCertificates(disabledPkgSetting.pkg, true /* skipVerify */);
-            if (pkgSetting.signatures.mSigningDetails.checkCapability(
-                    disabledPkgSetting.signatures.mSigningDetails,
-                    PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)
-                    || disabledPkgSetting.signatures.mSigningDetails.checkCapability(
-                            pkgSetting.signatures.mSigningDetails,
-                            PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) {
-                return true;
-            } else {
-                logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
-                        pkgSetting.name);
-                return false;
-            }
-        } catch (PackageParserException e) {
-            logCriticalInfo(Log.ERROR, "Failed to collect cert for " + pkgSetting.name + ": " +
-                    e.getMessage());
+        if (pkgSetting.signatures.mSigningDetails.checkCapability(
+                disabledPkgSetting.signatures.mSigningDetails,
+                PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)
+                || disabledPkgSetting.signatures.mSigningDetails.checkCapability(
+                pkgSetting.signatures.mSigningDetails,
+                PackageParser.SigningDetails.CertCapabilities.ROLLBACK)) {
+            return true;
+        } else {
+            logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
+                    pkgSetting.name);
             return false;
         }
     }
@@ -642,8 +648,8 @@
             }
         }
         // Check for shared user signatures
-        if (pkgSetting.sharedUser != null
-                && pkgSetting.sharedUser.signatures.mSigningDetails
+        if (pkgSetting.getSharedUser() != null
+                && pkgSetting.getSharedUser().signatures.mSigningDetails
                         != PackageParser.SigningDetails.UNKNOWN) {
 
             // Already existing package. Make sure signatures match.  In case of signing certificate
@@ -653,24 +659,24 @@
             // with being sharedUser with the existing signing cert.
             boolean match =
                     parsedSignatures.checkCapability(
-                            pkgSetting.sharedUser.signatures.mSigningDetails,
+                            pkgSetting.getSharedUser().signatures.mSigningDetails,
                             PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID)
-                    || pkgSetting.sharedUser.signatures.mSigningDetails.checkCapability(
+                    || pkgSetting.getSharedUser().signatures.mSigningDetails.checkCapability(
                             parsedSignatures,
                             PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID);
             if (!match && compareCompat) {
                 match = matchSignaturesCompat(
-                        packageName, pkgSetting.sharedUser.signatures, parsedSignatures);
+                        packageName, pkgSetting.getSharedUser().signatures, parsedSignatures);
             }
             if (!match && compareRecover) {
                 match =
                         matchSignaturesRecover(packageName,
-                                pkgSetting.sharedUser.signatures.mSigningDetails,
+                                pkgSetting.getSharedUser().signatures.mSigningDetails,
                                 parsedSignatures,
                                 PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID)
                         || matchSignaturesRecover(packageName,
                                 parsedSignatures,
-                                pkgSetting.sharedUser.signatures.mSigningDetails,
+                                pkgSetting.getSharedUser().signatures.mSigningDetails,
                                 PackageParser.SigningDetails.CertCapabilities.SHARED_USER_ID);
                 compatMatch |= match;
             }
@@ -678,7 +684,7 @@
                 throw new PackageManagerException(INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                         "Package " + packageName
                         + " has no signatures that match those in shared user "
-                        + pkgSetting.sharedUser.name + "; ignoring!");
+                        + pkgSetting.getSharedUser().name + "; ignoring!");
             }
         }
         return compatMatch;
@@ -823,11 +829,11 @@
      * Checks whenever downgrade of an app is permitted.
      *
      * @param installFlags flags of the current install.
-     * @param applicationFlags flags of the currently installed version of the app.
+     * @param isAppDebuggable if the currently installed version of the app is debuggable.
      * @return {@code true} if downgrade is permitted according to the {@code installFlags} and
      *         {@code applicationFlags}.
      */
-    public static boolean isDowngradePermitted(int installFlags, int applicationFlags) {
+    public static boolean isDowngradePermitted(int installFlags, boolean isAppDebuggable) {
         // If installed, the package will get access to data left on the device by its
         // predecessor. As a security measure, this is permitted only if this is not a
         // version downgrade or if the predecessor package is marked as debuggable and
@@ -849,9 +855,7 @@
         if (!downgradeRequested) {
             return false;
         }
-        final boolean isDebuggable =
-                Build.IS_DEBUGGABLE || ((applicationFlags
-                        & ApplicationInfo.FLAG_DEBUGGABLE) != 0);
+        final boolean isDebuggable = Build.IS_DEBUGGABLE || isAppDebuggable;
         if (isDebuggable) {
             return true;
         }
@@ -915,8 +919,8 @@
      */
     public static PermissionsState getPermissionsState(
             PackageManagerInternal packageManagerInternal, AndroidPackage pkg) {
-        final PackageSetting packageSetting =
-                (PackageSetting) packageManagerInternal.getPackageSetting(pkg.getPackageName());
+        final PackageSetting packageSetting = packageManagerInternal.getPackageSetting(
+                pkg.getPackageName());
         if (packageSetting == null) {
             return null;
         }
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index bbc0dc9..2bd1a26 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -16,24 +16,31 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
 import android.service.pm.PackageProto;
+import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionsState;
+import com.android.server.pm.pkg.PackageStateUnserialized;
 
 import java.io.File;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
 /**
  * Settings data for a particular package we know about.
  */
-public final class PackageSetting extends PackageSettingBase implements
-        ParsedPackage.PackageSettingCallback {
+public class PackageSetting extends PackageSettingBase {
     int appId;
 
     public AndroidPackage pkg;
@@ -50,17 +57,29 @@
      */
     private int sharedUserId;
 
+    /**
+     *  Maps mime group name to the set of Mime types in a group. Mime groups declared
+     *  by app are populated with empty sets at construction.
+     *  Mime groups can not be created/removed at runtime, thus keys in this map should not change
+     */
+    @Nullable
+    Map<String, ArraySet<String>> mimeGroups;
+
+    @NonNull
+    private PackageStateUnserialized pkgState = new PackageStateUnserialized();
+
     PackageSetting(String name, String realName, File codePath, File resourcePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString,
             long pVersionCode, int pkgFlags, int privateFlags,
             int sharedUserId, String[] usesStaticLibraries,
-            long[] usesStaticLibrariesVersions) {
+            long[] usesStaticLibrariesVersions, Map<String, ArraySet<String>> mimeGroups) {
         super(name, realName, codePath, resourcePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
                 pVersionCode, pkgFlags, privateFlags,
                 usesStaticLibraries, usesStaticLibrariesVersions);
         this.sharedUserId = sharedUserId;
+        copyMimeGroups(mimeGroups);
     }
 
     /**
@@ -110,6 +129,53 @@
         pkg = orig.pkg;
         sharedUser = orig.sharedUser;
         sharedUserId = orig.sharedUserId;
+        copyMimeGroups(orig.mimeGroups);
+    }
+
+    private void copyMimeGroups(@Nullable Map<String, ArraySet<String>> newMimeGroups) {
+        if (newMimeGroups == null) {
+            mimeGroups = null;
+            return;
+        }
+
+        mimeGroups = new ArrayMap<>(newMimeGroups.size());
+        for (String mimeGroup : newMimeGroups.keySet()) {
+            ArraySet<String> mimeTypes = newMimeGroups.get(mimeGroup);
+
+            if (mimeTypes != null) {
+                mimeGroups.put(mimeGroup, new ArraySet<>(mimeTypes));
+            } else {
+                mimeGroups.put(mimeGroup, new ArraySet<>());
+            }
+        }
+    }
+
+    /**
+     * Updates declared MIME groups, removing no longer declared groups
+     * and keeping previous state of MIME groups
+     */
+    void updateMimeGroups(@Nullable Set<String> newMimeGroupNames) {
+        if (newMimeGroupNames == null) {
+            mimeGroups = null;
+            return;
+        }
+
+        if (mimeGroups == null) {
+            // set mimeGroups to empty map to avoid repeated null-checks in the next loop
+            mimeGroups = Collections.emptyMap();
+        }
+
+        ArrayMap<String, ArraySet<String>> updatedMimeGroups =
+                new ArrayMap<>(newMimeGroupNames.size());
+
+        for (String mimeGroup : newMimeGroupNames) {
+            if (mimeGroups.containsKey(mimeGroup)) {
+                updatedMimeGroups.put(mimeGroup, mimeGroups.get(mimeGroup));
+            } else {
+                updatedMimeGroups.put(mimeGroup, new ArraySet<>());
+            }
+        }
+        mimeGroups = updatedMimeGroups;
     }
 
     @Override
@@ -160,10 +226,6 @@
         return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
 
-    public boolean isUpdatedSystem() {
-        return (pkgFlags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;
-    }
-
     @Override
     public boolean isSharedUser() {
         return sharedUser != null;
@@ -176,6 +238,41 @@
         return true;
     }
 
+    public boolean setMimeGroup(String mimeGroup, List<String> mimeTypes) {
+        ArraySet<String> oldMimeTypes = getMimeGroupInternal(mimeGroup);
+        if (oldMimeTypes == null) {
+            return false;
+        }
+
+        ArraySet<String> newMimeTypes = new ArraySet<>(mimeTypes);
+        boolean hasChanges = !newMimeTypes.equals(oldMimeTypes);
+        mimeGroups.put(mimeGroup, newMimeTypes);
+        return hasChanges;
+    }
+
+    public boolean clearMimeGroup(String mimeGroup) {
+        ArraySet<String> mimeTypes = getMimeGroupInternal(mimeGroup);
+
+        if (mimeTypes == null || mimeTypes.isEmpty()) {
+            return false;
+        }
+
+        mimeTypes.clear();
+        return true;
+    }
+
+    public List<String> getMimeGroup(String mimeGroup) {
+        ArraySet<String> mimeTypes = getMimeGroupInternal(mimeGroup);
+        if (mimeTypes == null) {
+            return null;
+        }
+        return new ArrayList<>(mimeTypes);
+    }
+
+    private ArraySet<String> getMimeGroupInternal(String mimeGroup) {
+        return mimeGroups != null ? mimeGroups.get(mimeGroup) : null;
+    }
+
     public void dumpDebug(ProtoOutputStream proto, long fieldId, List<UserInfo> users) {
         final long packageToken = proto.start(fieldId);
         proto.write(PackageProto.NAME, (realName != null ? realName : name));
@@ -221,11 +318,13 @@
         pkg = other.pkg;
         sharedUserId = other.sharedUserId;
         sharedUser = other.sharedUser;
+
+        Set<String> mimeGroupNames = other.mimeGroups != null ? other.mimeGroups.keySet() : null;
+        updateMimeGroups(mimeGroupNames);
     }
 
-    // TODO(b/135203078): Move to constructor
-    @Override
-    public void setAndroidPackage(AndroidPackage pkg) {
-        this.pkg = pkg;
+    @NonNull
+    public PackageStateUnserialized getPkgState() {
+        return pkgState;
     }
 }
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 7d95b19..18bc879 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -78,12 +78,12 @@
     /**
      * The primary CPU abi for this package.
      */
-    String primaryCpuAbiString;
+    public String primaryCpuAbiString;
 
     /**
      * The secondary CPU abi for this package.
      */
-    String secondaryCpuAbiString;
+    public String secondaryCpuAbiString;
 
     /**
      * The install time CPU override, if any. This value is written at install time
diff --git a/services/core/java/com/android/server/pm/PackageUsage.java b/services/core/java/com/android/server/pm/PackageUsage.java
index ce2c9e7..ef37a20 100644
--- a/services/core/java/com/android/server/pm/PackageUsage.java
+++ b/services/core/java/com/android/server/pm/PackageUsage.java
@@ -20,11 +20,12 @@
 import static android.os.Process.SYSTEM_UID;
 
 import android.content.pm.PackageManager;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.FileUtils;
 import android.util.AtomicFile;
 import android.util.Log;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
 import libcore.io.IoUtils;
 
 import java.io.BufferedInputStream;
@@ -36,7 +37,7 @@
 import java.nio.charset.StandardCharsets;
 import java.util.Map;
 
-class PackageUsage extends AbstractStatsBase<Map<String, AndroidPackage>> {
+class PackageUsage extends AbstractStatsBase<Map<String, PackageSetting>> {
 
     private static final String USAGE_FILE_MAGIC = "PACKAGE_USAGE__VERSION_";
     private static final String USAGE_FILE_MAGIC_VERSION_1 = USAGE_FILE_MAGIC + "1";
@@ -52,7 +53,7 @@
     }
 
     @Override
-    protected void writeInternal(Map<String, AndroidPackage> packages) {
+    protected void writeInternal(Map<String, PackageSetting> pkgSettings) {
         AtomicFile file = getFile();
         FileOutputStream f = null;
         try {
@@ -66,13 +67,14 @@
             sb.append('\n');
             out.write(sb.toString().getBytes(StandardCharsets.US_ASCII));
 
-            for (AndroidPackage pkg : packages.values()) {
-                if (pkg.getLatestPackageUseTimeInMills() == 0L) {
+            for (PackageSetting pkgSetting : pkgSettings.values()) {
+                if (pkgSetting.getPkgState().getLatestPackageUseTimeInMills() == 0L) {
                     continue;
                 }
                 sb.setLength(0);
-                sb.append(pkg.getPackageName());
-                for (long usageTimeInMillis : pkg.getLastPackageUsageTimeInMills()) {
+                sb.append(pkgSetting.name);
+                for (long usageTimeInMillis : pkgSetting.getPkgState()
+                        .getLastPackageUsageTimeInMills()) {
                     sb.append(' ');
                     sb.append(usageTimeInMillis);
                 }
@@ -90,7 +92,7 @@
     }
 
     @Override
-    protected void readInternal(Map<String, AndroidPackage> packages) {
+    protected void readInternal(Map<String, PackageSetting> pkgSettings) {
         AtomicFile file = getFile();
         BufferedInputStream in = null;
         try {
@@ -101,9 +103,9 @@
             if (firstLine == null) {
                 // Empty file. Do nothing.
             } else if (USAGE_FILE_MAGIC_VERSION_1.equals(firstLine)) {
-                readVersion1LP(packages, in, sb);
+                readVersion1LP(pkgSettings, in, sb);
             } else {
-                readVersion0LP(packages, in, sb, firstLine);
+                readVersion0LP(pkgSettings, in, sb, firstLine);
             }
         } catch (FileNotFoundException expected) {
             mIsHistoricalPackageUsageAvailable = false;
@@ -114,7 +116,7 @@
         }
     }
 
-    private void readVersion0LP(Map<String, AndroidPackage> packages, InputStream in,
+    private void readVersion0LP(Map<String, PackageSetting> pkgSettings, InputStream in,
             StringBuffer sb, String firstLine)
             throws IOException {
         // Initial version of the file had no version number and stored one
@@ -128,8 +130,8 @@
             }
 
             String packageName = tokens[0];
-            AndroidPackage pkg = packages.get(packageName);
-            if (pkg == null) {
+            PackageSetting pkgSetting = pkgSettings.get(packageName);
+            if (pkgSetting == null) {
                 continue;
             }
 
@@ -137,12 +139,12 @@
             for (int reason = 0;
                     reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
                     reason++) {
-                pkg.mutate().setLastPackageUsageTimeInMills(reason, timestamp);
+                pkgSetting.getPkgState().setLastPackageUsageTimeInMills(reason, timestamp);
             }
         }
     }
 
-    private void readVersion1LP(Map<String, AndroidPackage> packages, InputStream in,
+    private void readVersion1LP(Map<String, PackageSetting> pkgSettings, InputStream in,
             StringBuffer sb) throws IOException {
         // Version 1 of the file started with the corresponding version
         // number and then stored a package name and eight timestamps per line.
@@ -154,15 +156,15 @@
             }
 
             String packageName = tokens[0];
-            AndroidPackage pkg = packages.get(packageName);
-            if (pkg == null) {
+            PackageSetting pkgSetting = pkgSettings.get(packageName);
+            if (pkgSetting == null) {
                 continue;
             }
 
             for (int reason = 0;
                     reason < PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT;
                     reason++) {
-                pkg.mutate().setLastPackageUsageTimeInMills(reason,
+                pkgSetting.getPkgState().setLastPackageUsageTimeInMills(reason,
                         parseAsLong(tokens[reason + 1]));
             }
         }
diff --git a/services/core/java/com/android/server/pm/ParallelPackageParser.java b/services/core/java/com/android/server/pm/ParallelPackageParser.java
index 448dad0..21334c0 100644
--- a/services/core/java/com/android/server/pm/ParallelPackageParser.java
+++ b/services/core/java/com/android/server/pm/ParallelPackageParser.java
@@ -19,12 +19,13 @@
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
 
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Process;
 import android.os.Trace;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ConcurrentUtils;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.io.File;
 import java.util.concurrent.ArrayBlockingQueue;
@@ -50,11 +51,11 @@
                 Process.THREAD_PRIORITY_FOREGROUND);
     }
 
-    private final PackageParser mPackageParser;
+    private final PackageParser2 mPackageParser;
 
     private final ExecutorService mExecutorService;
 
-    ParallelPackageParser(PackageParser packageParser, ExecutorService executorService) {
+    ParallelPackageParser(PackageParser2 packageParser, ExecutorService executorService) {
         mPackageParser = packageParser;
         mExecutorService = executorService;
     }
@@ -125,6 +126,6 @@
     @VisibleForTesting
     protected ParsedPackage parsePackage(File scanFile, int parseFlags)
             throws PackageParser.PackageParserException {
-        return mPackageParser.parseParsedPackage(scanFile, parseFlags, true);
+        return mPackageParser.parsePackage(scanFile, parseFlags, true);
     }
 }
diff --git a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
index ef29cb3..08a87d8 100644
--- a/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PersistentPreferredIntentResolver.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
+import android.content.IntentFilter;
+
 import com.android.server.IntentResolver;
 
 public class PersistentPreferredIntentResolver
@@ -26,6 +29,11 @@
     }
 
     @Override
+    protected IntentFilter getIntentFilter(@NonNull PersistentPreferredActivity input) {
+        return input;
+    }
+
+    @Override
     protected boolean isPackageForFilter(String packageName, PersistentPreferredActivity filter) {
         return packageName.equals(filter.mComponent.getPackageName());
     }
diff --git a/services/core/java/com/android/server/pm/PreferredIntentResolver.java b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
index bce24d7..a261e29 100644
--- a/services/core/java/com/android/server/pm/PreferredIntentResolver.java
+++ b/services/core/java/com/android/server/pm/PreferredIntentResolver.java
@@ -16,6 +16,9 @@
 
 package com.android.server.pm;
 
+import android.annotation.NonNull;
+import android.content.IntentFilter;
+
 import java.io.PrintWriter;
 
 import com.android.server.IntentResolver;
@@ -37,4 +40,9 @@
             PreferredActivity filter) {
         filter.mPref.dump(out, prefix, filter);
     }
+
+    @Override
+    protected IntentFilter getIntentFilter(@NonNull PreferredActivity input) {
+        return input;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/SELinuxMMAC.java b/services/core/java/com/android/server/pm/SELinuxMMAC.java
index 466f19c..67e1994 100644
--- a/services/core/java/com/android/server/pm/SELinuxMMAC.java
+++ b/services/core/java/com/android/server/pm/SELinuxMMAC.java
@@ -18,15 +18,14 @@
 
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
-import android.content.pm.PackageParser;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.Signature;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Environment;
 import android.util.Slog;
 import android.util.Xml;
 
 import com.android.server.compat.PlatformCompat;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import libcore.io.IoUtils;
 
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d451152..42b2eeb 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -49,10 +49,12 @@
 import android.content.pm.SuspendDialogInfo;
 import android.content.pm.UserInfo;
 import android.content.pm.VerifierDeviceIdentity;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
-import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedProcess;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Build;
@@ -76,6 +78,7 @@
 import android.util.AtomicFile;
 import android.util.Log;
 import android.util.LogPrinter;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
@@ -96,6 +99,9 @@
 import com.android.permission.persistence.RuntimePermissionsState;
 import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.pm.permission.BasePermission;
 import com.android.server.pm.permission.PermissionSettings;
 import com.android.server.pm.permission.PermissionsState;
@@ -226,6 +232,8 @@
     @Deprecated
     private static final String TAG_SUSPENDED_LAUNCHER_EXTRAS = "suspended-launcher-extras";
     private static final String TAG_SUSPEND_PARAMS = "suspend-params";
+    private static final String TAG_MIME_GROUP = "mime-group";
+    private static final String TAG_MIME_TYPE = "mime-type";
 
     public static final String ATTR_NAME = "name";
     public static final String ATTR_PACKAGE = "package";
@@ -266,6 +274,7 @@
     private static final String ATTR_VOLUME_UUID = "volumeUuid";
     private static final String ATTR_SDK_VERSION = "sdkVersion";
     private static final String ATTR_DATABASE_VERSION = "databaseVersion";
+    private static final String ATTR_VALUE = "value";
 
     private final Object mLock;
 
@@ -476,10 +485,9 @@
         }
         final PackageSetting dp = mDisabledSysPackages.get(name);
         // always make sure the system package code and resource paths dont change
-        if (dp == null && p.pkg != null && p.pkg.isSystem() && !p.pkg.isUpdatedSystemApp()) {
-            if(p.pkg != null) {
-                p.pkg.mutate().setUpdatedSystemApp(true);
-            }
+        if (dp == null && p.pkg != null && p.pkg.isSystem()
+                && !p.getPkgState().isUpdatedSystemApp()) {
+            p.getPkgState().setUpdatedSystemApp(true);
             final PackageSetting disabled;
             if (replaced) {
                 // a little trick...  when we install the new package, we don't
@@ -503,16 +511,12 @@
             Log.w(PackageManagerService.TAG, "Package " + name + " is not disabled");
             return null;
         }
-        // Reset flag in ApplicationInfo object
-        if(p.pkg != null) {
-            p.pkg.mutate().setUpdatedSystemApp(false);
-        }
+        p.getPkgState().setUpdatedSystemApp(false);
         PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
                 p.legacyNativeLibraryPathString, p.primaryCpuAbiString,
                 p.secondaryCpuAbiString, p.cpuAbiOverrideString,
                 p.appId, p.versionCode, p.pkgFlags, p.pkgPrivateFlags,
-                p.usesStaticLibraries,
-                p.usesStaticLibrariesVersions);
+                p.usesStaticLibraries, p.usesStaticLibrariesVersions, p.mimeGroups);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -529,7 +533,7 @@
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc, int
             pkgFlags, int pkgPrivateFlags, String[] usesStaticLibraries,
-            long[] usesStaticLibraryNames) {
+            long[] usesStaticLibraryNames, Map<String, ArraySet<String>> mimeGroups) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.appId == uid) {
@@ -542,7 +546,8 @@
         p = new PackageSetting(name, realName, codePath, resourcePath,
                 legacyNativeLibraryPathString, primaryCpuAbiString, secondaryCpuAbiString,
                 cpuAbiOverrideString, vc, pkgFlags, pkgPrivateFlags,
-                0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames);
+                0 /*userId*/, usesStaticLibraries, usesStaticLibraryNames,
+                mimeGroups);
         p.appId = uid;
         if (registerExistingAppIdLPw(uid, p, name)) {
             mPackages.put(name, p);
@@ -605,7 +610,8 @@
             String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
             UserHandle installUser, boolean allowInstall, boolean instantApp,
             boolean virtualPreload, UserManagerService userManager,
-            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions) {
+            String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
+            Set<String> mimeGroupNames) {
         final PackageSetting pkgSetting;
         if (originalPkg != null) {
             if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
@@ -631,7 +637,7 @@
                     legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                     null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
                     0 /*sharedUserId*/, usesStaticLibraries,
-                    usesStaticLibrariesVersions);
+                    usesStaticLibrariesVersions, createMimeGroups(mimeGroupNames));
             pkgSetting.setTimeStamp(codePath.lastModified());
             pkgSetting.sharedUser = sharedUser;
             // If this is not a system app, it starts out stopped.
@@ -704,6 +710,14 @@
         return pkgSetting;
     }
 
+    private static Map<String, ArraySet<String>> createMimeGroups(Set<String> mimeGroupNames) {
+        if (mimeGroupNames == null) {
+            return null;
+        }
+
+        return new KeySetToValueMap<>(mimeGroupNames, new ArraySet<>());
+    }
+
     /**
      * Updates the given package setting using the provided information.
      * <p>
@@ -715,7 +729,8 @@
             @Nullable String legacyNativeLibraryPath, @Nullable String primaryCpuAbi,
             @Nullable String secondaryCpuAbi, int pkgFlags, int pkgPrivateFlags,
             @NonNull UserManagerService userManager,
-            @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions)
+            @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions,
+            @Nullable Set<String> mimeGroupNames)
                     throws PackageManagerException {
         final String pkgName = pkgSetting.name;
         if (pkgSetting.sharedUser != sharedUser) {
@@ -801,6 +816,7 @@
             pkgSetting.usesStaticLibraries = null;
             pkgSetting.usesStaticLibrariesVersions = null;
         }
+        pkgSetting.updateMimeGroups(mimeGroupNames);
     }
 
     /**
@@ -2659,15 +2675,19 @@
 
             StringBuilder sb = new StringBuilder();
             for (final PackageSetting pkg : mPackages.values()) {
-                if (pkg.pkg == null || pkg.pkg.getDataDir() == null) {
+                // TODO(b/135203078): This doesn't handle multiple users
+                final String dataPath = pkg.pkg == null ? null :
+                        PackageInfoWithoutStateUtils.getDataDir(pkg.pkg,
+                                UserHandle.USER_SYSTEM).getAbsolutePath();
+
+                if (pkg.pkg == null || dataPath == null) {
                     if (!"android".equals(pkg.name)) {
                         Slog.w(TAG, "Skipping " + pkg + " due to missing metadata");
                     }
                     continue;
                 }
 
-                final String dataPath = pkg.pkg.getDataDir();
-                final boolean isDebug = (pkg.pkg.getFlags() & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
+                final boolean isDebug = pkg.pkg.isDebuggable();
                 final int[] gids = pkg.getPermissionsState().computeGids(userIds);
 
                 // Avoid any application that has a space in its path.
@@ -2698,7 +2718,7 @@
                 sb.append(isDebug ? " 1 " : " 0 ");
                 sb.append(dataPath);
                 sb.append(" ");
-                sb.append(pkg.pkg.getSeInfo());
+                sb.append(AndroidPackageUtils.getSeInfo(pkg.pkg, pkg));
                 sb.append(" ");
                 if (gids != null && gids.length > 0) {
                     sb.append(gids[0]);
@@ -2855,6 +2875,7 @@
         writeUpgradeKeySetsLPr(serializer, pkg.keySetData);
         writeKeySetAliasesLPr(serializer, pkg.keySetData);
         writeDomainVerificationsLPr(serializer, pkg.verificationInfo);
+        writeMimeGroupLPr(serializer, pkg.mimeGroups);
 
         serializer.endTag(null, "package");
     }
@@ -3139,14 +3160,14 @@
         final PackageManagerInternal pmInternal =
                 LocalServices.getService(PackageManagerInternal.class);
         for (PackageSetting ps : mPackages.values()) {
-            if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
-                    && ps.pkg.getPreferredActivityFilters() != null) {
-                List<ComponentParseUtils.ParsedActivityIntentInfo> intents
+            if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
+                    && !ps.pkg.getPreferredActivityFilters().isEmpty()) {
+                List<Pair<String, ParsedIntentInfo>> intents
                         = ps.pkg.getPreferredActivityFilters();
                 for (int i=0; i<intents.size(); i++) {
-                    ComponentParseUtils.ParsedActivityIntentInfo aii = intents.get(i);
-                    applyDefaultPreferredActivityLPw(pmInternal, aii, new ComponentName(
-                                    ps.name, aii.getClassName()), userId);
+                    Pair<String, ParsedIntentInfo> pair = intents.get(i);
+                    applyDefaultPreferredActivityLPw(pmInternal, pair.second, new ComponentName(
+                            ps.name, pair.first), userId);
                 }
             }
         }
@@ -3506,7 +3527,7 @@
         PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
                 new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiStr,
                 secondaryCpuAbiStr, cpuAbiOverrideStr, versionCode, pkgFlags, pkgPrivateFlags,
-                0 /*sharedUserId*/, null, null);
+                0 /*sharedUserId*/, null, null, null);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -3745,8 +3766,8 @@
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         new File(resourcePathStr), legacyNativeLibraryPathStr, primaryCpuAbiString,
                         secondaryCpuAbiString, cpuAbiOverrideString, userId, versionCode, pkgFlags,
-                        pkgPrivateFlags,
-                        null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
+                        pkgPrivateFlags, null /*usesStaticLibraries*/,
+                        null /*usesStaticLibraryVersions*/, null /*mimeGroups*/);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
                             + userId + " pkg=" + packageSetting);
@@ -3764,9 +3785,10 @@
                     packageSetting = new PackageSetting(name.intern(), realName, new File(
                             codePathStr), new File(resourcePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                            versionCode, pkgFlags, pkgPrivateFlags,
-                            sharedUserId,
-                            null /*usesStaticLibraries*/, null /*usesStaticLibraryVersions*/);
+                            versionCode, pkgFlags, pkgPrivateFlags, sharedUserId,
+                            null /*usesStaticLibraries*/,
+                            null /*usesStaticLibraryVersions*/,
+                            null /*mimeGroups*/);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
                     packageSetting.lastUpdateTime = lastUpdateTime;
@@ -3880,6 +3902,8 @@
                             packageSetting.installSource.setInitiatingPackageSignatures(signatures);
                 } else if (tagName.equals(TAG_DOMAIN_VERIFICATION)) {
                     readDomainVerificationLPw(parser, packageSetting);
+                } else if (tagName.equals(TAG_MIME_GROUP)) {
+                    packageSetting.mimeGroups = readMimeGroupLPw(parser, packageSetting.mimeGroups);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Unknown element under <package>: " + parser.getName());
@@ -3903,6 +3927,67 @@
         }
     }
 
+    private Map<String, ArraySet<String>> readMimeGroupLPw(XmlPullParser parser,
+            Map<String, ArraySet<String>> mimeGroups) throws XmlPullParserException, IOException {
+        String groupName = parser.getAttributeValue(null, ATTR_NAME);
+        if (groupName == null) {
+            XmlUtils.skipCurrentTag(parser);
+            return mimeGroups;
+        }
+
+        if (mimeGroups == null) {
+            mimeGroups = new ArrayMap<>();
+        }
+
+        ArraySet<String> mimeTypes = mimeGroups.get(groupName);
+        if (mimeTypes == null) {
+            mimeTypes = new ArraySet<>();
+            mimeGroups.put(groupName, mimeTypes);
+        }
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_MIME_TYPE)) {
+                String typeName = parser.getAttributeValue(null, ATTR_VALUE);
+                if (typeName != null) {
+                    mimeTypes.add(typeName);
+                }
+            } else {
+                PackageManagerService.reportSettingsProblem(Log.WARN,
+                        "Unknown element under <mime-group>: " + parser.getName());
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+
+        return mimeGroups;
+    }
+
+    private void writeMimeGroupLPr(XmlSerializer serializer,
+            Map<String, ArraySet<String>> mimeGroups) throws IOException {
+        if (mimeGroups == null) {
+            return;
+        }
+
+        for (String mimeGroup: mimeGroups.keySet()) {
+            serializer.startTag(null, TAG_MIME_GROUP);
+            serializer.attribute(null, ATTR_NAME, mimeGroup);
+
+            for (String mimeType: mimeGroups.get(mimeGroup)) {
+                serializer.startTag(null, TAG_MIME_TYPE);
+                serializer.attribute(null, ATTR_VALUE, mimeType);
+                serializer.endTag(null, TAG_MIME_TYPE);
+            }
+
+            serializer.endTag(null, TAG_MIME_GROUP);
+        }
+    }
+
     private void readDisabledComponentsLPw(PackageSettingBase packageSetting, XmlPullParser parser,
             int userId) throws IOException, XmlPullParserException {
         int outerDepth = parser.getDepth();
@@ -4050,7 +4135,7 @@
                 final boolean shouldInstall = ps.isSystem() &&
                         (skipPackageWhitelist || installablePackages.contains(ps.name)) &&
                         !ArrayUtils.contains(disallowedPackages, ps.name) &&
-                        !ps.pkg.isHiddenUntilInstalled();
+                        !ps.getPkgState().isHiddenUntilInstalled();
                 // Only system apps are initially installed.
                 ps.setInstalled(shouldInstall, userHandle);
                 if (!shouldInstall) {
@@ -4061,7 +4146,7 @@
                 volumeUuids[i] = ps.volumeUuid;
                 names[i] = ps.name;
                 appIds[i] = ps.appId;
-                seinfos[i] = ps.pkg.getSeInfo();
+                seinfos[i] = AndroidPackageUtils.getSeInfo(ps.pkg, ps);
                 targetSdkVersions[i] = ps.pkg.getTargetSdkVersion();
             }
         }
@@ -4202,7 +4287,7 @@
         return userState.isMatch(componentInfo, flags);
     }
 
-    boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedComponent component, int flags,
+    boolean isEnabledAndMatchLPr(AndroidPackage pkg, ParsedMainComponent component, int flags,
             int userId) {
         final PackageSetting ps = mPackages.get(component.getPackageName());
         if (ps == null) return false;
@@ -4517,58 +4602,60 @@
             pw.print(prefix); pw.print("  apkSigningVersion="); pw.println(apkSigningVersion);
             // TODO(b/135203078): Is there anything to print here with AppInfo removed?
             pw.print(prefix); pw.print("  applicationInfo=");
-            pw.println(pkg.toAppInfoWithoutState().toString());
-            pw.print(prefix); pw.print("  flags="); printFlags(pw, pkg.getFlags(),
-                    FLAG_DUMP_SPEC); pw.println();
-            if (pkg.getPrivateFlags() != 0) {
+            pw.println(pkg.toAppInfoToString());
+            pw.print(prefix); pw.print("  flags=");
+            printFlags(pw, PackageInfoUtils.appInfoFlags(pkg, ps), FLAG_DUMP_SPEC); pw.println();
+            int privateFlags = PackageInfoUtils.appInfoPrivateFlags(pkg, ps);
+            if (privateFlags != 0) {
                 pw.print(prefix); pw.print("  privateFlags="); printFlags(pw,
-                        pkg.getPrivateFlags(), PRIVATE_FLAG_DUMP_SPEC); pw.println();
+                        privateFlags, PRIVATE_FLAG_DUMP_SPEC); pw.println();
             }
             pw.print(prefix); pw.print("  forceQueryable="); pw.print(ps.pkg.isForceQueryable());
             if (ps.forceQueryableOverride) {
                 pw.print(" (override=true)");
             }
             pw.println();
-            if (ps.pkg.getQueriesPackages() != null) {
+            if (ps.pkg.getQueriesPackages().isEmpty()) {
                 pw.append(prefix).append("  queriesPackages=").println(ps.pkg.getQueriesPackages());
             }
-            if (ps.pkg.getQueriesIntents() != null) {
+            if (!ps.pkg.getQueriesIntents().isEmpty()) {
                 pw.append(prefix).append("  queriesIntents=").println(ps.pkg.getQueriesIntents());
             }
-            pw.print(prefix); pw.print("  dataDir="); pw.println(ps.pkg.getDataDir());
+            File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId());
+            pw.print(prefix); pw.print("  dataDir="); pw.println(dataDir.getAbsolutePath());
             pw.print(prefix); pw.print("  supportsScreens=[");
             boolean first = true;
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_SMALL_SCREENS) != 0) {
+            if (pkg.isSupportsSmallScreens()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
                 pw.print("small");
             }
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_NORMAL_SCREENS) != 0) {
+            if (pkg.isSupportsNormalScreens()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
                 pw.print("medium");
             }
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_LARGE_SCREENS) != 0) {
+            if (pkg.isSupportsLargeScreens()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
                 pw.print("large");
             }
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_XLARGE_SCREENS) != 0) {
+            if (pkg.isSupportsExtraLargeScreens()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
                 pw.print("xlarge");
             }
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_RESIZEABLE_FOR_SCREENS) != 0) {
+            if (pkg.isResizeable()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
                 pw.print("resizeable");
             }
-            if ((pkg.getFlags() & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+            if (pkg.isAnyDensity()) {
                 if (!first)
                     pw.print(", ");
                 first = false;
@@ -4590,18 +4677,17 @@
                 pw.print(" version:"); pw.println(pkg.getStaticSharedLibVersion());
             }
 
-            final List<String> usesLibraries = pkg.getUsesLibraries();
-            if (usesLibraries != null && usesLibraries.size() > 0) {
+            List<String> usesLibraries = pkg.getUsesLibraries();
+            if (usesLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesLibraries:");
                 for (int i=0; i< usesLibraries.size(); i++) {
                     pw.print(prefix); pw.print("    "); pw.println(usesLibraries.get(i));
                 }
             }
 
-            final List<String> usesStaticLibraries = pkg.getUsesStaticLibraries();
-            final long[] usesStaticLibrariesVersions = pkg.getUsesStaticLibrariesVersions();
-            if (usesStaticLibraries != null
-                    && usesStaticLibraries.size() > 0) {
+            List<String> usesStaticLibraries = pkg.getUsesStaticLibraries();
+            long[] usesStaticLibrariesVersions = pkg.getUsesStaticLibrariesVersions();
+            if (usesStaticLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesStaticLibraries:");
                 for (int i=0; i< usesStaticLibraries.size(); i++) {
                     pw.print(prefix); pw.print("    ");
@@ -4610,9 +4696,8 @@
                 }
             }
 
-            final List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries();
-            if (usesOptionalLibraries != null
-                    && usesOptionalLibraries.size() > 0) {
+            List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries();
+            if (usesOptionalLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesOptionalLibraries:");
                 for (int i=0; i< usesOptionalLibraries.size(); i++) {
                     pw.print(prefix); pw.print("    ");
@@ -4620,24 +4705,22 @@
                 }
             }
 
-            final String[] usesLibraryFiles = pkg.getUsesLibraryFiles();
-            if (usesLibraryFiles != null
-                    && usesLibraryFiles.length > 0) {
+            List<String> usesLibraryFiles = ps.getPkgState().getUsesLibraryFiles();
+            if (usesLibraryFiles.size() > 0) {
                 pw.print(prefix); pw.println("  usesLibraryFiles:");
-                for (int i=0; i< usesLibraryFiles.length; i++) {
-                    pw.print(prefix); pw.print("    "); pw.println(usesLibraryFiles[i]);
+                for (int i=0; i< usesLibraryFiles.size(); i++) {
+                    pw.print(prefix); pw.print("    "); pw.println(usesLibraryFiles.get(i));
                 }
             }
-            final ArrayMap<String, ComponentParseUtils.ParsedProcess> procs = pkg.getProcesses();
-            if (procs != null) {
+            final Map<String, ParsedProcess> procs = pkg.getProcesses();
+            if (!procs.isEmpty()) {
                 pw.print(prefix); pw.println("  processes:");
-                for (int i = 0; i < procs.size(); i++) {
-                    final ComponentParseUtils.ParsedProcess proc = procs.valueAt(i);
-                    pw.print(prefix); pw.print("    "); pw.println(proc.name);
-                    if (proc.deniedPermissions != null) {
-                        for (int j = 0; j < proc.deniedPermissions.size(); j++) {
+                for (ParsedProcess proc : procs.values()) {
+                    pw.print(prefix); pw.print("    "); pw.println(proc.getName());
+                    if (proc.getDeniedPermissions() != null) {
+                        for (String deniedPermission : proc.getDeniedPermissions()) {
                             pw.print(prefix); pw.print("      deny: ");
-                            pw.println(proc.deniedPermissions.valueAt(j));
+                            pw.println(deniedPermission);
                         }
                     }
                 }
@@ -4672,7 +4755,7 @@
             pw.print(prefix); pw.print("  overlayCategory="); pw.println(pkg.getOverlayCategory());
         }
 
-        if (pkg != null && pkg.getPermissions() != null && pkg.getPermissions().size() > 0) {
+        if (pkg != null && !pkg.getPermissions().isEmpty()) {
             final List<ParsedPermission> perms = pkg.getPermissions();
             pw.print(prefix); pw.println("  declared permissions:");
             for (int i=0; i<perms.size(); i++) {
@@ -4683,14 +4766,14 @@
                 }
                 pw.print(prefix); pw.print("    "); pw.print(perm.getName());
                 pw.print(": prot=");
-                pw.print(PermissionInfo.protectionToString(perm.protectionLevel));
-                if ((perm.flags&PermissionInfo.FLAG_COSTS_MONEY) != 0) {
+                pw.print(PermissionInfo.protectionToString(perm.getProtectionLevel()));
+                if ((perm.getFlags() &PermissionInfo.FLAG_COSTS_MONEY) != 0) {
                     pw.print(", COSTS_MONEY");
                 }
-                if ((perm.flags&PermissionInfo.FLAG_REMOVED) != 0) {
+                if ((perm.getFlags() &PermissionInfo.FLAG_REMOVED) != 0) {
                     pw.print(", HIDDEN");
                 }
-                if ((perm.flags&PermissionInfo.FLAG_INSTALLED) != 0) {
+                if ((perm.getFlags() &PermissionInfo.FLAG_INSTALLED) != 0) {
                     pw.print(", INSTALLED");
                 }
                 pw.println();
@@ -5116,6 +5199,77 @@
         }
     }
 
+    private static class KeySetToValueMap<K, V> implements Map<K, V> {
+        @NonNull
+        private final Set<K> mKeySet;
+        private final V mValue;
+
+        KeySetToValueMap(@NonNull Set<K> keySet, V value) {
+            mKeySet = keySet;
+            mValue = value;
+        }
+
+        @Override
+        public int size() {
+            return mKeySet.size();
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return mKeySet.isEmpty();
+        }
+
+        @Override
+        public boolean containsKey(Object key) {
+            return mKeySet.contains(key);
+        }
+
+        @Override
+        public boolean containsValue(Object value) {
+            return mValue == value;
+        }
+
+        @Override
+        public V get(Object key) {
+            return mValue;
+        }
+
+        @Override
+        public V put(K key, V value) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public V remove(Object key) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void putAll(Map<? extends K, ? extends V> m) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<K> keySet() {
+            return mKeySet;
+        }
+
+        @Override
+        public Collection<V> values() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<Entry<K, V>> entrySet() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
     private final class RuntimePermissionPersistence {
         private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 200;
         private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000;
@@ -5253,7 +5407,7 @@
                         packagePermissions, sharedUserPermissions);
             }
 
-            mPersistence.write(runtimePermissions, UserHandle.of(userId));
+            mPersistence.writeAsUser(runtimePermissions, UserHandle.of(userId));
         }
 
         @NonNull
@@ -5307,12 +5461,13 @@
         }
 
         public void deleteUserRuntimePermissionsFile(int userId) {
-            mPersistence.delete(UserHandle.of(userId));
+            mPersistence.deleteAsUser(UserHandle.of(userId));
         }
 
         @GuardedBy("Settings.this.mLock")
         public void readStateForUserSyncLPr(int userId) {
-            RuntimePermissionsState runtimePermissions = mPersistence.read(UserHandle.of(userId));
+            RuntimePermissionsState runtimePermissions = mPersistence.readAsUser(UserHandle.of(
+                    userId));
             if (runtimePermissions == null) {
                 readLegacyStateForUserSyncLPr(userId);
                 writePermissionsForUserAsyncLPr(userId);
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index bbd319c..6103f558 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -18,19 +18,20 @@
 
 import android.annotation.Nullable;
 import android.content.pm.ApplicationInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedProcess;
 import android.service.pm.PackageServiceDumpProto;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import libcore.util.EmptyArray;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Settings data for a particular shared user ID we know about.
@@ -53,7 +54,7 @@
     final PackageSignatures signatures = new PackageSignatures();
     Boolean signaturesChanged;
 
-    ArrayMap<String, ComponentParseUtils.ParsedProcess> processes;
+    ArrayMap<String, ParsedProcess> processes;
 
     SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
         super(_pkgFlags, _pkgPrivateFlags);
@@ -76,18 +77,18 @@
         proto.end(token);
     }
 
-    void addProcesses(ArrayMap<String, ComponentParseUtils.ParsedProcess> newProcs) {
+    void addProcesses(Map<String, ParsedProcess> newProcs) {
         if (newProcs != null) {
             final int numProcs = newProcs.size();
             if (processes == null) {
                 processes = new ArrayMap<>(numProcs);
             }
-            for (int i = 0; i < numProcs; i++) {
-                ComponentParseUtils.ParsedProcess newProc = newProcs.valueAt(i);
-                ComponentParseUtils.ParsedProcess proc = processes.get(newProc.name);
+            for (String key : newProcs.keySet()) {
+                ParsedProcess newProc = newProcs.get(key);
+                ParsedProcess proc = processes.get(newProc.getName());
                 if (proc == null) {
-                    proc = new ComponentParseUtils.ParsedProcess(newProc);
-                    processes.put(newProc.name, proc);
+                    proc = new ParsedProcess(newProc);
+                    processes.put(newProc.getName(), proc);
                 } else {
                     proc.addStateFrom(newProc);
                 }
@@ -159,19 +160,24 @@
      * restrictive selinux domain.
      */
     public void fixSeInfoLocked() {
-        final List<AndroidPackage> pkgList = getPackages();
-        if (pkgList == null || pkgList.size() == 0) {
+        if (packages == null || packages.size() == 0) {
             return;
         }
-
-        for (AndroidPackage pkg : pkgList) {
-            if (pkg.getTargetSdkVersion() < seInfoTargetSdkVersion) {
-                seInfoTargetSdkVersion = pkg.getTargetSdkVersion();
+        for (PackageSetting ps : packages) {
+            if ((ps == null) || (ps.pkg == null)) {
+                continue;
+            }
+            if (ps.pkg.getTargetSdkVersion() < seInfoTargetSdkVersion) {
+                seInfoTargetSdkVersion = ps.pkg.getTargetSdkVersion();
             }
         }
-        for (AndroidPackage pkg : pkgList) {
-            final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
-            pkg.mutate().setSeInfo(SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+
+        for (PackageSetting ps : packages) {
+            if ((ps == null) || (ps.pkg == null)) {
+                continue;
+            }
+            final boolean isPrivileged = isPrivileged() | ps.pkg.isPrivileged();
+            ps.getPkgState().setOverrideSeInfo(SELinuxMMAC.getSeInfo(ps.pkg, isPrivileged,
                     seInfoTargetSdkVersion));
         }
     }
@@ -221,9 +227,9 @@
             final int numProcs = sharedUser.processes.size();
             this.processes = new ArrayMap<>(numProcs);
             for (int i = 0; i < numProcs; i++) {
-                ComponentParseUtils.ParsedProcess proc =
-                        new ComponentParseUtils.ParsedProcess(sharedUser.processes.valueAt(i));
-                this.processes.put(proc.name, proc);
+                ParsedProcess proc =
+                        new ParsedProcess(sharedUser.processes.valueAt(i));
+                this.processes.put(proc.getName(), proc);
             }
         } else {
             this.processes = null;
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index c37ceb3..c8df5c7 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -36,6 +36,7 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.ShortcutService.DumpFilter;
@@ -310,10 +311,67 @@
     }
 
     /**
-     * Remove all shortcuts that aren't pinned, cached nor dynamic.
+     * Push a shortcut. If the max number of dynamic shortcuts is already reached, remove the
+     * shortcut with the lowest rank before adding the new shortcut.
      */
-    private void removeOrphans() {
+    public boolean pushDynamicShortcut(@NonNull ShortcutInfo newShortcut) {
+        Preconditions.checkArgument(newShortcut.isEnabled(),
+                "pushDynamicShortcuts() cannot publish disabled shortcuts");
+
+        newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+
+        final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
+        boolean wasPinned = false;
+
+        if (oldShortcut == null) {
+            final ShortcutService service = mShortcutUser.mService;
+            final int maxShortcuts = service.getMaxActivityShortcuts();
+
+            final ArrayMap<ComponentName, ArrayList<ShortcutInfo>> all =
+                    sortShortcutsToActivities();
+            final ArrayList<ShortcutInfo> activityShortcuts = all.get(newShortcut.getActivity());
+
+            if (activityShortcuts != null && activityShortcuts.size() == maxShortcuts) {
+                // Max has reached. Delete the shortcut with lowest rank.
+
+                // Sort by isManifestShortcut() and getRank().
+                Collections.sort(activityShortcuts, mShortcutTypeAndRankComparator);
+
+                final ShortcutInfo shortcut = activityShortcuts.get(maxShortcuts - 1);
+                if (shortcut.isManifestShortcut()) {
+                    // All shortcuts are manifest shortcuts and cannot be removed.
+                    Slog.e(TAG, "Failed to remove manifest shortcut while pushing dynamic shortcut "
+                            + newShortcut.getId());
+                    return false;
+                }
+
+                deleteDynamicWithId(shortcut.getId(), /*ignoreInvisible=*/ true);
+            }
+        } else {
+            // It's an update case.
+            // Make sure the target is updatable. (i.e. should be mutable.)
+            oldShortcut.ensureUpdatableWith(newShortcut, /*isUpdating=*/ false);
+
+            wasPinned = oldShortcut.isPinned();
+        }
+
+        // If it was originally pinned, the new one should be pinned too.
+        if (wasPinned) {
+            newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+        }
+
+        forceReplaceShortcutInner(newShortcut);
+        return true;
+    }
+
+    /**
+     * Remove all shortcuts that aren't pinned, cached nor dynamic.
+     *
+     * @return List of removed shortcuts.
+     */
+    private List<ShortcutInfo> removeOrphans() {
         ArrayList<String> removeList = null; // Lazily initialize.
+        List<ShortcutInfo> removedShortcuts = null;
 
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
@@ -322,20 +380,26 @@
 
             if (removeList == null) {
                 removeList = new ArrayList<>();
+                removedShortcuts = new ArrayList<>();
             }
             removeList.add(si.getId());
+            removedShortcuts.add(si);
         }
         if (removeList != null) {
             for (int i = removeList.size() - 1; i >= 0; i--) {
                 forceDeleteShortcutInner(removeList.get(i));
             }
         }
+
+        return removedShortcuts;
     }
 
     /**
      * Remove all dynamic shortcuts.
+     *
+     * @return List of shortcuts that actually got removed.
      */
-    public void deleteAllDynamicShortcuts(boolean ignoreInvisible) {
+    public List<ShortcutInfo> deleteAllDynamicShortcuts(boolean ignoreInvisible) {
         final long now = mShortcutUser.mService.injectCurrentTimeMillis();
 
         boolean changed = false;
@@ -350,8 +414,9 @@
             }
         }
         if (changed) {
-            removeOrphans();
+            return removeOrphans();
         }
+        return null;
     }
 
     /**
@@ -974,7 +1039,8 @@
         s.verifyStates();
 
         // This will send a notification to the launcher, and also save .
-        s.packageShortcutsChanged(getPackageName(), getPackageUserId());
+        // TODO: List changed and removed manifest shortcuts and pass to packageShortcutsChanged()
+        s.packageShortcutsChanged(getPackageName(), getPackageUserId(), null, null);
         return true; // true means changed.
     }
 
@@ -1245,15 +1311,14 @@
      */
     public void resolveResourceStrings() {
         final ShortcutService s = mShortcutUser.mService;
-        boolean changed = false;
+
+        List<ShortcutInfo> changedShortcuts = null;
 
         Resources publisherRes = null;
         for (int i = mShortcuts.size() - 1; i >= 0; i--) {
             final ShortcutInfo si = mShortcuts.valueAt(i);
 
             if (si.hasStringResources()) {
-                changed = true;
-
                 if (publisherRes == null) {
                     publisherRes = getPackageResources();
                     if (publisherRes == null) {
@@ -1263,10 +1328,15 @@
 
                 si.resolveResourceStrings(publisherRes);
                 si.setTimestamp(s.injectCurrentTimeMillis());
+
+                if (changedShortcuts == null) {
+                    changedShortcuts = new ArrayList<>(1);
+                }
+                changedShortcuts.add(si);
             }
         }
-        if (changed) {
-            s.packageShortcutsChanged(getPackageName(), getPackageUserId());
+        if (!CollectionUtils.isEmpty(changedShortcuts)) {
+            s.packageShortcutsChanged(getPackageName(), getPackageUserId(), changedShortcuts, null);
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
index 3e44de9..6fd997d 100644
--- a/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
+++ b/services/core/java/com/android/server/pm/ShortcutRequestPinProcessor.java
@@ -26,7 +26,6 @@
 import android.content.pm.LauncherApps.PinItemRequest;
 import android.content.pm.ShortcutInfo;
 import android.os.Bundle;
-import android.os.RemoteException;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Pair;
@@ -36,6 +35,9 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.Preconditions;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * Handles {@link android.content.pm.ShortcutManager#requestPinShortcut} related tasks.
  */
@@ -452,6 +454,8 @@
         final String launcherPackage = request.launcherPackage;
         final String shortcutId = original.getId();
 
+        List<ShortcutInfo> changedShortcuts = null;
+
         synchronized (mLock) {
             if (!(mService.isUserUnlockedL(appUserId)
                     && mService.isUserUnlockedL(request.launcherUserId))) {
@@ -506,8 +510,13 @@
                 Slog.d(TAG, "Pinning " + shortcutId);
             }
 
+
             launcher.addPinnedShortcut(appPackageName, appUserId, shortcutId,
                     /*forPinRequest=*/ true);
+            if (changedShortcuts == null) {
+                changedShortcuts = new ArrayList<>(1);
+            }
+            changedShortcuts.add(original);
 
             if (current == null) {
                 if (DEBUG) {
@@ -520,7 +529,7 @@
         }
 
         mService.verifyStates();
-        mService.packageShortcutsChanged(appPackageName, appUserId);
+        mService.packageShortcutsChanged(appPackageName, appUserId, changedShortcuts, null);
 
         return true;
     }
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index 377fd16..66f3574 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -98,6 +98,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.FastXmlSerializer;
 import com.android.internal.util.Preconditions;
@@ -133,6 +134,7 @@
 import java.net.URISyntaxException;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
@@ -276,6 +278,10 @@
     private final ArrayList<ShortcutChangeListener> mListeners = new ArrayList<>(1);
 
     @GuardedBy("mLock")
+    private final ArrayList<LauncherApps.ShortcutChangeCallback> mShortcutChangeCallbacks =
+            new ArrayList<>(1);
+
+    @GuardedBy("mLock")
     private long mRawLastResetTime;
 
     /**
@@ -1638,8 +1644,12 @@
      * - Sends a notification to LauncherApps
      * - Write to file
      */
-    void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId) {
+    void packageShortcutsChanged(@NonNull String packageName, @UserIdInt int userId,
+            @Nullable List<ShortcutInfo> addedOrUpdatedShortcuts,
+            @Nullable List<ShortcutInfo> removedShortcuts) {
         notifyListeners(packageName, userId);
+        notifyShortcutChangeCallbacks(packageName, userId, addedOrUpdatedShortcuts,
+                removedShortcuts);
         scheduleSaveUser(userId);
     }
 
@@ -1667,6 +1677,34 @@
         });
     }
 
+    private void notifyShortcutChangeCallbacks(@NonNull String packageName, @UserIdInt int userId,
+            @Nullable List<ShortcutInfo> addedOrUpdatedShortcuts,
+            @Nullable List<ShortcutInfo> removedShortcuts) {
+        final UserHandle user = UserHandle.of(userId);
+        injectPostToHandler(() -> {
+            try {
+                final ArrayList<LauncherApps.ShortcutChangeCallback> copy;
+                synchronized (mLock) {
+                    if (!isUserUnlockedL(userId)) {
+                        return;
+                    }
+
+                    copy = new ArrayList<>(mShortcutChangeCallbacks);
+                }
+                for (int i = copy.size() - 1; i >= 0; i--) {
+                    if (!CollectionUtils.isEmpty(addedOrUpdatedShortcuts)) {
+                        copy.get(i).onShortcutsAddedOrUpdated(packageName, addedOrUpdatedShortcuts,
+                                user);
+                    }
+                    if (!CollectionUtils.isEmpty(removedShortcuts)) {
+                        copy.get(i).onShortcutsRemoved(packageName, removedShortcuts, user);
+                    }
+                }
+            } catch (Exception ignore) {
+            }
+        });
+    }
+
     /**
      * Clean up / validate an incoming shortcut.
      * - Make sure all mandatory fields are set.
@@ -1761,6 +1799,8 @@
         final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                 injectBinderCallingPid(), injectBinderCallingUid());
 
+        List<ShortcutInfo> removedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -1786,7 +1826,7 @@
             }
 
             // First, remove all un-pinned; dynamic shortcuts
-            ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
+            removedShortcuts = ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
 
             // Then, add/update all.  We need to make sure to take over "pinned" flag.
             for (int i = 0; i < size; i++) {
@@ -1797,7 +1837,7 @@
             // Lastly, adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        packageShortcutsChanged(packageName, userId, newShortcuts, removedShortcuts);
 
         verifyStates();
 
@@ -1816,6 +1856,8 @@
         final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                 injectBinderCallingPid(), injectBinderCallingUid());
 
+        List<ShortcutInfo> changedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -1878,12 +1920,17 @@
                 if (replacingIcon || source.hasStringResources()) {
                     fixUpShortcutResourceNamesAndValues(target);
                 }
+
+                if (changedShortcuts == null) {
+                    changedShortcuts = new ArrayList<>(1);
+                }
+                changedShortcuts.add(target);
             }
 
             // Lastly, adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        packageShortcutsChanged(packageName, userId, changedShortcuts, null);
 
         verifyStates();
 
@@ -1902,6 +1949,8 @@
         final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
                 injectBinderCallingPid(), injectBinderCallingUid());
 
+        List<ShortcutInfo> changedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -1933,12 +1982,17 @@
 
                 // Add it.
                 ps.addOrReplaceDynamicShortcut(newShortcut);
+
+                if (changedShortcuts == null) {
+                    changedShortcuts = new ArrayList<>(1);
+                }
+                changedShortcuts.add(newShortcut);
             }
 
             // Lastly, adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        packageShortcutsChanged(packageName, userId, changedShortcuts, null);
 
         verifyStates();
 
@@ -1946,6 +2000,50 @@
     }
 
     @Override
+    public void pushDynamicShortcut(String packageName, ShortcutInfo shortcut,
+            @UserIdInt int userId) {
+        verifyCaller(packageName, userId);
+        verifyShortcutInfoPackage(packageName, shortcut);
+
+        final boolean unlimited = injectHasUnlimitedShortcutsApiCallsPermission(
+                injectBinderCallingPid(), injectBinderCallingUid());
+
+        synchronized (mLock) {
+            throwIfUserLockedL(userId);
+
+            final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
+
+            ps.ensureNotImmutable(shortcut.getId(), /*ignoreInvisible=*/ true);
+            fillInDefaultActivity(Arrays.asList(shortcut));
+
+            if (!shortcut.hasRank()) {
+                shortcut.setRank(0);
+            }
+            // Initialize the implicit ranks for ShortcutPackage.adjustRanks().
+            ps.clearAllImplicitRanks();
+            shortcut.setImplicitRank(0);
+
+            // Validate the shortcut.
+            fixUpIncomingShortcutInfo(shortcut, /* forUpdate= */ false);
+
+            // When ranks are changing, we need to insert between ranks, so set the
+            // "rank changed" flag.
+            shortcut.setRankChanged();
+
+            // Push it.
+            if (!ps.pushDynamicShortcut(shortcut)) {
+                return;
+            }
+
+            // Lastly, adjust the ranks.
+            ps.adjustRanks();
+        }
+        packageShortcutsChanged(packageName, userId, Collections.singletonList(shortcut), null);
+
+        verifyStates();
+    }
+
+    @Override
     public boolean requestPinShortcut(String packageName, ShortcutInfo shortcut,
             IntentSender resultIntent, int userId) {
         Objects.requireNonNull(shortcut);
@@ -2007,7 +2105,8 @@
 
                     ps.updateInvisibleShortcutForPinRequestWith(shortcut);
 
-                    packageShortcutsChanged(shortcutPackage, userId);
+                    packageShortcutsChanged(shortcutPackage, userId,
+                            Collections.singletonList(shortcut), null);
                 }
             }
 
@@ -2052,7 +2151,8 @@
             // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        // TODO: Disabling dynamic shortcuts will removed them if not pinned. Cover all cases.
+        packageShortcutsChanged(packageName, userId, null, null);
 
         verifyStates();
     }
@@ -2062,6 +2162,8 @@
         verifyCaller(packageName, userId);
         Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
 
+        List<ShortcutInfo> changedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -2076,9 +2178,18 @@
                     continue;
                 }
                 ps.enableWithId(id);
+
+                final ShortcutInfo si = ps.findShortcutById(id);
+                if (si != null) {
+                    if (changedShortcuts == null) {
+                        changedShortcuts = new ArrayList<>(1);
+                    }
+                    changedShortcuts.add(si);
+                }
             }
         }
-        packageShortcutsChanged(packageName, userId);
+
+        packageShortcutsChanged(packageName, userId, changedShortcuts, null);
 
         verifyStates();
     }
@@ -2089,6 +2200,9 @@
         verifyCaller(packageName, userId);
         Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
 
+        List<ShortcutInfo> changedShortcuts = null;
+        List<ShortcutInfo> removedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -2102,13 +2216,25 @@
                 if (!ps.isShortcutExistsAndVisibleToPublisher(id)) {
                     continue;
                 }
-                ps.deleteDynamicWithId(id, /*ignoreInvisible=*/ true);
+                final ShortcutInfo si = ps.findShortcutById(id);
+                final boolean removed = ps.deleteDynamicWithId(id, /*ignoreInvisible=*/ true);
+                if (removed) {
+                    if (removedShortcuts == null) {
+                        removedShortcuts = new ArrayList<>(1);
+                    }
+                    removedShortcuts.add(si);
+                } else {
+                    if (changedShortcuts == null) {
+                        changedShortcuts = new ArrayList<>(1);
+                    }
+                    changedShortcuts.add(si);
+                }
             }
 
             // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        packageShortcutsChanged(packageName, userId, changedShortcuts, removedShortcuts);
 
         verifyStates();
     }
@@ -2117,13 +2243,19 @@
     public void removeAllDynamicShortcuts(String packageName, @UserIdInt int userId) {
         verifyCaller(packageName, userId);
 
+        List<ShortcutInfo> changedShortcuts = null;
+        List<ShortcutInfo> removedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
             final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId);
-            ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
+
+            removedShortcuts = ps.deleteAllDynamicShortcuts(/*ignoreInvisible=*/ true);
         }
-        packageShortcutsChanged(packageName, userId);
+
+        // TODO: Pinned and cached shortcuts are not removed, add those to changedShortcuts list
+        packageShortcutsChanged(packageName, userId, changedShortcuts, removedShortcuts);
 
         verifyStates();
     }
@@ -2134,6 +2266,9 @@
         verifyCaller(packageName, userId);
         Objects.requireNonNull(shortcutIds, "shortcutIds must be provided");
 
+        List<ShortcutInfo> changedShortcuts = null;
+        List<ShortcutInfo> removedShortcuts = null;
+
         synchronized (mLock) {
             throwIfUserLockedL(userId);
 
@@ -2144,13 +2279,29 @@
 
             for (int i = shortcutIds.size() - 1; i >= 0; i--) {
                 final String id = Preconditions.checkStringNotEmpty((String) shortcutIds.get(i));
-                ps.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
+
+                final ShortcutInfo si = ps.findShortcutById(id);
+                final boolean removed = ps.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
+
+                if (si != null) {
+                    if (removed) {
+                        if (removedShortcuts == null) {
+                            removedShortcuts = new ArrayList<>(1);
+                        }
+                        removedShortcuts.add(si);
+                    } else {
+                        if (changedShortcuts == null) {
+                            changedShortcuts = new ArrayList<>(1);
+                        }
+                        changedShortcuts.add(si);
+                    }
+                }
             }
 
             // We may have removed dynamic shortcuts which may have left a gap, so adjust the ranks.
             ps.adjustRanks();
         }
-        packageShortcutsChanged(packageName, userId);
+        packageShortcutsChanged(packageName, userId, changedShortcuts, removedShortcuts);
 
         verifyStates();
     }
@@ -2742,6 +2893,8 @@
             Preconditions.checkStringNotEmpty(packageName, "packageName");
             Objects.requireNonNull(shortcutIds, "shortcutIds");
 
+            List<ShortcutInfo> changedShortcuts = null;
+
             synchronized (mLock) {
                 throwIfUserLockedL(userId);
                 throwIfUserLockedL(launcherUserId);
@@ -2751,8 +2904,23 @@
                 launcher.attemptToRestoreIfNeededAndSave();
 
                 launcher.pinShortcuts(userId, packageName, shortcutIds, /*forPinRequest=*/ false);
+
+                final ShortcutPackage sp = getUserShortcutsLocked(userId)
+                        .getPackageShortcutsIfExists(packageName);
+                if (sp != null) {
+                    for (int i = 0; i < shortcutIds.size(); i++) {
+                        final ShortcutInfo si = sp.findShortcutById(shortcutIds.get(i));
+                        if (si != null) {
+                            if (changedShortcuts == null) {
+                                changedShortcuts = new ArrayList<>(1);
+                            }
+                            changedShortcuts.add(si);
+                        }
+                    }
+                }
             }
-            packageShortcutsChanged(packageName, userId);
+            // TODO: Include previously pinned shortcuts since they are not pinned anymore.
+            packageShortcutsChanged(packageName, userId, changedShortcuts, null);
 
             verifyStates();
         }
@@ -2773,6 +2941,13 @@
                     userId, /* doCache= */ false);
         }
 
+        @Override
+        public List<ShortcutManager.ShareShortcutInfo> getShareTargets(
+                @NonNull String callingPackage, @NonNull IntentFilter intentFilter, int userId) {
+            return ShortcutService.this.getShareTargets(
+                    callingPackage, intentFilter, userId).getList();
+        }
+
         private void updateCachedShortcutsInternal(int launcherUserId,
                 @NonNull String callingPackage, @NonNull String packageName,
                 @NonNull List<String> shortcutIds, int userId, boolean doCache) {
@@ -2780,6 +2955,9 @@
             Preconditions.checkStringNotEmpty(packageName, "packageName");
             Objects.requireNonNull(shortcutIds, "shortcutIds");
 
+            List<ShortcutInfo> changedShortcuts = null;
+            List<ShortcutInfo> removedShortcuts = null;
+
             synchronized (mLock) {
                 throwIfUserLockedL(userId);
                 throwIfUserLockedL(launcherUserId);
@@ -2801,20 +2979,36 @@
                     if (doCache) {
                         if (si.isDynamic() && si.isLongLived()) {
                             si.addFlags(ShortcutInfo.FLAG_CACHED);
+                            if (changedShortcuts == null) {
+                                changedShortcuts = new ArrayList<>(1);
+                            }
+                            changedShortcuts.add(si);
                         } else {
                             Log.w(TAG, "Only dynamic long lived shortcuts can get cached. Ignoring"
                                     + "shortcut " + si.getId());
                         }
                     } else {
+                        boolean removed = false;
                         if (si.isDynamic()) {
                             si.clearFlags(ShortcutInfo.FLAG_CACHED);
                         } else {
-                            sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
+                            removed = sp.deleteLongLivedWithId(id, /*ignoreInvisible=*/ true);
+                        }
+                        if (removed) {
+                            if (removedShortcuts == null) {
+                                removedShortcuts = new ArrayList<>(1);
+                            }
+                            removedShortcuts.add(si);
+                        } else {
+                            if (changedShortcuts == null) {
+                                changedShortcuts = new ArrayList<>(1);
+                            }
+                            changedShortcuts.add(si);
                         }
                     }
                 }
             }
-            packageShortcutsChanged(packageName, userId);
+            packageShortcutsChanged(packageName, userId, changedShortcuts, removedShortcuts);
 
             verifyStates();
         }
@@ -2860,6 +3054,14 @@
         }
 
         @Override
+        public void addShortcutChangeCallback(
+                @NonNull LauncherApps.ShortcutChangeCallback callback) {
+            synchronized (mLock) {
+                mShortcutChangeCallbacks.add(Objects.requireNonNull(callback));
+            }
+        }
+
+        @Override
         public int getShortcutIconResId(int launcherUserId, @NonNull String callingPackage,
                 @NonNull String packageName, @NonNull String shortcutId, int userId) {
             Objects.requireNonNull(callingPackage, "callingPackage");
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index 614cc3f..fe99229 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -29,6 +29,7 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageInstaller.SessionInfo;
@@ -39,7 +40,6 @@
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.ParceledListSlice;
-import android.content.pm.parsing.AndroidPackage;
 import android.content.rollback.IRollbackManager;
 import android.content.rollback.RollbackInfo;
 import android.content.rollback.RollbackManager;
@@ -68,6 +68,8 @@
 import com.android.internal.content.PackageHelper;
 import com.android.internal.os.BackgroundThread;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
 import com.android.server.rollback.WatchdogRollbackLogger;
 
 import java.io.File;
@@ -284,8 +286,10 @@
             throws PackageManagerException {
         final long activeVersion = activePackage.applicationInfo.longVersionCode;
         final long newVersionCode = newPackage.applicationInfo.longVersionCode;
+        boolean isAppDebuggable = (activePackage.applicationInfo.flags
+                & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
         final boolean allowsDowngrade = PackageManagerServiceUtils.isDowngradePermitted(
-                session.params.installFlags, activePackage.applicationInfo.flags);
+                session.params.installFlags, isAppDebuggable);
         if (activeVersion > newVersionCode && !allowsDowngrade) {
             if (!mApexManager.abortStagedSession(session.sessionId)) {
                 Slog.e(TAG, "Failed to abort apex session " + session.sessionId);
@@ -426,11 +430,10 @@
                     + "for snapshotting/restoring user data.");
             return;
         }
-        final String seInfo = pkg.getSeInfo();
 
         int appId = -1;
         long ceDataInode = -1;
-        final PackageSetting ps = (PackageSetting) mPmi.getPackageSetting(packageName);
+        final PackageSetting ps = mPmi.getPackageSetting(packageName);
         if (ps != null) {
             appId = ps.appId;
             ceDataInode = ps.getCeDataInode(UserHandle.USER_SYSTEM);
@@ -438,6 +441,7 @@
             // an update, and hence need to restore data for all installed users.
             final int[] installedUsers = ps.queryInstalledUsers(allUsers, true);
 
+            final String seInfo = AndroidPackageUtils.getSeInfo(pkg, ps);
             try {
                 rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
                         seInfo, 0 /*token*/);
diff --git a/services/core/java/com/android/server/pm/TEST_MAPPING b/services/core/java/com/android/server/pm/TEST_MAPPING
index 81c7471..97f9548 100644
--- a/services/core/java/com/android/server/pm/TEST_MAPPING
+++ b/services/core/java/com/android/server/pm/TEST_MAPPING
@@ -13,6 +13,9 @@
       "name": "AppEnumerationTests"
     },
     {
+      "name": "CtsMatchFlagTestCases"
+    },
+    {
       "name": "FrameworksServicesTests",
       "options": [
         {
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index cb755f9..df3c83a 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -437,7 +437,7 @@
     /**
      * Start an {@link IntentSender} when user is unlocked after disabling quiet mode.
      *
-     * @see {@link #requestQuietModeEnabled(String, boolean, int, IntentSender)}
+     * @see #requestQuietModeEnabled(String, boolean, int, IntentSender, int)
      */
     private class DisableQuietModeUserUnlockedCallback extends IProgressListener.Stub {
         private final IntentSender mTarget;
@@ -967,7 +967,16 @@
                     "target should only be specified when we are disabling quiet mode.");
         }
 
-        ensureCanModifyQuietMode(callingPackage, Binder.getCallingUid(), userId, target != null);
+        final boolean dontAskCredential =
+                (flags & UserManager.QUIET_MODE_DISABLE_DONT_ASK_CREDENTIAL) != 0;
+        final boolean onlyIfCredentialNotRequired =
+                (flags & UserManager.QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED) != 0;
+        if (dontAskCredential && onlyIfCredentialNotRequired) {
+            throw new IllegalArgumentException("invalid flags: " + flags);
+        }
+
+        ensureCanModifyQuietMode(
+                callingPackage, Binder.getCallingUid(), userId, target != null, dontAskCredential);
         final long identity = Binder.clearCallingIdentity();
         try {
             if (enableQuietMode) {
@@ -976,11 +985,11 @@
                 return true;
             }
             mLockPatternUtils.tryUnlockWithCachedUnifiedChallenge(userId);
-            boolean needToShowConfirmCredential =
-                    mLockPatternUtils.isSecure(userId)
-                            && !StorageManager.isUserKeyUnlocked(userId);
+            final boolean needToShowConfirmCredential = !dontAskCredential
+                    && mLockPatternUtils.isSecure(userId)
+                    && !StorageManager.isUserKeyUnlocked(userId);
             if (needToShowConfirmCredential) {
-                if ((flags & UserManager.QUIET_MODE_DISABLE_ONLY_IF_CREDENTIAL_NOT_REQUIRED) != 0) {
+                if (onlyIfCredentialNotRequired) {
                     return false;
                 }
                 showConfirmCredentialToDisableQuietMode(userId, target);
@@ -1007,7 +1016,7 @@
      * {@link Manifest.permission#MANAGE_USERS}.
      */
     private void ensureCanModifyQuietMode(String callingPackage, int callingUid,
-            @UserIdInt int targetUserId, boolean startIntent) {
+            @UserIdInt int targetUserId, boolean startIntent, boolean dontAskCredential) {
         if (hasManageUsersPermission()) {
             return;
         }
@@ -1015,6 +1024,10 @@
             throw new SecurityException("MANAGE_USERS permission is required to start intent "
                     + "after disabling quiet mode.");
         }
+        if (dontAskCredential) {
+            throw new SecurityException("MANAGE_USERS permission is required to disable quiet "
+                    + "mode without credentials.");
+        }
         if (!isSameProfileGroupNoChecks(UserHandle.getUserId(callingUid), targetUserId)) {
             throw new SecurityException("MANAGE_USERS permission is required to modify quiet mode "
                     + "for a different profile group.");
diff --git a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
index 67b1008..27e8b0b 100644
--- a/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
+++ b/services/core/java/com/android/server/pm/UserRestrictionsUtils.java
@@ -585,6 +585,9 @@
                             android.provider.Settings.Global.putStringForUser(cr,
                                     android.provider.Settings.Global.ADB_ENABLED, "0",
                                     userId);
+                            android.provider.Settings.Global.putStringForUser(cr,
+                                    android.provider.Settings.Global.ADB_WIFI_ENABLED, "0",
+                                    userId);
                         }
                     }
                     break;
@@ -721,6 +724,7 @@
                 break;
 
             case android.provider.Settings.Global.ADB_ENABLED:
+            case android.provider.Settings.Global.ADB_WIFI_ENABLED:
                 if ("0".equals(value)) {
                     return false;
                 }
diff --git a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
index 4c40448..d6480d3 100644
--- a/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
+++ b/services/core/java/com/android/server/pm/UserSystemPackageInstaller.java
@@ -22,7 +22,6 @@
 import android.annotation.UserIdInt;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.AndroidPackage;
 import android.content.res.Resources;
 import android.os.SystemProperties;
 import android.os.UserHandle;
@@ -33,6 +32,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import java.io.PrintWriter;
 import java.lang.annotation.Retention;
@@ -190,13 +190,14 @@
         // Install/uninstall system packages per user.
         for (int userId : mUm.getUserIds()) {
             final Set<String> userWhitelist = getInstallablePackagesForUserId(userId);
-            pmInt.forEachPackage(pkg -> {
-                if (!pkg.isSystem()) {
+            pmInt.forEachPackageSetting(pkgSetting -> {
+                AndroidPackage pkg = pkgSetting.pkg;
+                if (pkg == null || !pkg.isSystem()) {
                     return;
                 }
                 final boolean install =
                         (userWhitelist == null || userWhitelist.contains(pkg.getPackageName()))
-                        && !pkg.isHiddenUntilInstalled();
+                                && !pkgSetting.getPkgState().isHiddenUntilInstalled();
                 if (isConsideredUpgrade && !isFirstBoot && !install) {
                     return; // To be careful, we don’t uninstall apps during OTAs
                 }
diff --git a/services/core/java/com/android/server/pm/dex/ArtManagerService.java b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
index 0caab6d..51e07faf 100644
--- a/services/core/java/com/android/server/pm/dex/ArtManagerService.java
+++ b/services/core/java/com/android/server/pm/dex/ArtManagerService.java
@@ -31,7 +31,7 @@
 import android.content.pm.dex.DexMetadataHelper;
 import android.content.pm.dex.ISnapshotRuntimeProfileCallback;
 import android.content.pm.dex.PackageOptimizationInfo;
-import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.os.Binder;
 import android.os.Build;
 import android.os.Handler;
@@ -54,6 +54,7 @@
 import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.PackageManagerServiceCompilerMapping;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import dalvik.system.DexFile;
 import dalvik.system.VMRuntime;
@@ -482,8 +483,10 @@
         try {
             final String packageName = pkg.getPackageName();
             final String apkPath = pkg.getBaseCodePath();
-            final String outDexFile = pkg.getDataDir() + "/code_cache/compiled_view.dex";
-            if (pkg.isPrivileged() || pkg.isEmbeddedDexUsed()
+            // TODO(b/143971007): Use a cross-user directory
+            File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId());
+            final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
+            if (pkg.isPrivileged() || pkg.isUseEmbeddedDex()
                     || pkg.isDefaultToDeviceProtectedStorage()) {
                 // Privileged apps prefer to load trusted code so they don't use compiled views.
                 // If the app is not privileged but prefers code integrity, also avoid compiling
@@ -516,7 +519,7 @@
      */
     private ArrayMap<String, String> getPackageProfileNames(AndroidPackage pkg) {
         ArrayMap<String, String> result = new ArrayMap<>();
-        if ((pkg.getFlags() & ApplicationInfo.FLAG_HAS_CODE) != 0) {
+        if (pkg.isHasCode()) {
             result.put(pkg.getBaseCodePath(), ArtManager.getProfileName(null));
         }
 
diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java
index df24c013..117cc5e 100644
--- a/services/core/java/com/android/server/pm/dex/DexManager.java
+++ b/services/core/java/com/android/server/pm/dex/DexManager.java
@@ -41,6 +41,8 @@
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.PackageManagerServiceUtils;
 
+import dalvik.system.VMRuntime;
+
 import java.io.File;
 import java.io.IOException;
 import java.util.Arrays;
@@ -136,22 +138,15 @@
      * return as fast as possible.
      *
      * @param loadingAppInfo the package performing the load
-     * @param classLoadersNames the names of the class loaders present in the loading chain. The
-     *    list encodes the class loader chain in the natural order. The first class loader has
-     *    the second one as its parent and so on. The dex files present in the class path of the
-     *    first class loader will be recorded in the usage file.
-     * @param classPaths the class paths corresponding to the class loaders names from
-     *     {@param classLoadersNames}. The the first element corresponds to the first class loader
-     *     and so on. A classpath is represented as a list of dex files separated by
-     *     {@code File.pathSeparator}, or null if the class loader's classpath is not known.
-     *     The dex files found in the first class path will be recorded in the usage file.
+     * @param classLoaderContextMap a map from file paths to dex files that have been loaded to
+     *     the class loader context that was used to load them.
      * @param loaderIsa the ISA of the app loading the dex files
      * @param loaderUserId the user id which runs the code loading the dex files
      */
-    public void notifyDexLoad(ApplicationInfo loadingAppInfo, List<String> classLoadersNames,
-            List<String> classPaths, String loaderIsa, int loaderUserId) {
+    public void notifyDexLoad(ApplicationInfo loadingAppInfo,
+            Map<String, String> classLoaderContextMap, String loaderIsa, int loaderUserId) {
         try {
-            notifyDexLoadInternal(loadingAppInfo, classLoadersNames, classPaths, loaderIsa,
+            notifyDexLoadInternal(loadingAppInfo, classLoaderContextMap, loaderIsa,
                     loaderUserId);
         } catch (Exception e) {
             Slog.w(TAG, "Exception while notifying dex load for package " +
@@ -161,46 +156,23 @@
 
     @VisibleForTesting
     /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo,
-            List<String> classLoaderNames, List<String> classPaths, String loaderIsa,
+            Map<String, String> classLoaderContextMap, String loaderIsa,
             int loaderUserId) {
-        if (classLoaderNames.size() != classPaths.size()) {
-            Slog.wtf(TAG, "Bad call to noitfyDexLoad: args have different size");
+        if (classLoaderContextMap == null) {
             return;
         }
-        if (classLoaderNames.isEmpty()) {
+        if (classLoaderContextMap.isEmpty()) {
             Slog.wtf(TAG, "Bad call to notifyDexLoad: class loaders list is empty");
             return;
         }
         if (!PackageManagerServiceUtils.checkISA(loaderIsa)) {
-            Slog.w(TAG, "Loading dex files " + classPaths + " in unsupported ISA: " +
-                    loaderIsa + "?");
+            Slog.w(TAG, "Loading dex files " + classLoaderContextMap.keySet()
+                    + " in unsupported ISA: " + loaderIsa + "?");
             return;
         }
 
-        // The first classpath should never be null because the first classloader
-        // should always be an instance of BaseDexClassLoader.
-        String firstClassPath = classPaths.get(0);
-        if (firstClassPath == null) {
-            return;
-        }
-        // The classpath is represented as a list of dex files separated by File.pathSeparator.
-        String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator);
-
-        // Encode the class loader contexts for the dexPathsToRegister.
-        String[] classLoaderContexts = DexoptUtils.processContextForDexLoad(
-                classLoaderNames, classPaths);
-
-        // A null classLoaderContexts means that there are unsupported class loaders in the
-        // chain.
-        if (classLoaderContexts == null) {
-            if (DEBUG) {
-                Slog.i(TAG, loadingAppInfo.packageName +
-                        " uses unsupported class loader in " + classLoaderNames);
-            }
-        }
-
-        int dexPathIndex = 0;
-        for (String dexPath : dexPathsToRegister) {
+        for (Map.Entry<String, String> mapping : classLoaderContextMap.entrySet()) {
+            String dexPath = mapping.getKey();
             // Find the owning package name.
             DexSearchResult searchResult = getDexPackage(loadingAppInfo, dexPath, loaderUserId);
 
@@ -222,7 +194,6 @@
                     // If the dex file is the primary apk (or a split) and not isUsedByOtherApps
                     // do not record it. This case does not bring any new usable information
                     // and can be safely skipped.
-                    dexPathIndex++;
                     continue;
                 }
 
@@ -232,13 +203,13 @@
                             searchResult.mOwningPackageName, loadingAppInfo.packageName);
                 }
 
-                if (classLoaderContexts != null) {
-
+                String classLoaderContext = mapping.getValue();
+                if (classLoaderContext != null
+                        && VMRuntime.isValidClassLoaderContext(classLoaderContext)) {
                     // Record dex file usage. If the current usage is a new pattern (e.g. new
                     // secondary, or UsedByOtherApps), record will return true and we trigger an
                     // async write to disk to make sure we don't loose the data in case of a reboot.
 
-                    String classLoaderContext = classLoaderContexts[dexPathIndex];
                     if (mPackageDexUsage.record(searchResult.mOwningPackageName,
                             dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit,
                             loadingAppInfo.packageName, classLoaderContext)) {
@@ -252,7 +223,6 @@
                     Slog.i(TAG, "Could not find owning package for dex file: " + dexPath);
                 }
             }
-            dexPathIndex++;
         }
     }
 
diff --git a/services/core/java/com/android/server/pm/dex/DexoptUtils.java b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
index 6e6b137..6807388 100644
--- a/services/core/java/com/android/server/pm/dex/DexoptUtils.java
+++ b/services/core/java/com/android/server/pm/dex/DexoptUtils.java
@@ -18,7 +18,7 @@
 
 import android.content.pm.ApplicationInfo;
 import android.content.pm.SharedLibraryInfo;
-import android.content.pm.parsing.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import android.util.Slog;
 import android.util.SparseArray;
 
@@ -77,7 +77,7 @@
         }
 
         String baseApkContextClassLoader = encodeClassLoader(
-                "", pkg.getAppInfoClassLoaderName(), sharedLibrariesContext);
+                "", pkg.getClassLoaderName(), sharedLibrariesContext);
         if (pkg.getSplitCodePaths() == null) {
             // The application has no splits.
             return new String[] {baseApkContextClassLoader};
@@ -101,7 +101,7 @@
 
         SparseArray<int[]> splitDependencies = pkg.getSplitDependencies();
 
-        if (!pkg.requestsIsolatedSplitLoading()
+        if (!pkg.isIsolatedSplitLoading()
                 || splitDependencies == null
                 || splitDependencies.size() == 0) {
             // If the app didn't request for the splits to be loaded in isolation or if it does not
@@ -111,7 +111,7 @@
             for (int i = 1; i < classLoaderContexts.length; i++) {
                 if (pathsWithCode[i]) {
                     classLoaderContexts[i] = encodeClassLoader(
-                            classpath, pkg.getAppInfoClassLoaderName(), sharedLibrariesContext);
+                            classpath, pkg.getClassLoaderName(), sharedLibrariesContext);
                 } else {
                     classLoaderContexts[i] = null;
                 }
diff --git a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
index e68c238..08763e7 100644
--- a/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
+++ b/services/core/java/com/android/server/pm/dex/PackageDexUsage.java
@@ -83,8 +83,9 @@
             "=UnknownClassLoaderContext=";
 
     // The marker used for unsupported class loader contexts (no longer written, may occur in old
-    // files so discarded on read).
-    private static final String UNSUPPORTED_CLASS_LOADER_CONTEXT =
+    // files so discarded on read). Note: this matches
+    // ClassLoaderContext::kUnsupportedClassLoaderContextEncoding in the runtime.
+    /*package*/ static final String UNSUPPORTED_CLASS_LOADER_CONTEXT =
             "=UnsupportedClassLoaderContext=";
 
     /**
@@ -133,6 +134,9 @@
         if (classLoaderContext == null) {
             throw new IllegalArgumentException("Null classLoaderContext");
         }
+        if (classLoaderContext.equals(UNSUPPORTED_CLASS_LOADER_CONTEXT)) {
+            return false;
+        }
 
         synchronized (mPackageUseInfoMap) {
             PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(owningPackageName);
@@ -843,10 +847,11 @@
             boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages);
 
             String oldClassLoaderContext = mClassLoaderContext;
-            if (UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext)) {
+            if (isUnknownOrUnsupportedContext(mClassLoaderContext)) {
                 // Can happen if we read a previous version.
                 mClassLoaderContext = dexUseInfo.mClassLoaderContext;
-            } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
+            } else if (!isUnknownOrUnsupportedContext(dexUseInfo.mClassLoaderContext)
+                        && !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) {
                 // We detected a context change.
                 mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT;
             }
@@ -857,6 +862,13 @@
                     || !Objects.equals(oldClassLoaderContext, mClassLoaderContext);
         }
 
+        private static boolean isUnknownOrUnsupportedContext(String context) {
+            // TODO: Merge UNKNOWN_CLASS_LOADER_CONTEXT & UNSUPPORTED_CLASS_LOADER_CONTEXT cases
+            // into UNSUPPORTED_CLASS_LOADER_CONTEXT.
+            return UNKNOWN_CLASS_LOADER_CONTEXT.equals(context)
+                    || UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context);
+        }
+
         public boolean isUsedByOtherApps() {
             return mIsUsedByOtherApps;
         }
@@ -878,7 +890,7 @@
         public boolean isUnknownClassLoaderContext() {
             // The class loader context may be unknown if we loaded the data from a previous version
             // which didn't save the context.
-            return UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext);
+            return isUnknownOrUnsupportedContext(mClassLoaderContext);
         }
 
         public boolean isVariableClassLoaderContext() {
diff --git a/services/core/java/com/android/server/pm/dex/ViewCompiler.java b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
index b7443f3..5506a52 100644
--- a/services/core/java/com/android/server/pm/dex/ViewCompiler.java
+++ b/services/core/java/com/android/server/pm/dex/ViewCompiler.java
@@ -16,12 +16,16 @@
 
 package com.android.server.pm.dex;
 
-import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.os.Binder;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.server.pm.Installer;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
+import java.io.File;
 
 public class ViewCompiler {
     private final Object mInstallLock;
@@ -37,7 +41,9 @@
         try {
             final String packageName = pkg.getPackageName();
             final String apkPath = pkg.getBaseCodePath();
-            final String outDexFile = pkg.getDataDir() + "/code_cache/compiled_view.dex";
+            // TODO(b/143971007): Use a cross-user directory
+            File dataDir = PackageInfoWithoutStateUtils.getDataDir(pkg, UserHandle.myUserId());
+            final String outDexFile = dataDir.getAbsolutePath() + "/code_cache/compiled_view.dex";
             Log.i("PackageManager", "Compiling layouts in " + packageName + " (" + apkPath +
                 ") to " + outDexFile);
             long callingId = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
new file mode 100644
index 0000000..e5e1b0b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java
@@ -0,0 +1,200 @@
+/*
+ * 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.pm.parsing;
+
+import android.annotation.NonNull;
+import android.content.pm.PackageParserCacheHelper;
+import android.os.Parcel;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
+import android.util.Slog;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+import libcore.io.IoUtils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class PackageCacher {
+
+    private static final String TAG = "PackageCacher";
+
+    /**
+     * Total number of packages that were read from the cache.  We use it only for logging.
+     */
+    public static final AtomicInteger sCachedPackageReadCount = new AtomicInteger();
+
+    @NonNull
+    private File mCacheDir;
+
+    public PackageCacher(@NonNull File cacheDir) {
+        this.mCacheDir = cacheDir;
+    }
+
+    /**
+     * Returns the cache key for a specified {@code packageFile} and {@code flags}.
+     */
+    private String getCacheKey(File packageFile, int flags) {
+        StringBuilder sb = new StringBuilder(packageFile.getName());
+        sb.append('-');
+        sb.append(flags);
+
+        return sb.toString();
+    }
+
+    @VisibleForTesting
+    protected ParsedPackage fromCacheEntry(byte[] bytes) {
+        return fromCacheEntryStatic(bytes);
+    }
+
+    /** static version of {@link #fromCacheEntry} for unit tests. */
+    @VisibleForTesting
+    public static ParsedPackage fromCacheEntryStatic(byte[] bytes) {
+        final Parcel p = Parcel.obtain();
+        p.unmarshall(bytes, 0, bytes.length);
+        p.setDataPosition(0);
+
+        final PackageParserCacheHelper.ReadHelper helper = new PackageParserCacheHelper.ReadHelper(p);
+        helper.startAndInstall();
+
+        // TODO(b/135203078): Hide PackageImpl constructor?
+        ParsedPackage pkg = new PackageImpl(p);
+
+        p.recycle();
+
+        sCachedPackageReadCount.incrementAndGet();
+
+        return pkg;
+    }
+
+    @VisibleForTesting
+    protected byte[] toCacheEntry(ParsedPackage pkg) {
+        return toCacheEntryStatic(pkg);
+
+    }
+
+    /** static version of {@link #toCacheEntry} for unit tests. */
+    @VisibleForTesting
+    public static byte[] toCacheEntryStatic(ParsedPackage pkg) {
+        final Parcel p = Parcel.obtain();
+        final PackageParserCacheHelper.WriteHelper helper = new PackageParserCacheHelper.WriteHelper(p);
+
+        pkg.writeToParcel(p, 0 /* flags */);
+
+        helper.finishAndUninstall();
+
+        byte[] serialized = p.marshall();
+        p.recycle();
+
+        return serialized;
+    }
+
+    /**
+     * Given a {@code packageFile} and a {@code cacheFile} returns whether the
+     * cache file is up to date based on the mod-time of both files.
+     */
+    private static boolean isCacheUpToDate(File packageFile, File cacheFile) {
+        try {
+            // NOTE: We don't use the File.lastModified API because it has the very
+            // non-ideal failure mode of returning 0 with no excepions thrown.
+            // The nio2 Files API is a little better but is considerably more expensive.
+            final StructStat pkg = Os.stat(packageFile.getAbsolutePath());
+            final StructStat cache = Os.stat(cacheFile.getAbsolutePath());
+            return pkg.st_mtime < cache.st_mtime;
+        } catch (ErrnoException ee) {
+            // The most common reason why stat fails is that a given cache file doesn't
+            // exist. We ignore that here. It's easy to reason that it's safe to say the
+            // cache isn't up to date if we see any sort of exception here.
+            //
+            // (1) Exception while stating the package file : This should never happen,
+            // and if it does, we do a full package parse (which is likely to throw the
+            // same exception).
+            // (2) Exception while stating the cache file : If the file doesn't exist, the
+            // cache is obviously out of date. If the file *does* exist, we can't read it.
+            // We will attempt to delete and recreate it after parsing the package.
+            if (ee.errno != OsConstants.ENOENT) {
+                Slog.w("Error while stating package cache : ", ee);
+            }
+
+            return false;
+        }
+    }
+
+    /**
+     * Returns the cached parse result for {@code packageFile} for parse flags {@code flags},
+     * or {@code null} if no cached result exists.
+     */
+    public ParsedPackage getCachedResult(File packageFile, int flags) {
+        final String cacheKey = getCacheKey(packageFile, flags);
+        final File cacheFile = new File(mCacheDir, cacheKey);
+
+        try {
+            // If the cache is not up to date, return null.
+            if (!isCacheUpToDate(packageFile, cacheFile)) {
+                return null;
+            }
+
+            final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
+            return fromCacheEntry(bytes);
+        } catch (Throwable e) {
+            Slog.w(TAG, "Error reading package cache: ", e);
+
+            // If something went wrong while reading the cache entry, delete the cache file
+            // so that we regenerate it the next time.
+            cacheFile.delete();
+            return null;
+        }
+    }
+
+    /**
+     * Caches the parse result for {@code packageFile} with flags {@code flags}.
+     */
+    public void cacheResult(File packageFile, int flags, ParsedPackage parsed) {
+        try {
+            final String cacheKey = getCacheKey(packageFile, flags);
+            final File cacheFile = new File(mCacheDir, cacheKey);
+
+            if (cacheFile.exists()) {
+                if (!cacheFile.delete()) {
+                    Slog.e(TAG, "Unable to delete cache file: " + cacheFile);
+                }
+            }
+
+            final byte[] cacheEntry = toCacheEntry(parsed);
+
+            if (cacheEntry == null) {
+                return;
+            }
+
+            try (FileOutputStream fos = new FileOutputStream(cacheFile)) {
+                fos.write(cacheEntry);
+            } catch (IOException ioe) {
+                Slog.w(TAG, "Error writing cache entry.", ioe);
+                cacheFile.delete();
+            }
+        } catch (Throwable e) {
+            Slog.w(TAG, "Error saving package cache.", e);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
new file mode 100644
index 0000000..23bdf5f
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -0,0 +1,483 @@
+/*
+ * 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.pm.parsing;
+
+import android.annotation.CheckResult;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.apex.ApexInfo;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ComponentInfo;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageItemInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageUserState;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProcessInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
+import android.content.pm.parsing.component.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProcess;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.PackageSetting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.pkg.PackageStateUnserialized;
+
+import libcore.util.EmptyArray;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+/**
+ * Methods that use a {@link PackageSetting} use it to override information provided from the raw
+ * package, or to provide information that would otherwise be missing. Null can be passed if none
+ * of the state values should be applied.
+ *
+ * @hide
+ **/
+public class PackageInfoUtils {
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static PackageInfo generate(AndroidPackage pkg, int[] gids,
+            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+            Set<String> grantedPermissions, PackageUserState state, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        return generateWithComponents(pkg, gids, flags, firstInstallTime, lastUpdateTime,
+                grantedPermissions, state, userId, null, pkgSetting);
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static PackageInfo generate(AndroidPackage pkg, ApexInfo apexInfo, int flags,
+            @Nullable PackageSetting pkgSetting) {
+        return generateWithComponents(pkg, EmptyArray.INT, flags, 0, 0, Collections.emptySet(),
+                new PackageUserState(), UserHandle.getCallingUserId(), apexInfo, pkgSetting);
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    private static PackageInfo generateWithComponents(AndroidPackage pkg, int[] gids,
+            @PackageManager.PackageInfoFlags int flags, long firstInstallTime, long lastUpdateTime,
+            Set<String> grantedPermissions, PackageUserState state, int userId,
+            @Nullable ApexInfo apexInfo, @Nullable PackageSetting pkgSetting) {
+        ApplicationInfo applicationInfo = generateApplicationInfo(pkg, flags, state, userId,
+                pkgSetting);
+        if (applicationInfo == null) {
+            return null;
+        }
+
+        PackageInfo info = PackageInfoWithoutStateUtils.generateWithoutComponents(pkg, gids, flags,
+                firstInstallTime, lastUpdateTime, grantedPermissions, state, userId, apexInfo,
+                applicationInfo);
+        if (info == null) {
+            return null;
+        }
+
+        info.isStub = pkg.isStub();
+        info.coreApp = pkg.isCoreApp();
+
+        if ((flags & PackageManager.GET_ACTIVITIES) != 0) {
+            final int N = pkg.getActivities().size();
+            if (N > 0) {
+                int num = 0;
+                final ActivityInfo[] res = new ActivityInfo[N];
+                for (int i = 0; i < N; i++) {
+                    final ParsedActivity a = pkg.getActivities().get(i);
+                    if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a,
+                            flags)) {
+                        if (PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME.equals(
+                                a.getName())) {
+                            continue;
+                        }
+                        res[num++] = generateActivityInfo(pkg, a, flags, state,
+                                applicationInfo, userId, pkgSetting);
+                    }
+                }
+                info.activities = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_RECEIVERS) != 0) {
+            final int size = pkg.getReceivers().size();
+            if (size > 0) {
+                int num = 0;
+                final ActivityInfo[] res = new ActivityInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedActivity a = pkg.getReceivers().get(i);
+                    if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), a,
+                            flags)) {
+                        res[num++] = generateActivityInfo(pkg, a, flags, state, applicationInfo,
+                                userId, pkgSetting);
+                    }
+                }
+                info.receivers = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_SERVICES) != 0) {
+            final int size = pkg.getServices().size();
+            if (size > 0) {
+                int num = 0;
+                final ServiceInfo[] res = new ServiceInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedService s = pkg.getServices().get(i);
+                    if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), s,
+                            flags)) {
+                        res[num++] = generateServiceInfo(pkg, s, flags, state, applicationInfo,
+                                userId, pkgSetting);
+                    }
+                }
+                info.services = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_PROVIDERS) != 0) {
+            final int size = pkg.getProviders().size();
+            if (size > 0) {
+                int num = 0;
+                final ProviderInfo[] res = new ProviderInfo[size];
+                for (int i = 0; i < size; i++) {
+                    final ParsedProvider pr = pkg.getProviders()
+                            .get(i);
+                    if (ComponentParseUtils.isMatch(state, pkg.isSystem(), pkg.isEnabled(), pr,
+                            flags)) {
+                        res[num++] = generateProviderInfo(pkg, pr, flags, state, applicationInfo,
+                                userId, pkgSetting);
+                    }
+                }
+                info.providers = ArrayUtils.trimToSize(res, num);
+            }
+        }
+        if ((flags & PackageManager.GET_INSTRUMENTATION) != 0) {
+            int N = pkg.getInstrumentations().size();
+            if (N > 0) {
+                info.instrumentation = new InstrumentationInfo[N];
+                for (int i = 0; i < N; i++) {
+                    info.instrumentation[i] = generateInstrumentationInfo(
+                            pkg.getInstrumentations().get(i), pkg, flags, userId, pkgSetting);
+                }
+            }
+        }
+
+        return info;
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static ApplicationInfo generateApplicationInfo(AndroidPackage pkg,
+            @PackageManager.ApplicationInfoFlags int flags, PackageUserState state, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        // TODO(b/135203078): Consider cases where we don't have a PkgSetting
+        if (pkg == null) {
+            return null;
+        }
+
+        if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)
+                || !AndroidPackageUtils.isMatchForSystemOnly(pkg, flags)) {
+            return null;
+        }
+
+        ApplicationInfo info = PackageInfoWithoutStateUtils.generateApplicationInfo(pkg, flags,
+                state, userId);
+        if (info == null) {
+            return null;
+        }
+
+        if (pkgSetting != null) {
+            // TODO(b/135203078): Remove PackageParser1/toAppInfoWithoutState and clean all this up
+            PackageStateUnserialized pkgState = pkgSetting.getPkgState();
+            info.hiddenUntilInstalled = pkgState.isHiddenUntilInstalled();
+            List<String> usesLibraryFiles = pkgState.getUsesLibraryFiles();
+            List<SharedLibraryInfo> usesLibraryInfos = pkgState.getUsesLibraryInfos();
+            info.sharedLibraryFiles = usesLibraryFiles.isEmpty()
+                    ? null : usesLibraryFiles.toArray(new String[0]);
+            info.sharedLibraryInfos = usesLibraryInfos.isEmpty() ? null : usesLibraryInfos;
+        }
+
+        info.flags |= appInfoFlags(pkg, pkgSetting);
+        info.privateFlags |= appInfoPrivateFlags(pkg, pkgSetting);
+        return info;
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        return generateActivityInfo(pkg, a, flags, state, null, userId, pkgSetting);
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    private static ActivityInfo generateActivityInfo(AndroidPackage pkg, ParsedActivity a,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        if (a == null) return null;
+        if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
+        }
+        ActivityInfo info = PackageInfoWithoutStateUtils.generateActivityInfo(pkg, a, flags, state,
+                applicationInfo, userId);
+        if (info == null) {
+            return null;
+        }
+
+        assignSharedFieldsForComponentInfo(info, a, pkgSetting);
+        return info;
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        return generateServiceInfo(pkg, s, flags, state, null, userId, pkgSetting);
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    private static ServiceInfo generateServiceInfo(AndroidPackage pkg, ParsedService s,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        if (s == null) return null;
+        if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
+        }
+        ServiceInfo info = PackageInfoWithoutStateUtils.generateServiceInfo(pkg, s, flags, state,
+                applicationInfo, userId);
+        if (info == null) {
+            return null;
+        }
+
+        assignSharedFieldsForComponentInfo(info, s, pkgSetting);
+        return info;
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        return generateProviderInfo(pkg, p, flags, state, null, userId, pkgSetting);
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    private static ProviderInfo generateProviderInfo(AndroidPackage pkg, ParsedProvider p,
+            @PackageManager.ComponentInfoFlags int flags, PackageUserState state,
+            @Nullable ApplicationInfo applicationInfo, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        if (p == null) return null;
+        if (!checkUseInstalledOrHidden(pkg, pkgSetting, state, flags)) {
+            return null;
+        }
+        if (applicationInfo == null) {
+            applicationInfo = generateApplicationInfo(pkg, flags, state, userId, pkgSetting);
+        }
+        ProviderInfo info = PackageInfoWithoutStateUtils.generateProviderInfo(pkg, p, flags, state,
+                applicationInfo, userId);
+        if (info == null) {
+            return null;
+        }
+
+        assignSharedFieldsForComponentInfo(info, p, pkgSetting);
+        return info;
+    }
+
+    /**
+     * @param pkgSetting See {@link PackageInfoUtils} for description of pkgSetting usage.
+     */
+    @Nullable
+    public static InstrumentationInfo generateInstrumentationInfo(ParsedInstrumentation i,
+            AndroidPackage pkg, @PackageManager.ComponentInfoFlags int flags, int userId,
+            @Nullable PackageSetting pkgSetting) {
+        if (i == null) return null;
+
+        InstrumentationInfo info =
+                PackageInfoWithoutStateUtils.generateInstrumentationInfo(i, pkg, flags, userId);
+        if (info == null) {
+            return null;
+        }
+
+        // TODO(b/135203078): Add setting related state
+        info.primaryCpuAbi = AndroidPackageUtils.getPrimaryCpuAbi(pkg, pkgSetting);
+        info.secondaryCpuAbi = AndroidPackageUtils.getSecondaryCpuAbi(pkg, pkgSetting);
+        info.nativeLibraryDir = pkg.getNativeLibraryDir();
+        info.secondaryNativeLibraryDir = pkg.getSecondaryNativeLibraryDir();
+
+        assignStateFieldsForPackageItemInfo(info, i, pkgSetting);
+
+        return info;
+    }
+
+    // TODO(b/135203078): Determine if permission methods need to pass in a non-null PackageSetting
+    //  os that checkUseInstalledOrHidden filter can apply
+    @Nullable
+    public static PermissionInfo generatePermissionInfo(ParsedPermission p,
+            @PackageManager.ComponentInfoFlags int flags) {
+        // TODO(b/135203078): Remove null checks and make all usages @NonNull
+        if (p == null) return null;
+
+        // For now, permissions don't have state-adjustable fields; return directly
+        return PackageInfoWithoutStateUtils.generatePermissionInfo(p, flags);
+    }
+
+    @Nullable
+    public static PermissionGroupInfo generatePermissionGroupInfo(ParsedPermissionGroup pg,
+            @PackageManager.ComponentInfoFlags int flags) {
+        if (pg == null) return null;
+
+        // For now, permissions don't have state-adjustable fields; return directly
+        return PackageInfoWithoutStateUtils.generatePermissionGroupInfo(pg, flags);
+    }
+
+    @Nullable
+    public static ArrayMap<String, ProcessInfo> generateProcessInfo(
+            Map<String, ParsedProcess> procs, @PackageManager.ComponentInfoFlags int flags) {
+        if (procs == null) {
+            return null;
+        }
+
+        final int numProcs = procs.size();
+        ArrayMap<String, ProcessInfo> retProcs = new ArrayMap<>(numProcs);
+        for (String key : procs.keySet()) {
+            ParsedProcess proc = procs.get(key);
+            retProcs.put(proc.getName(), new ProcessInfo(proc.getName(),
+                    new ArraySet<>(proc.getDeniedPermissions())));
+        }
+        return retProcs;
+    }
+
+    /**
+     * Returns true if the package is installed and not hidden, or if the caller
+     * explicitly wanted all uninstalled and hidden packages as well.
+     */
+    private static boolean checkUseInstalledOrHidden(AndroidPackage pkg,
+            PackageSetting pkgSetting, PackageUserState state,
+            @PackageManager.PackageInfoFlags int flags) {
+        // Returns false if the package is hidden system app until installed.
+        if ((flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) == 0
+                && !state.installed
+                && pkgSetting != null
+                && pkgSetting.getPkgState().isHiddenUntilInstalled()) {
+            return false;
+        }
+
+        // If available for the target user, or trying to match uninstalled packages and it's
+        // a system app.
+        return state.isAvailable(flags)
+                || (pkg.isSystem()
+                && ((flags & PackageManager.MATCH_KNOWN_PACKAGES) != 0
+                || (flags & PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS) != 0));
+    }
+
+    private static void assignSharedFieldsForComponentInfo(@NonNull ComponentInfo componentInfo,
+            @NonNull ParsedMainComponent mainComponent, @Nullable PackageSetting pkgSetting) {
+        assignStateFieldsForPackageItemInfo(componentInfo, mainComponent, pkgSetting);
+        componentInfo.descriptionRes = mainComponent.getDescriptionRes();
+        componentInfo.directBootAware = mainComponent.isDirectBootAware();
+        componentInfo.enabled = mainComponent.isEnabled();
+        componentInfo.splitName = mainComponent.getSplitName();
+    }
+
+    private static void assignStateFieldsForPackageItemInfo(
+            @NonNull PackageItemInfo packageItemInfo, @NonNull ParsedComponent component,
+            @Nullable PackageSetting pkgSetting) {
+        // TODO(b/135203078): Add setting related state
+    }
+
+    @CheckResult
+    private static int flag(boolean hasFlag, int flag) {
+        return hasFlag ? flag : 0;
+    }
+
+    /** @see ApplicationInfo#flags */
+    public static int appInfoFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
+        // TODO(b/135203078): Add setting related state
+        // @formatter:off
+        int flags = PackageInfoWithoutStateUtils.appInfoFlags(pkg)
+                | flag(pkg.isSystem(), ApplicationInfo.FLAG_SYSTEM)
+                | flag(pkg.isFactoryTest(), ApplicationInfo.FLAG_FACTORY_TEST);
+        if (pkgSetting != null) {
+            flags |= flag(pkgSetting.getPkgState().isUpdatedSystemApp(), ApplicationInfo.FLAG_UPDATED_SYSTEM_APP);
+        }
+        return flags;
+        // @formatter:on
+    }
+
+    /** @see ApplicationInfo#privateFlags */
+    public static int appInfoPrivateFlags(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
+        // TODO(b/135203078): Add setting related state
+        // @formatter:off
+        return PackageInfoWithoutStateUtils.appInfoPrivateFlags(pkg)
+                | flag(pkg.isSystemExt(), ApplicationInfo.PRIVATE_FLAG_SYSTEM_EXT)
+                | flag(pkg.isPrivileged(), ApplicationInfo.PRIVATE_FLAG_PRIVILEGED)
+                | flag(pkg.isOem(), ApplicationInfo.PRIVATE_FLAG_OEM)
+                | flag(pkg.isVendor(), ApplicationInfo.PRIVATE_FLAG_VENDOR)
+                | flag(pkg.isProduct(), ApplicationInfo.PRIVATE_FLAG_PRODUCT)
+                | flag(pkg.isOdm(), ApplicationInfo.PRIVATE_FLAG_ODM)
+                | flag(pkg.isSignedWithPlatformKey(), ApplicationInfo.PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY);
+        // @formatter:on
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/PackageParser2.java b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
new file mode 100644
index 0000000..f99791a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/PackageParser2.java
@@ -0,0 +1,138 @@
+/*
+ * 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.pm.parsing;
+
+import android.annotation.AnyThread;
+import android.annotation.Nullable;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageUtils;
+import android.content.pm.parsing.result.ParseInput;
+import android.content.pm.parsing.result.ParseResult;
+import android.content.pm.parsing.result.ParseTypeImpl;
+import android.content.res.TypedArray;
+import android.os.Build;
+import android.os.SystemClock;
+import android.util.DisplayMetrics;
+import android.util.Slog;
+
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
+import java.io.File;
+
+/**
+ * The v2 of {@link PackageParser} for use when parsing is initiated in the server and must
+ * contain state contained by the server.
+ */
+public class PackageParser2 {
+
+    private static final String TAG = "PackageParser2";
+
+    private static final boolean LOG_PARSE_TIMINGS = Build.IS_DEBUGGABLE;
+    private static final int LOG_PARSE_TIMINGS_THRESHOLD_MS = 100;
+
+    private ThreadLocal<ParseTypeImpl> mSharedResult = ThreadLocal.withInitial(ParseTypeImpl::new);
+
+    private final String[] mSeparateProcesses;
+    private final boolean mOnlyCoreApps;
+    private final DisplayMetrics mDisplayMetrics;
+
+    @Nullable
+    protected PackageCacher mCacher;
+
+    private ParsingPackageUtils parsingUtils;
+
+    /**
+     * @param onlyCoreApps Flag indicating this parser should only consider apps with
+     *                     {@code coreApp} manifest attribute to be valid apps. This is useful when
+     *                     creating a minimalist boot environment.
+     */
+    public PackageParser2(String[] separateProcesses, boolean onlyCoreApps,
+            DisplayMetrics displayMetrics, @Nullable File cacheDir, Callback callback) {
+        mSeparateProcesses = separateProcesses;
+        mOnlyCoreApps = onlyCoreApps;
+
+        if (displayMetrics == null) {
+            mDisplayMetrics = new DisplayMetrics();
+            mDisplayMetrics.setToDefaults();
+        } else {
+            mDisplayMetrics = displayMetrics;
+        }
+
+        mCacher = cacheDir == null ? null : new PackageCacher(cacheDir);
+        // TODO(b/135203078): Remove nullability of callback
+        callback = callback != null ? callback : new Callback() {
+            @Override
+            public boolean hasFeature(String feature) {
+                return false;
+            }
+        };
+
+        parsingUtils = new ParsingPackageUtils(onlyCoreApps, separateProcesses, displayMetrics, callback);
+    }
+
+    /**
+     * TODO(b/135203078): Document new package parsing
+     */
+    @AnyThread
+    public ParsedPackage parsePackage(File packageFile, int flags, boolean useCaches)
+            throws PackageParserException {
+        if (useCaches && mCacher != null) {
+            ParsedPackage parsed = mCacher.getCachedResult(packageFile, flags);
+            if (parsed != null) {
+                return parsed;
+            }
+        }
+
+        long parseTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
+        ParseInput input = mSharedResult.get().reset();
+        ParseResult<ParsingPackage> result = parsingUtils.parsePackage(input, packageFile, flags);
+        if (result.isError()) {
+            throw new PackageParserException(result.getErrorCode(), result.getErrorMessage(),
+                    result.getException());
+        }
+
+        ParsedPackage parsed = (ParsedPackage) result.getResult().hideAsParsed();
+
+        long cacheTime = LOG_PARSE_TIMINGS ? SystemClock.uptimeMillis() : 0;
+        if (mCacher != null) {
+            mCacher.cacheResult(packageFile, flags, parsed);
+        }
+        if (LOG_PARSE_TIMINGS) {
+            parseTime = cacheTime - parseTime;
+            cacheTime = SystemClock.uptimeMillis() - cacheTime;
+            if (parseTime + cacheTime > LOG_PARSE_TIMINGS_THRESHOLD_MS) {
+                Slog.i(TAG, "Parse times for '" + packageFile + "': parse=" + parseTime
+                        + "ms, update_cache=" + cacheTime + " ms");
+            }
+        }
+
+        return parsed;
+    }
+
+    public static abstract class Callback implements ParsingPackageUtils.Callback {
+
+        @Override
+        public final ParsingPackage startParsingPackage(String packageName, String baseCodePath,
+                String codePath, TypedArray manifestArray, boolean isCoreApp) {
+            return PackageImpl.forParsing(packageName, baseCodePath, codePath, manifestArray,
+                    isCoreApp);
+        }
+    }
+}
diff --git a/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java b/services/core/java/com/android/server/pm/parsing/library/AndroidHidlUpdater.java
similarity index 71%
rename from core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java
rename to services/core/java/com/android/server/pm/parsing/library/AndroidHidlUpdater.java
index 81b4bc5..ebb96bb 100644
--- a/core/java/android/content/pm/parsing/library/AndroidHidlUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/AndroidHidlUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -13,31 +13,33 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER;
 
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 /**
  * Updates a package to ensure that if it targets <= P that the android.hidl.base-V1.0-java
  * and android.hidl.manager-V1.0-java libraries are included by default.
  *
+ * TODO(b/135203078): See if this class can be removed, thus removing the isUpdatedSystemApp param
+ *
  * @hide
  */
 @VisibleForTesting
 public class AndroidHidlUpdater extends PackageSharedLibraryUpdater {
 
     @Override
-    public void updatePackage(ParsedPackage parsedPackage) {
+    public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
         // This was the default <= P and is maintained for backwards compatibility.
         boolean isLegacy = parsedPackage.getTargetSdkVersion() <= Build.VERSION_CODES.P;
         // Only system apps use these libraries
-        boolean isSystem = parsedPackage.isSystemApp() || parsedPackage.isUpdatedSystemApp();
+        boolean isSystem = parsedPackage.isSystem() || isUpdatedSystemApp;
 
         if (isLegacy && isSystem) {
             prefixRequiredLibrary(parsedPackage, ANDROID_HIDL_BASE);
diff --git a/core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
similarity index 87%
rename from core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java
rename to services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
index 5fbe5b9..432394a 100644
--- a/core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/AndroidTestBaseUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -13,16 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
 
 import android.compat.annotation.ChangeId;
 import android.compat.annotation.EnabledAfter;
 import android.content.Context;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -30,6 +28,8 @@
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.compat.IPlatformCompat;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 /**
  * Updates a package to ensure that if it targets <= Q that the android.test.base library is
@@ -73,7 +73,7 @@
     }
 
     @Override
-    public void updatePackage(ParsedPackage pkg) {
+    public void updatePackage(ParsedPackage pkg, boolean isUpdatedSystemApp) {
         // Packages targeted at <= Q expect the classes in the android.test.base library
         // to be accessible so this maintains backward compatibility by adding the
         // android.test.base library to those packages.
diff --git a/core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java b/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
similarity index 78%
rename from core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
rename to services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
index 613a06b..7de457e 100644
--- a/core/java/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -13,15 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 /**
  * Updates a package to ensure that if it targets < P that the org.apache.http.legacy library is
@@ -37,7 +37,7 @@
     }
 
     @Override
-    public void updatePackage(ParsedPackage parsedPackage) {
+    public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
         // Packages targeted at <= O_MR1 expect the classes in the org.apache.http.legacy library
         // to be accessible so this maintains backward compatibility by adding the
         // org.apache.http.legacy library to those packages.
diff --git a/core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
similarity index 62%
rename from core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java
rename to services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
index 1220fc4..1d018c4 100644
--- a/core/java/android/content/pm/parsing/library/PackageBackwardCompatibility.java
+++ b/services/core/java/com/android/server/pm/parsing/library/PackageBackwardCompatibility.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,21 +14,21 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
-import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
-import android.content.pm.parsing.ParsedPackage;
+import android.content.pm.PackageParser;
 import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.function.Supplier;
 
 /**
  * Modifies {@link ParsedPackage} in order to maintain backwards compatibility.
@@ -55,13 +55,7 @@
         // android.test.mock.
         packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
 
-        // Attempt to load and add the optional updater that will only be available when
-        // REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that
-        // will remove any references to org.apache.http.library from the package so that it does
-        // not try and load the library when it is on the bootclasspath.
-        boolean bootClassPathContainsATB = !addOptionalUpdater(packageUpdaters,
-                "android.content.pm.parsing.library.AndroidTestBaseUpdater",
-                RemoveUnnecessaryAndroidTestBaseLibrary::new);
+        boolean bootClassPathContainsATB = !addUpdaterForAndroidTestBase(packageUpdaters);
 
         PackageSharedLibraryUpdater[] updaterArray = packageUpdaters
                 .toArray(new PackageSharedLibraryUpdater[0]);
@@ -70,41 +64,31 @@
     }
 
     /**
-     * Add an optional {@link PackageSharedLibraryUpdater} instance to the list, if it could not be
-     * found then add a default instance instead.
+     * Attempt to load and add the optional updater that will only be available when
+     * REMOVE_ATB_FROM_BCP=true. If that could not be found then add the default updater that
+     * will remove any references to org.apache.http.library from the package so that
+     * it does not try and load the library when it is on the bootclasspath.
      *
-     * @param packageUpdaters the list to update.
-     * @param className the name of the optional class.
-     * @param defaultUpdater the supplier of the default instance.
-     * @return true if the optional updater was added false otherwise.
+     * TODO:(b/135203078): Find a better way to do this.
      */
-    private static boolean addOptionalUpdater(List<PackageSharedLibraryUpdater> packageUpdaters,
-            String className, Supplier<PackageSharedLibraryUpdater> defaultUpdater) {
-        Class<? extends PackageSharedLibraryUpdater> clazz;
+    private static boolean addUpdaterForAndroidTestBase(
+            List<PackageSharedLibraryUpdater> packageUpdaters) {
+        boolean hasClass = false;
+        String className = "android.content.pm.AndroidTestBaseUpdater";
         try {
-            clazz = (PackageBackwardCompatibility.class.getClassLoader()
-                    .loadClass(className)
-                    .asSubclass(PackageSharedLibraryUpdater.class));
+            Class clazz = (PackageParser.class.getClassLoader().loadClass(className));
+            hasClass = clazz != null;
             Log.i(TAG, "Loaded " + className);
         } catch (ClassNotFoundException e) {
             Log.i(TAG, "Could not find " + className + ", ignoring");
-            clazz = null;
         }
 
-        boolean usedOptional = false;
-        PackageSharedLibraryUpdater updater;
-        if (clazz == null) {
-            updater = defaultUpdater.get();
+        if (hasClass) {
+            packageUpdaters.add(new AndroidTestBaseUpdater());
         } else {
-            try {
-                updater = clazz.getConstructor().newInstance();
-                usedOptional = true;
-            } catch (ReflectiveOperationException e) {
-                throw new IllegalStateException("Could not create instance of " + className, e);
-            }
+            packageUpdaters.add(new RemoveUnnecessaryAndroidTestBaseLibrary());
         }
-        packageUpdaters.add(updater);
-        return usedOptional;
+        return hasClass;
     }
 
     @VisibleForTesting
@@ -129,14 +113,15 @@
      * @param parsedPackage the {@link ParsedPackage} to modify.
      */
     @VisibleForTesting
-    public static void modifySharedLibraries(ParsedPackage parsedPackage) {
-        INSTANCE.updatePackage(parsedPackage);
+    public static void modifySharedLibraries(ParsedPackage parsedPackage,
+            boolean isUpdatedSystemApp) {
+        INSTANCE.updatePackage(parsedPackage, isUpdatedSystemApp);
     }
 
     @Override
-    public void updatePackage(ParsedPackage parsedPackage) {
+    public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
         for (PackageSharedLibraryUpdater packageUpdater : mPackageUpdaters) {
-            packageUpdater.updatePackage(parsedPackage);
+            packageUpdater.updatePackage(parsedPackage, isUpdatedSystemApp);
         }
     }
 
@@ -161,7 +146,7 @@
     public static class AndroidTestRunnerSplitUpdater extends PackageSharedLibraryUpdater {
 
         @Override
-        public void updatePackage(ParsedPackage parsedPackage) {
+        public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
             // android.test.runner has a dependency on android.test.mock so if android.test.runner
             // is present but android.test.mock is not then add android.test.mock.
             prefixImplicitDependency(parsedPackage, ANDROID_TEST_RUNNER, ANDROID_TEST_MOCK);
@@ -177,7 +162,7 @@
             extends PackageSharedLibraryUpdater {
 
         @Override
-        public void updatePackage(ParsedPackage parsedPackage) {
+        public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
             removeLibrary(parsedPackage, ORG_APACHE_HTTP_LEGACY);
         }
 
@@ -192,7 +177,7 @@
             extends PackageSharedLibraryUpdater {
 
         @Override
-        public void updatePackage(ParsedPackage parsedPackage) {
+        public void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp) {
             removeLibrary(parsedPackage, ANDROID_TEST_BASE);
         }
     }
diff --git a/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java b/services/core/java/com/android/server/pm/parsing/library/PackageSharedLibraryUpdater.java
similarity index 94%
rename from core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java
rename to services/core/java/com/android/server/pm/parsing/library/PackageSharedLibraryUpdater.java
index 8b27d14..123b808 100644
--- a/core/java/android/content/pm/parsing/library/PackageSharedLibraryUpdater.java
+++ b/services/core/java/com/android/server/pm/parsing/library/PackageSharedLibraryUpdater.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -13,14 +13,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.pm.parsing.ParsedPackage;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,7 +38,7 @@
      *
      * @param parsedPackage the package to update.
      */
-    public abstract void updatePackage(ParsedPackage parsedPackage);
+    public abstract void updatePackage(ParsedPackage parsedPackage, boolean isUpdatedSystemApp);
 
     static void removeLibrary(ParsedPackage parsedPackage, String libraryName) {
         parsedPackage.removeUsesLibrary(libraryName)
diff --git a/core/java/android/content/pm/parsing/library/SharedLibraryNames.java b/services/core/java/com/android/server/pm/parsing/library/SharedLibraryNames.java
similarity index 91%
rename from core/java/android/content/pm/parsing/library/SharedLibraryNames.java
rename to services/core/java/com/android/server/pm/parsing/library/SharedLibraryNames.java
index 7b691c0..f62f014 100644
--- a/core/java/android/content/pm/parsing/library/SharedLibraryNames.java
+++ b/services/core/java/com/android/server/pm/parsing/library/SharedLibraryNames.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
 /**
  * A set of shared library names
diff --git a/core/java/android/content/pm/parsing/AndroidPackage.aidl b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.aidl
similarity index 100%
rename from core/java/android/content/pm/parsing/AndroidPackage.aidl
rename to services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.aidl
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
new file mode 100644
index 0000000..7929579
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackage.java
@@ -0,0 +1,311 @@
+/*
+ * 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.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.Intent;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageParser;
+import android.content.pm.PermissionGroupInfo;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.parsing.ParsingPackageRead;
+import android.content.pm.parsing.component.ParsedFeature;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.os.Bundle;
+import android.os.Parcelable;
+import android.util.ArraySet;
+import android.util.Pair;
+
+import com.android.internal.R;
+
+import java.security.PublicKey;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * The last state of a package during parsing/install before it is available in
+ * {@link com.android.server.pm.PackageManagerService#mPackages}.
+ *
+ * It is the responsibility of the caller to understand what data is available at what step of the
+ * parsing or install process.
+ *
+ * TODO(b/135203078): Nullability annotations
+ * TODO(b/135203078): Remove get/setAppInfo differences
+ *
+ * @hide
+ */
+public interface AndroidPackage extends PkgAppInfo, PkgPackageInfo, ParsingPackageRead, Parcelable {
+
+    /**
+     * The names of packages to adopt ownership of permissions from, parsed under
+     * {@link PackageParser#TAG_ADOPT_PERMISSIONS}.
+     * @see R.styleable#AndroidManifestOriginalPackage_name
+     */
+    @NonNull
+    List<String> getAdoptPermissions();
+
+    /** Path of base APK */
+    @NonNull
+    String getBaseCodePath();
+
+    /** Revision code of base APK */
+    int getBaseRevisionCode();
+
+    /**
+     * Path where this package was found on disk. For monolithic packages
+     * this is path to single base APK file; for cluster packages this is
+     * path to the cluster directory.
+     */
+    @NonNull
+    String getCodePath();
+
+    /**
+     * Permissions requested but not in the manifest. These may have been split or migrated from
+     * previous versions/definitions.
+     */
+    @NonNull
+    List<String> getImplicitPermissions();
+
+    /**
+     * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
+     * {@link PackageParser#TAG_KEY_SETS}.
+     * @see R.styleable#AndroidManifestKeySet
+     * @see R.styleable#AndroidManifestPublicKey
+     */
+    @NonNull
+    Map<String, ArraySet<PublicKey>> getKeySetMapping();
+
+    /**
+     * Library names this package is declared as, for use by other packages with "uses-library".
+     * @see R.styleable#AndroidManifestLibrary
+     */
+    @NonNull
+    List<String> getLibraryNames();
+
+    /**
+     * The package name as declared in the manifest, since the package can be renamed. For example,
+     * static shared libs use synthetic package names.
+     */
+    @NonNull
+    String getManifestPackageName();
+
+    /**
+     * We store the application meta-data independently to avoid multiple unwanted references
+     * TODO(b/135203078): What does this comment mean?
+     * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?)
+     */
+    @Nullable
+    Bundle getMetaData();
+
+    /**
+     * For system use to migrate from an old package name to a new one, moving over data
+     * if available.
+     * @see R.styleable#AndroidManifestOriginalPackage}
+     */
+    @NonNull
+    List<String> getOriginalPackages();
+
+    /**
+     * Map of overlayable name to actor name.
+     */
+    @NonNull
+    Map<String, String> getOverlayables();
+
+    /**
+     * The name of the package as used to identify it in the system. This may be adjusted by the
+     * system from the value declared in the manifest, and may not correspond to a Java code
+     * package.
+     * @see ApplicationInfo#packageName
+     * @see PackageInfo#packageName
+     */
+    @NonNull
+    String getPackageName();
+
+    /**
+     * @see PermissionGroupInfo
+     */
+    @NonNull
+    List<ParsedPermissionGroup> getPermissionGroups();
+
+    @NonNull
+    List<ParsedFeature> getFeatures();
+
+    /**
+     * Used to determine the default preferred handler of an {@link Intent}.
+     *
+     * Map of component className to intent info inside that component.
+     * TODO(b/135203078): Is this actually used/working?
+     */
+    @NonNull
+    List<Pair<String, ParsedIntentInfo>> getPreferredActivityFilters();
+
+    /**
+     * System protected broadcasts.
+     * @see R.styleable#AndroidManifestProtectedBroadcast
+     */
+    @NonNull
+    List<String> getProtectedBroadcasts();
+
+    /**
+     * Intents that this package may query or require and thus requires visibility into.
+     * @see R.styleable#AndroidManifestQueriesIntent
+     */
+    @NonNull
+    List<Intent> getQueriesIntents();
+
+    /**
+     * Other packages that this package may query or require and thus requires visibility into.
+     * @see R.styleable#AndroidManifestQueriesPackage
+     */
+    @NonNull
+    List<String> getQueriesPackages();
+
+    /**
+     * If a system app declares {@link #getOriginalPackages()}, and the app was previously installed
+     * under one of those original package names, the {@link #getPackageName()} system identifier
+     * will be changed to that previously installed name. This will then be non-null, set to the
+     * manifest package name, for tracking the package under its true name.
+     *
+     * TODO(b/135203078): Remove this in favor of checking originalPackages.isEmpty and
+     *  getManifestPackageName
+     */
+    @Nullable
+    String getRealPackage();
+
+    /**
+     * SHA-512 hash of the only APK that can be used to update a system package.
+     * @see R.styleable#AndroidManifestRestrictUpdate
+     */
+    @Nullable
+    byte[] getRestrictUpdateHash();
+
+    /**
+     * The signature data of all APKs in this package, which must be exactly the same across the
+     * base and splits.
+     */
+    PackageParser.SigningDetails getSigningDetails();
+
+    /**
+     * TODO(b/135203078): Move split stuff to an inner data class
+     * @see ApplicationInfo#splitNames
+     * @see PackageInfo#splitNames
+     */
+    @Nullable
+    String[] getSplitNames();
+
+    /** Flags of any split APKs; ordered by parsed splitName */
+    @Nullable
+    int[] getSplitFlags();
+
+    /** @see R.styleable#AndroidManifestStaticLibrary_name */
+    @Nullable
+    String getStaticSharedLibName();
+
+    /** @see R.styleable#AndroidManifestStaticLibrary_version */
+    long getStaticSharedLibVersion();
+
+    /**
+     * {@link android.os.storage.StorageManager#convert(String)} version of
+     * {@link #getVolumeUuid()}.
+     * TODO(b/135203078): All usages call toString() on this. Can the string be returned directly,
+     *  or does the parsing logic in StorageManager have to run?
+     */
+    UUID getStorageUuid();
+
+    /**
+     * For use with {@link com.android.server.pm.KeySetManagerService}. Parsed in
+     * {@link PackageParser#TAG_KEY_SETS}.
+     * @see R.styleable#AndroidManifestUpgradeKeySet
+     */
+    @NonNull
+    Set<String> getUpgradeKeySets();
+
+    /** @see R.styleable#AndroidManifestUsesLibrary */
+    @NonNull
+    List<String> getUsesLibraries();
+
+    /**
+     * Like {@link #getUsesLibraries()}, but marked optional by setting
+     * {@link R.styleable#AndroidManifestUsesLibrary_required} to false . Application is expected
+     * to handle absence manually.
+     * @see R.styleable#AndroidManifestUsesLibrary
+     */
+    @NonNull
+    List<String> getUsesOptionalLibraries();
+
+    /**
+     * TODO(b/135203078): Move static library stuff to an inner data class
+     * @see R.styleable#AndroidManifestUsesStaticLibrary
+     */
+    @NonNull
+    List<String> getUsesStaticLibraries();
+
+    /** @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest */
+    @Nullable
+    String[][] getUsesStaticLibrariesCertDigests();
+
+    /** @see R.styleable#AndroidManifestUsesStaticLibrary_version */
+    @Nullable
+    long[] getUsesStaticLibrariesVersions();
+
+    /** @see R.styleable#AndroidManifestApplication_forceQueryable */
+    boolean isForceQueryable();
+
+    boolean isCrossProfile();
+
+    /**
+     * The install time abi override to choose 32bit abi's when multiple abi's
+     * are present. This is only meaningfull for multiarch applications.
+     */
+    boolean isUse32BitAbi();
+
+    /**
+     * Set if the any of components are visible to instant applications.
+     * @see R.styleable#AndroidManifestActivity_visibleToInstantApps
+     * @see R.styleable#AndroidManifestProvider_visibleToInstantApps
+     * @see R.styleable#AndroidManifestService_visibleToInstantApps
+     */
+    boolean isVisibleToInstantApps();
+
+    /**
+     * Generates an {@link ApplicationInfo} object with only the data available in this object.
+     *
+     * TODO(b/135203078): Actually add this
+     * This does not contain any system or user state data, and should be avoided. Prefer
+     * com.android.server.pm.parsing.PackageInfoUtils#generateApplicationInfo(
+     * AndroidPackage, int, PackageUserState, int, com.android.server.pm.PackageSetting)
+     *
+     * @deprecated Access AndroidPackage fields directly.
+     */
+    @Deprecated
+    @NonNull
+    ApplicationInfo toAppInfoWithoutState();
+
+    /**
+     * TODO(b/135203078): Remove usages?
+     * @return a mock of what the previous package.applicationInfo would've returned for logging
+     * @deprecated don't use this in any new code, just print package name directly
+     */
+    @Deprecated
+    @NonNull
+    String toAppInfoToString();
+}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
new file mode 100644
index 0000000..780b234
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/AndroidPackageUtils.java
@@ -0,0 +1,291 @@
+/*
+ * 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.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.PackageParserException;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.VersionedPackage;
+import android.content.pm.dex.DexMetadataHelper;
+import android.content.pm.parsing.ParsingPackageRead;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+import android.text.TextUtils;
+
+import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.util.ArrayUtils;
+import com.android.server.SystemConfig;
+import com.android.server.pm.PackageSetting;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/** @hide */
+public class AndroidPackageUtils {
+
+    private AndroidPackageUtils() {
+    }
+
+    public static List<String> getAllCodePathsExcludingResourceOnly(
+            AndroidPackage aPkg) {
+        PackageImpl pkg = (PackageImpl) aPkg;
+        ArrayList<String> paths = new ArrayList<>();
+        if (pkg.isHasCode()) {
+            paths.add(pkg.getBaseCodePath());
+        }
+        String[] splitCodePaths = pkg.getSplitCodePaths();
+        if (!ArrayUtils.isEmpty(splitCodePaths)) {
+            for (int i = 0; i < splitCodePaths.length; i++) {
+                if ((pkg.getSplitFlags()[i] & ApplicationInfo.FLAG_HAS_CODE) != 0) {
+                    paths.add(splitCodePaths[i]);
+                }
+            }
+        }
+        return paths;
+    }
+
+    /**
+     * @return a list of the base and split code paths.
+     */
+    public static List<String> getAllCodePaths(AndroidPackage aPkg) {
+        PackageImpl pkg = (PackageImpl) aPkg;
+        ArrayList<String> paths = new ArrayList<>();
+        paths.add(pkg.getBaseCodePath());
+
+        String[] splitCodePaths = pkg.getSplitCodePaths();
+        if (!ArrayUtils.isEmpty(splitCodePaths)) {
+            Collections.addAll(paths, splitCodePaths);
+        }
+        return paths;
+    }
+
+    public static SharedLibraryInfo createSharedLibraryForStatic(AndroidPackage pkg) {
+        return new SharedLibraryInfo(null, pkg.getPackageName(),
+                AndroidPackageUtils.getAllCodePaths(pkg),
+                pkg.getStaticSharedLibName(),
+                pkg.getStaticSharedLibVersion(),
+                SharedLibraryInfo.TYPE_STATIC,
+                new VersionedPackage(pkg.getManifestPackageName(),
+                        pkg.getLongVersionCode()),
+                null, null);
+    }
+
+    public static SharedLibraryInfo createSharedLibraryForDynamic(AndroidPackage pkg, String name) {
+        return new SharedLibraryInfo(null, pkg.getPackageName(),
+                AndroidPackageUtils.getAllCodePaths(pkg), name,
+                SharedLibraryInfo.VERSION_UNDEFINED,
+                SharedLibraryInfo.TYPE_DYNAMIC, new VersionedPackage(pkg.getPackageName(),
+                pkg.getLongVersionCode()),
+                null, null);
+    }
+
+    /**
+     * Return the dex metadata files for the given package as a map
+     * [code path -> dex metadata path].
+     *
+     * NOTE: involves I/O checks.
+     */
+    public static Map<String, String> getPackageDexMetadata(AndroidPackage pkg) {
+        return DexMetadataHelper.buildPackageApkToDexMetadataMap
+                (AndroidPackageUtils.getAllCodePaths(pkg));
+    }
+
+    /**
+     * Validate the dex metadata files installed for the given package.
+     *
+     * @throws PackageParserException in case of errors.
+     */
+    public static void validatePackageDexMetadata(AndroidPackage pkg)
+            throws PackageParserException {
+        Collection<String> apkToDexMetadataList = getPackageDexMetadata(pkg).values();
+        for (String dexMetadata : apkToDexMetadataList) {
+            DexMetadataHelper.validateDexMetadataFile(dexMetadata);
+        }
+    }
+
+    public static NativeLibraryHelper.Handle createNativeLibraryHandle(AndroidPackage pkg)
+            throws IOException {
+        return NativeLibraryHelper.Handle.create(
+                AndroidPackageUtils.getAllCodePaths(pkg),
+                pkg.isMultiArch(),
+                pkg.isExtractNativeLibs(),
+                pkg.isDebuggable()
+        );
+    }
+
+    public static boolean canHaveOatDir(AndroidPackage pkg, boolean isUpdatedSystemApp) {
+        // The following app types CANNOT have oat directory
+        // - non-updated system apps
+        return !pkg.isSystem() || isUpdatedSystemApp;
+    }
+
+    public static boolean hasComponentClassName(AndroidPackage pkg, String className) {
+        List<ParsedActivity> activities = pkg.getActivities();
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            if (Objects.equals(className, activities.get(index).getName())) {
+                return true;
+            }
+        }
+
+        List<ParsedActivity> receivers = pkg.getReceivers();
+        int receiversSize = receivers.size();
+        for (int index = 0; index < receiversSize; index++) {
+            if (Objects.equals(className, receivers.get(index).getName())) {
+                return true;
+            }
+        }
+
+        List<ParsedProvider> providers = pkg.getProviders();
+        int providersSize = providers.size();
+        for (int index = 0; index < providersSize; index++) {
+            if (Objects.equals(className, providers.get(index).getName())) {
+                return true;
+            }
+        }
+
+        List<ParsedService> services = pkg.getServices();
+        int servicesSize = services.size();
+        for (int index = 0; index < servicesSize; index++) {
+            if (Objects.equals(className, services.get(index).getName())) {
+                return true;
+            }
+        }
+
+        List<ParsedInstrumentation> instrumentations = pkg.getInstrumentations();
+        int instrumentationsSize = instrumentations.size();
+        for (int index = 0; index < instrumentationsSize; index++) {
+            if (Objects.equals(className, instrumentations.get(index).getName())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public static boolean isEncryptionAware(AndroidPackage pkg) {
+        return pkg.isDirectBootAware() || pkg.isPartiallyDirectBootAware();
+    }
+
+    public static boolean isLibrary(AndroidPackage pkg) {
+        // TODO(b/135203078): Can parsing just enforce these always match?
+        return pkg.getStaticSharedLibName() != null || !pkg.getLibraryNames().isEmpty();
+    }
+
+    public static int getHiddenApiEnforcementPolicy(AndroidPackage pkg,
+            @NonNull PackageSetting pkgSetting) {
+        boolean isAllowedToUseHiddenApis;
+        if (pkg.isSignedWithPlatformKey()) {
+            isAllowedToUseHiddenApis = true;
+        } else if (pkg.isSystem() || pkgSetting.getPkgState().isUpdatedSystemApp()) {
+            isAllowedToUseHiddenApis = pkg.isUsesNonSdkApi()
+                    || SystemConfig.getInstance().getHiddenApiWhitelistedApps().contains(
+                    pkg.getPackageName());
+        } else {
+            isAllowedToUseHiddenApis = false;
+        }
+
+        if (isAllowedToUseHiddenApis) {
+            return ApplicationInfo.HIDDEN_API_ENFORCEMENT_DISABLED;
+        }
+
+        // TODO(b/135203078): Handle maybeUpdateHiddenApiEnforcementPolicy. Right now it's done
+        //  entirely through ApplicationInfo and shouldn't touch this specific class, but that
+        //  may not always hold true.
+//        if (mHiddenApiPolicy != ApplicationInfo.HIDDEN_API_ENFORCEMENT_DEFAULT) {
+//            return mHiddenApiPolicy;
+//        }
+        return ApplicationInfo.HIDDEN_API_ENFORCEMENT_ENABLED;
+    }
+
+    public static int getIcon(ParsingPackageRead pkg) {
+        return (PackageParser.sUseRoundIcon && pkg.getRoundIconRes() != 0)
+                ? pkg.getRoundIconRes() : pkg.getIconRes();
+    }
+
+    public static long getLongVersionCode(AndroidPackage pkg) {
+        return PackageInfo.composeLongVersionCode(pkg.getVersionCodeMajor(), pkg.getVersionCode());
+    }
+
+    public static boolean isMatchForSystemOnly(AndroidPackage pkg, int flags) {
+        if ((flags & PackageManager.MATCH_SYSTEM_ONLY) != 0) {
+            return pkg.isSystem();
+        }
+        return true;
+    }
+
+    public static String getPrimaryCpuAbi(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
+        if (pkgSetting == null || TextUtils.isEmpty(pkgSetting.primaryCpuAbiString)) {
+            return pkg.getPrimaryCpuAbi();
+        }
+
+        return pkgSetting.primaryCpuAbiString;
+    }
+
+    public static String getSecondaryCpuAbi(AndroidPackage pkg,
+            @Nullable PackageSetting pkgSetting) {
+        if (pkgSetting == null || TextUtils.isEmpty(pkgSetting.secondaryCpuAbiString)) {
+            return pkg.getSecondaryCpuAbi();
+        }
+
+        return pkgSetting.secondaryCpuAbiString;
+    }
+
+    /**
+     * Returns the primary ABI as parsed from the package. Used only during parsing and derivation.
+     * Otherwise prefer {@link #getPrimaryCpuAbi(AndroidPackage, PackageSetting)}.
+     *
+     * TODO(b/135203078): Actually hide the method
+     * Placed in the utility to hide the method on the interface.
+     */
+    public static String getRawPrimaryCpuAbi(AndroidPackage pkg) {
+        return pkg.getPrimaryCpuAbi();
+    }
+
+    /**
+     * Returns the secondary ABI as parsed from the package. Used only during parsing and
+     * derivation. Otherwise prefer {@link #getSecondaryCpuAbi(AndroidPackage, PackageSetting)}.
+     *
+     * TODO(b/135203078): Actually hide the method
+     * Placed in the utility to hide the method on the interface.
+     */
+    public static String getRawSecondaryCpuAbi(AndroidPackage pkg) {
+        return pkg.getSecondaryCpuAbi();
+    }
+
+    public static String getSeInfo(AndroidPackage pkg, @Nullable PackageSetting pkgSetting) {
+        if (pkgSetting != null) {
+            String overrideSeInfo = pkgSetting.getPkgState().getOverrideSeInfo();
+            if (!TextUtils.isEmpty(overrideSeInfo)) {
+                return overrideSeInfo;
+            }
+        }
+        return pkg.getSeInfo();
+    }
+}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
new file mode 100644
index 0000000..2b508ea
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -0,0 +1,752 @@
+/*
+ * 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.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.SharedLibraryInfo;
+import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.ParsingPackageImpl;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedMainComponent;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+import android.content.res.TypedArray;
+import android.os.Environment;
+import android.os.Parcel;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
+import android.text.TextUtils;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.util.CollectionUtils;
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Parcelling;
+import com.android.internal.util.Parcelling.BuiltIn.ForInternedString;
+import com.android.server.pm.parsing.PackageInfoUtils;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Extensions to {@link ParsingPackageImpl} including fields/state contained in the system server
+ * and not exposed to the core SDK.
+ *
+ * Many of the fields contained here will eventually be moved inside
+ * {@link com.android.server.pm.PackageSetting} or {@link android.content.pm.PackageUserState}.
+ *
+ * @hide
+ */
+public final class PackageImpl extends ParsingPackageImpl implements ParsedPackage, AndroidPackage {
+
+    public static PackageImpl forParsing(@NonNull String packageName, @NonNull String baseCodePath,
+            @NonNull String codePath, @NonNull TypedArray manifestArray, boolean isCoreApp) {
+        return new PackageImpl(packageName, baseCodePath, codePath, manifestArray, isCoreApp);
+    }
+
+    /**
+     * Mock an unavailable {@link AndroidPackage} to use when
+     * removing
+     * a package from the system.
+     * This can occur if the package was installed on a storage device that has since been removed.
+     * Since the infrastructure uses {@link AndroidPackage}, but
+     * for
+     * this case only cares about
+     * volumeUuid, just fake it rather than having separate method paths.
+     */
+    public static AndroidPackage buildFakeForDeletion(String packageName, String volumeUuid) {
+        return ((ParsedPackage) PackageImpl.forTesting(packageName)
+                .setVolumeUuid(volumeUuid)
+                .hideAsParsed())
+                .hideAsFinal();
+    }
+
+    @VisibleForTesting
+    public static ParsingPackage forTesting(String packageName) {
+        return forTesting(packageName, "");
+    }
+
+    @VisibleForTesting
+    public static ParsingPackage forTesting(String packageName, String baseCodePath) {
+        return new PackageImpl(packageName, baseCodePath, baseCodePath, null, false);
+    }
+
+    @NonNull
+    @DataClass.ParcelWith(ForInternedString.class)
+    private final String manifestPackageName;
+
+    private boolean stub;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String nativeLibraryDir;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String nativeLibraryRootDir;
+
+    private boolean nativeLibraryRootRequiresIsa;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String primaryCpuAbi;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String secondaryCpuAbi;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String secondaryNativeLibraryDir;
+
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String seInfo;
+    @Nullable
+    @DataClass.ParcelWith(ForInternedString.class)
+    protected String seInfoUser;
+
+    private boolean coreApp;
+
+    private boolean system;
+    private boolean factoryTest;
+
+    private boolean systemExt;
+    private boolean privileged;
+    private boolean oem;
+    private boolean vendor;
+    private boolean product;
+    private boolean odm;
+
+    private boolean signedWithPlatformKey;
+
+    /**
+     * This is an appId, the uid if the userId is == USER_SYSTEM
+     */
+    private int uid = -1;
+
+    @VisibleForTesting
+    public PackageImpl(@NonNull String packageName, @NonNull String baseCodePath,
+            @NonNull String codePath, @Nullable TypedArray manifestArray, boolean isCoreApp) {
+        super(packageName, baseCodePath, codePath, manifestArray);
+        this.manifestPackageName = this.packageName;
+        this.coreApp = isCoreApp;
+    }
+
+    @Override
+    public ParsedPackage hideAsParsed() {
+        return this;
+    }
+
+    @Override
+    public AndroidPackage hideAsFinal() {
+        // TODO(b/135203078): Lock as immutable
+        return this;
+    }
+
+    @Override
+    public long getLongVersionCode() {
+        return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode);
+    }
+
+    @Override
+    public PackageImpl removePermission(int index) {
+        this.permissions.remove(index);
+        return this;
+    }
+
+    @Override
+    public PackageImpl addUsesOptionalLibrary(int index, String libraryName) {
+        this.usesOptionalLibraries = CollectionUtils.add(usesOptionalLibraries, index,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public PackageImpl addUsesLibrary(int index, String libraryName) {
+        this.usesLibraries = CollectionUtils.add(usesLibraries, index,
+                TextUtils.safeIntern(libraryName));
+        return this;
+    }
+
+    @Override
+    public PackageImpl removeUsesLibrary(String libraryName) {
+        this.usesLibraries = CollectionUtils.remove(this.usesLibraries, libraryName);
+        return this;
+    }
+
+    @Override
+    public PackageImpl removeUsesOptionalLibrary(String libraryName) {
+        super.removeUsesOptionalLibrary(libraryName);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSigningDetails(@Nullable PackageParser.SigningDetails value) {
+        super.setSigningDetails(value);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setRestrictUpdateHash(@Nullable byte... value) {
+        super.setRestrictUpdateHash(value);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setRealPackage(@Nullable String realPackage) {
+        super.setRealPackage(realPackage);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setPersistent(boolean value) {
+        super.setPersistent(value);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setDefaultToDeviceProtectedStorage(boolean value) {
+        super.setDefaultToDeviceProtectedStorage(value);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setDirectBootAware(boolean value) {
+        super.setDirectBootAware(value);
+        return this;
+    }
+
+    @Override
+    public PackageImpl clearProtectedBroadcasts() {
+        protectedBroadcasts.clear();
+        return this;
+    }
+
+    @Override
+    public PackageImpl clearOriginalPackages() {
+        originalPackages.clear();
+        return this;
+    }
+
+    @Override
+    public PackageImpl clearAdoptPermissions() {
+        adoptPermissions.clear();
+        return this;
+    }
+
+    @Override
+    public PackageImpl setCodePath(@NonNull String value) {
+        this.codePath = value;
+        return this;
+    }
+
+    // TODO(b/135203078): Move PackageManagerService#renameStaticSharedLibraryPackage
+    //  into initial package parsing
+    @Override
+    public PackageImpl setPackageName(@NonNull String packageName) {
+        this.packageName = TextUtils.safeIntern(packageName);
+
+        int permissionsSize = permissions.size();
+        for (int index = 0; index < permissionsSize; index++) {
+            permissions.get(index).setPackageName(this.packageName);
+        }
+
+        int permissionGroupsSize = permissionGroups.size();
+        for (int index = 0; index < permissionGroupsSize; index++) {
+            permissionGroups.get(index).setPackageName(this.packageName);
+        }
+
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            activities.get(index).setPackageName(this.packageName);
+        }
+
+        int receiversSize = receivers.size();
+        for (int index = 0; index < receiversSize; index++) {
+            receivers.get(index).setPackageName(this.packageName);
+        }
+
+        int providersSize = providers.size();
+        for (int index = 0; index < providersSize; index++) {
+            providers.get(index).setPackageName(this.packageName);
+        }
+
+        int servicesSize = services.size();
+        for (int index = 0; index < servicesSize; index++) {
+            services.get(index).setPackageName(this.packageName);
+        }
+
+        int instrumentationsSize = instrumentations.size();
+        for (int index = 0; index < instrumentationsSize; index++) {
+            instrumentations.get(index).setPackageName(this.packageName);
+        }
+
+        return this;
+    }
+
+    @Override
+    public PackageImpl setAllComponentsDirectBootAware(boolean allComponentsDirectBootAware) {
+        int activitiesSize = activities.size();
+        for (int index = 0; index < activitiesSize; index++) {
+            activities.get(index).setDirectBootAware(allComponentsDirectBootAware);
+        }
+
+        int receiversSize = receivers.size();
+        for (int index = 0; index < receiversSize; index++) {
+            receivers.get(index).setDirectBootAware(allComponentsDirectBootAware);
+        }
+
+        int providersSize = providers.size();
+        for (int index = 0; index < providersSize; index++) {
+            providers.get(index).setDirectBootAware(allComponentsDirectBootAware);
+        }
+
+        int servicesSize = services.size();
+        for (int index = 0; index < servicesSize; index++) {
+            services.get(index).setDirectBootAware(allComponentsDirectBootAware);
+        }
+
+        return this;
+    }
+
+    @Override
+    public PackageImpl setBaseCodePath(@NonNull String baseCodePath) {
+        this.baseCodePath = TextUtils.safeIntern(baseCodePath);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setNativeLibraryDir(@Nullable String nativeLibraryDir) {
+        this.nativeLibraryDir = TextUtils.safeIntern(nativeLibraryDir);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setNativeLibraryRootDir(@Nullable String nativeLibraryRootDir) {
+        this.nativeLibraryRootDir = TextUtils.safeIntern(nativeLibraryRootDir);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setPrimaryCpuAbi(@Nullable String primaryCpuAbi) {
+        this.primaryCpuAbi = TextUtils.safeIntern(primaryCpuAbi);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSecondaryCpuAbi(@Nullable String secondaryCpuAbi) {
+        this.secondaryCpuAbi = TextUtils.safeIntern(secondaryCpuAbi);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSecondaryNativeLibraryDir(@Nullable String secondaryNativeLibraryDir) {
+        this.secondaryNativeLibraryDir = TextUtils.safeIntern(secondaryNativeLibraryDir);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSeInfo(@Nullable String seInfo) {
+        this.seInfo = TextUtils.safeIntern(seInfo);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSeInfoUser(@Nullable String seInfoUser) {
+        this.seInfoUser = TextUtils.safeIntern(seInfoUser);
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSplitCodePaths(@Nullable String[] splitCodePaths) {
+        this.splitCodePaths = splitCodePaths;
+        if (splitCodePaths != null) {
+            int size = splitCodePaths.length;
+            for (int index = 0; index < size; index++) {
+                this.splitCodePaths[index] = TextUtils.safeIntern(this.splitCodePaths[index]);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public PackageImpl capPermissionPriorities() {
+        int size = permissionGroups.size();
+        for (int index = size - 1; index >= 0; --index) {
+            // TODO(b/135203078): Builder/immutability
+            permissionGroups.get(index).setPriority(0);
+        }
+        return this;
+    }
+
+    @Override
+    public PackageImpl markNotActivitiesAsNotExportedIfSingleUser() {
+        // ignore export request for single user receivers
+        int receiversSize = receivers.size();
+        for (int index = 0; index < receiversSize; index++) {
+            ParsedActivity receiver = receivers.get(index);
+            if ((receiver.getFlags() & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                receiver.setExported(false);
+            }
+        }
+
+        // ignore export request for single user services
+        int servicesSize = services.size();
+        for (int index = 0; index < servicesSize; index++) {
+            ParsedService service = services.get(index);
+            if ((service.getFlags() & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                service.setExported(false);
+            }
+        }
+
+        // ignore export request for single user providers
+        int providersSize = providers.size();
+        for (int index = 0; index < providersSize; index++) {
+            ParsedProvider provider = providers.get(index);
+            if ((provider.getFlags() & ActivityInfo.FLAG_SINGLE_USER) != 0) {
+                provider.setExported(false);
+            }
+        }
+
+        return this;
+    }
+
+    @Override
+    public UUID getStorageUuid() {
+        return StorageManager.convert(volumeUuid);
+    }
+
+    @Deprecated
+    @Override
+    public String toAppInfoToString() {
+        return "ApplicationInfo{"
+                + Integer.toHexString(System.identityHashCode(this))
+                + " " + getPackageName() + "}";
+    }
+
+    @Override
+    public ParsedPackage setCoreApp(boolean coreApp) {
+        this.coreApp = coreApp;
+        return this;
+    }
+
+    @Override
+    public ParsedPackage setVersionCode(int versionCode) {
+        this.versionCode = versionCode;
+        return this;
+    }
+
+    @Override
+    public ParsedPackage setVersionCodeMajor(int versionCodeMajor) {
+        this.versionCodeMajor = versionCodeMajor;
+        return this;
+    }
+
+    @Override
+    public ApplicationInfo toAppInfoWithoutState() {
+        ApplicationInfo appInfo = super.toAppInfoWithoutState();
+        appInfo.flags = PackageInfoUtils.appInfoFlags(this, null);
+        appInfo.privateFlags = PackageInfoUtils.appInfoPrivateFlags(this, null);
+        appInfo.nativeLibraryDir = nativeLibraryDir;
+        appInfo.nativeLibraryRootDir = nativeLibraryRootDir;
+        appInfo.nativeLibraryRootRequiresIsa = nativeLibraryRootRequiresIsa;
+        appInfo.primaryCpuAbi = primaryCpuAbi;
+        appInfo.secondaryCpuAbi = secondaryCpuAbi;
+        appInfo.secondaryNativeLibraryDir = secondaryNativeLibraryDir;
+        appInfo.seInfo = seInfo;
+        appInfo.seInfoUser = seInfoUser;
+        appInfo.uid = uid;
+        return appInfo;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        super.writeToParcel(dest, flags);
+        sForString.parcel(this.manifestPackageName, dest, flags);
+        dest.writeBoolean(this.stub);
+        sForString.parcel(this.nativeLibraryDir, dest, flags);
+        sForString.parcel(this.nativeLibraryRootDir, dest, flags);
+        dest.writeBoolean(this.nativeLibraryRootRequiresIsa);
+        sForString.parcel(this.primaryCpuAbi, dest, flags);
+        sForString.parcel(this.secondaryCpuAbi, dest, flags);
+        sForString.parcel(this.secondaryNativeLibraryDir, dest, flags);
+        sForString.parcel(this.seInfo, dest, flags);
+        sForString.parcel(this.seInfoUser, dest, flags);
+        dest.writeInt(this.uid);
+        dest.writeBoolean(this.coreApp);
+        dest.writeBoolean(this.system);
+        dest.writeBoolean(this.factoryTest);
+        dest.writeBoolean(this.systemExt);
+        dest.writeBoolean(this.privileged);
+        dest.writeBoolean(this.oem);
+        dest.writeBoolean(this.vendor);
+        dest.writeBoolean(this.product);
+        dest.writeBoolean(this.odm);
+        dest.writeBoolean(this.signedWithPlatformKey);
+    }
+
+    public PackageImpl(Parcel in) {
+        super(in);
+        this.manifestPackageName = sForString.unparcel(in);
+        this.stub = in.readBoolean();
+        this.nativeLibraryDir = sForString.unparcel(in);
+        this.nativeLibraryRootDir = sForString.unparcel(in);
+        this.nativeLibraryRootRequiresIsa = in.readBoolean();
+        this.primaryCpuAbi = sForString.unparcel(in);
+        this.secondaryCpuAbi = sForString.unparcel(in);
+        this.secondaryNativeLibraryDir = sForString.unparcel(in);
+        this.seInfo = sForString.unparcel(in);
+        this.seInfoUser = sForString.unparcel(in);
+        this.uid = in.readInt();
+        this.coreApp = in.readBoolean();
+        this.system = in.readBoolean();
+        this.factoryTest = in.readBoolean();
+        this.systemExt = in.readBoolean();
+        this.privileged = in.readBoolean();
+        this.oem = in.readBoolean();
+        this.vendor = in.readBoolean();
+        this.product = in.readBoolean();
+        this.odm = in.readBoolean();
+        this.signedWithPlatformKey = in.readBoolean();
+    }
+
+    public static final Creator<PackageImpl> CREATOR = new Creator<PackageImpl>() {
+        @Override
+        public PackageImpl createFromParcel(Parcel source) {
+            return new PackageImpl(source);
+        }
+
+        @Override
+        public PackageImpl[] newArray(int size) {
+            return new PackageImpl[size];
+        }
+    };
+
+    @NonNull
+    @Override
+    public String getManifestPackageName() {
+        return manifestPackageName;
+    }
+
+    @DataClass.Generated.Member
+    public boolean isStub() {
+        return stub;
+    }
+
+    @Nullable
+    @Override
+    public String getNativeLibraryDir() {
+        return nativeLibraryDir;
+    }
+
+    @Nullable
+    @Override
+    public String getNativeLibraryRootDir() {
+        return nativeLibraryRootDir;
+    }
+
+    @Override
+    public boolean isNativeLibraryRootRequiresIsa() {
+        return nativeLibraryRootRequiresIsa;
+    }
+
+    @Nullable
+    @Override
+    public String getPrimaryCpuAbi() {
+        return primaryCpuAbi;
+    }
+
+    @Nullable
+    @Override
+    public String getSecondaryCpuAbi() {
+        return secondaryCpuAbi;
+    }
+
+    @Nullable
+    @Override
+    public String getSecondaryNativeLibraryDir() {
+        return secondaryNativeLibraryDir;
+    }
+
+    @Nullable
+    @Override
+    public String getSeInfo() {
+        return seInfo;
+    }
+
+    @Nullable
+    @Override
+    public String getSeInfoUser() {
+        return seInfoUser;
+    }
+
+    @Override
+    public boolean isCoreApp() {
+        return coreApp;
+    }
+
+    @Override
+    public boolean isSystem() {
+        return system;
+    }
+
+    @Override
+    public boolean isFactoryTest() {
+        return factoryTest;
+    }
+
+    @Override
+    public boolean isSystemExt() {
+        return systemExt;
+    }
+
+    @Override
+    public boolean isPrivileged() {
+        return privileged;
+    }
+
+    @Override
+    public boolean isOem() {
+        return oem;
+    }
+
+    @Override
+    public boolean isVendor() {
+        return vendor;
+    }
+
+    @Override
+    public boolean isProduct() {
+        return product;
+    }
+
+    @Override
+    public boolean isOdm() {
+        return odm;
+    }
+
+    @Override
+    public boolean isSignedWithPlatformKey() {
+        return signedWithPlatformKey;
+    }
+
+    /**
+     * This is an appId, the uid if the userId is == USER_SYSTEM
+     */
+    @Override
+    public int getUid() {
+        return uid;
+    }
+
+    @DataClass.Generated.Member
+    public PackageImpl setStub(boolean value) {
+        stub = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setNativeLibraryRootRequiresIsa(boolean value) {
+        nativeLibraryRootRequiresIsa = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSystem(boolean value) {
+        system = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setFactoryTest(boolean value) {
+        factoryTest = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSystemExt(boolean value) {
+        systemExt = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setPrivileged(boolean value) {
+        privileged = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setOem(boolean value) {
+        oem = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setVendor(boolean value) {
+        vendor = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setProduct(boolean value) {
+        product = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setOdm(boolean value) {
+        odm = value;
+        return this;
+    }
+
+    @Override
+    public PackageImpl setSignedWithPlatformKey(boolean value) {
+        signedWithPlatformKey = value;
+        return this;
+    }
+
+    /**
+     * This is an appId, the uid if the userId is == USER_SYSTEM
+     */
+    @Override
+    public PackageImpl setUid(int value) {
+        uid = value;
+        return this;
+    }
+
+    @DataClass.Generated(
+            time = 1580517688900L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java",
+            inputSignatures = "private final @android.annotation.NonNull @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String manifestPackageName\nprivate  boolean stub\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String nativeLibraryDir\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String nativeLibraryRootDir\nprivate  boolean nativeLibraryRootRequiresIsa\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String primaryCpuAbi\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String secondaryCpuAbi\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String secondaryNativeLibraryDir\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String seInfo\nprotected @android.annotation.Nullable @com.android.internal.util.DataClass.ParcelWith(com.android.internal.util.Parcelling.BuiltIn.ForInternedString.class) java.lang.String seInfoUser\nprivate  boolean system\nprivate  boolean factoryTest\nprivate  boolean systemExt\nprivate  boolean privileged\nprivate  boolean oem\nprivate  boolean vendor\nprivate  boolean product\nprivate  boolean odm\nprivate  boolean signedWithPlatformKey\nprivate  int uid\npublic static final  com.android.server.pm.parsing.pkg.Creator<com.android.server.pm.parsing.pkg.PackageImpl> CREATOR\npublic static  com.android.server.pm.parsing.pkg.PackageImpl forParsing(java.lang.String,java.lang.String,java.lang.String,android.content.res.TypedArray,boolean)\npublic static  com.android.server.pm.parsing.pkg.AndroidPackage buildFakeForDeletion(java.lang.String,java.lang.String)\npublic static @com.android.internal.annotations.VisibleForTesting android.content.pm.parsing.ParsingPackage forTesting(java.lang.String)\npublic static @com.android.internal.annotations.VisibleForTesting android.content.pm.parsing.ParsingPackage forTesting(java.lang.String,java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.ParsedPackage hideAsParsed()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.AndroidPackage hideAsFinal()\npublic @java.lang.Override long getLongVersionCode()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl removePermission(int)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl addUsesOptionalLibrary(int,java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl addUsesLibrary(int,java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl removeUsesLibrary(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl removeUsesOptionalLibrary(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSigningDetails(android.content.pm.PackageParser.SigningDetails)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setRestrictUpdateHash(byte)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setRealPackage(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setPersistent(boolean)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setDefaultToDeviceProtectedStorage(boolean)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setDirectBootAware(boolean)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl clearProtectedBroadcasts()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl clearOriginalPackages()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl clearAdoptPermissions()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setCodePath(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setPackageName(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setAllComponentsDirectBootAware(boolean)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setBaseCodePath(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setNativeLibraryDir(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setNativeLibraryRootDir(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setPrimaryCpuAbi(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSecondaryCpuAbi(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSecondaryNativeLibraryDir(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSeInfo(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSeInfoUser(java.lang.String)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl setSplitCodePaths(java.lang.String[])\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl capPermissionPriorities()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.PackageImpl markNotActivitiesAsNotExportedIfSingleUser()\npublic @java.lang.Override java.util.UUID getStorageUuid()\npublic @java.lang.Deprecated @java.lang.Override java.lang.String toAppInfoToString()\npublic @java.lang.Override com.android.server.pm.parsing.pkg.ParsedPackage setCoreApp(boolean)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.ParsedPackage setVersionCode(int)\npublic @java.lang.Override com.android.server.pm.parsing.pkg.ParsedPackage setVersionCodeMajor(int)\npublic @java.lang.Override android.content.pm.ApplicationInfo toAppInfoWithoutState()\npublic @java.lang.Override int describeContents()\npublic @java.lang.Override void writeToParcel(android.os.Parcel,int)\nclass PackageImpl extends android.content.pm.parsing.ParsingPackageImpl implements [com.android.server.pm.parsing.pkg.ParsedPackage, com.android.server.pm.parsing.pkg.AndroidPackage]\n@com.android.internal.util.DataClass(genConstructor=false, genParcelable=false, genAidl=false, genBuilder=false, genHiddenConstructor=false, genCopyConstructor=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/core/java/android/content/pm/parsing/ParsedPackage.java b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
similarity index 71%
rename from core/java/android/content/pm/parsing/ParsedPackage.java
rename to services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
index 05cf586..2660f2b 100644
--- a/core/java/android/content/pm/parsing/ParsedPackage.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/ParsedPackage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,8 +14,9 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing;
+package com.android.server.pm.parsing.pkg;
 
+import android.annotation.Nullable;
 import android.content.pm.PackageParser;
 
 /**
@@ -42,26 +43,10 @@
 
     ParsedPackage clearProtectedBroadcasts();
 
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #setCodePath(String)}
-     */
-    @Deprecated
-    ParsedPackage setApplicationInfoCodePath(String applicationInfoCodePath);
-
-    /**
-     * TODO(b/135203078): Use non-AppInfo method
-     * @deprecated use {@link #setCodePath(String)}
-     */
-    @Deprecated
-    ParsedPackage setApplicationInfoResourcePath(String applicationInfoResourcePath);
-
     ParsedPackage setBaseCodePath(String baseCodePath);
 
     ParsedPackage setCodePath(String codePath);
 
-    ParsedPackage setCpuAbiOverride(String cpuAbiOverride);
-
     ParsedPackage setNativeLibraryDir(String nativeLibraryDir);
 
     ParsedPackage setNativeLibraryRootDir(String nativeLibraryRootDir);
@@ -70,9 +55,7 @@
 
     ParsedPackage setPrimaryCpuAbi(String primaryCpuAbi);
 
-    ParsedPackage setProcessName(String processName);
-
-    ParsedPackage setRealPackage(String realPackage);
+    ParsedPackage setRealPackage(@Nullable String realPackage);
 
     ParsedPackage setSecondaryCpuAbi(String secondaryCpuAbi);
 
@@ -80,8 +63,6 @@
 
     ParsedPackage setSplitCodePaths(String[] splitCodePaths);
 
-    ParsedPackage initForUser(int userId);
-
     ParsedPackage setNativeLibraryRootRequiresIsa(boolean nativeLibraryRootRequiresIsa);
 
     ParsedPackage setAllComponentsDirectBootAware(boolean allComponentsDirectBootAware);
@@ -104,8 +85,6 @@
 
     ParsedPackage setSystemExt(boolean systemExt);
 
-    ParsedPackage setUpdatedSystemApp(boolean updatedSystemApp);
-
     ParsedPackage setVendor(boolean vendor);
 
     ParsedPackage removePermission(int index);
@@ -114,19 +93,9 @@
 
     ParsedPackage removeUsesOptionalLibrary(String libraryName);
 
-    ParsedPackage setApplicationInfoBaseResourcePath(String applicationInfoBaseResourcePath);
-
-    ParsedPackage setApplicationInfoSplitResourcePaths(
-            String[] applicationInfoSplitResourcePaths);
-
-    ParsedPackage setApplicationVolumeUuid(String applicationVolumeUuid);
-
     ParsedPackage setCoreApp(boolean coreApp);
 
-    ParsedPackage setIsStub(boolean isStub);
-
-    // TODO(b/135203078): Remove entirely
-    ParsedPackage setPackageSettingCallback(PackageSettingCallback packageSettingCallback);
+    ParsedPackage setStub(boolean isStub);
 
     ParsedPackage setRestrictUpdateHash(byte[] restrictUpdateHash);
 
@@ -148,8 +117,4 @@
     ParsedPackage setDirectBootAware(boolean directBootAware);
 
     ParsedPackage setPersistent(boolean persistent);
-
-    interface PackageSettingCallback {
-        default void setAndroidPackage(AndroidPackage pkg){}
-    }
 }
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java b/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java
new file mode 100644
index 0000000..0cb425f
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PkgAppInfo.java
@@ -0,0 +1,493 @@
+/*
+ * 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.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ApplicationInfo;
+import android.util.SparseArray;
+
+import com.android.internal.R;
+
+/**
+ * Container for fields that are eventually exposed through {@link ApplicationInfo}.
+ *
+ * Done to separate the meaningless, re-directed JavaDoc for methods and to separate what's
+ * exposed vs not exposed to core.
+ *
+ * @hide
+ */
+interface PkgAppInfo {
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE */
+    boolean isCantSaveState();
+
+    /**
+     * @see ApplicationInfo#appComponentFactory
+     * @see R.styleable#AndroidManifestApplication_appComponentFactory
+     */
+    @Nullable
+    String getAppComponentFactory();
+
+    /**
+     * @see ApplicationInfo#backupAgentName
+     * @see R.styleable#AndroidManifestApplication_backupAgent
+     */
+    @Nullable
+    String getBackupAgentName();
+
+    /**
+     * @see ApplicationInfo#banner
+     * @see R.styleable#AndroidManifestApplication_banner
+     */
+    int getBanner();
+
+    /**
+     * @see ApplicationInfo#category
+     * @see R.styleable#AndroidManifestApplication_appCategory
+     */
+    int getCategory();
+
+    /**
+     * @see ApplicationInfo#classLoaderName
+     * @see R.styleable#AndroidManifestApplication_classLoader
+     */
+    @Nullable
+    String getClassLoaderName();
+
+    /**
+     * @see ApplicationInfo#className
+     * @see R.styleable#AndroidManifestApplication_name
+     */
+    @Nullable
+    String getClassName();
+
+    /**
+     * @see ApplicationInfo#compatibleWidthLimitDp
+     * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp
+     */
+    int getCompatibleWidthLimitDp();
+
+    /**
+     * @see ApplicationInfo#compileSdkVersion
+     * @see R.styleable#AndroidManifest_compileSdkVersion
+     */
+    int getCompileSdkVersion();
+
+    /**
+     * @see ApplicationInfo#compileSdkVersionCodename
+     * @see R.styleable#AndroidManifest_compileSdkVersionCodename
+     */
+    @Nullable
+    String getCompileSdkVersionCodeName();
+
+    /**
+     * @see ApplicationInfo#descriptionRes
+     * @see R.styleable#AndroidManifestApplication_description
+     */
+    int getDescriptionRes();
+
+    /**
+     * @see ApplicationInfo#fullBackupContent
+     * @see R.styleable#AndroidManifestApplication_fullBackupContent
+     */
+    int getFullBackupContent();
+
+    /**
+     * @see ApplicationInfo#iconRes
+     * @see R.styleable#AndroidManifestApplication_icon
+     */
+    int getIconRes();
+
+    /**
+     * @see ApplicationInfo#labelRes
+     * @see R.styleable#AndroidManifestApplication_label
+     */
+    int getLabelRes();
+
+    /**
+     * @see ApplicationInfo#largestWidthLimitDp
+     * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp
+     */
+    int getLargestWidthLimitDp();
+
+    /**
+     * @see ApplicationInfo#logo
+     * @see R.styleable#AndroidManifestApplication_logo
+     */
+    int getLogo();
+
+    /**
+     * @see ApplicationInfo#manageSpaceActivityName
+     * @see R.styleable#AndroidManifestApplication_manageSpaceActivity
+     */
+    @Nullable
+    String getManageSpaceActivityName();
+
+    /**
+     * @see ApplicationInfo#maxAspectRatio
+     * @see R.styleable#AndroidManifestApplication_maxAspectRatio
+     */
+    float getMaxAspectRatio();
+
+    /**
+     * @see ApplicationInfo#minAspectRatio
+     * @see R.styleable#AndroidManifestApplication_minAspectRatio
+     */
+    float getMinAspectRatio();
+
+    /**
+     * @see ApplicationInfo#minSdkVersion
+     * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion
+     */
+    int getMinSdkVersion();
+
+    /** @see ApplicationInfo#nativeLibraryDir */
+    @Nullable
+    String getNativeLibraryDir();
+
+    /** @see ApplicationInfo#nativeLibraryRootDir */
+    @Nullable
+    String getNativeLibraryRootDir();
+
+    /**
+     * @see ApplicationInfo#networkSecurityConfigRes
+     * @see R.styleable#AndroidManifestApplication_networkSecurityConfig
+     */
+    int getNetworkSecurityConfigRes();
+
+    /**
+     * If {@link R.styleable#AndroidManifestApplication_label} is a string literal, this is it.
+     * Otherwise, it's stored as {@link #getLabelRes()}.
+     * @see ApplicationInfo#nonLocalizedLabel
+     * @see R.styleable#AndroidManifestApplication_label
+     */
+    @Nullable
+    CharSequence getNonLocalizedLabel();
+
+    /**
+     * @see ApplicationInfo#permission
+     * @see R.styleable#AndroidManifestApplication_permission
+     */
+    @Nullable
+    String getPermission();
+
+    /**
+     * TODO(b/135203078): Hide this in the utility, should never be accessed directly
+     * @see ApplicationInfo#primaryCpuAbi
+     */
+    @Nullable
+    String getPrimaryCpuAbi();
+
+    /**
+     * @see ApplicationInfo#processName
+     * @see R.styleable#AndroidManifestApplication_process
+     */
+    @NonNull
+    String getProcessName();
+
+    /**
+     * @see ApplicationInfo#requiresSmallestWidthDp
+     * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp
+     */
+    int getRequiresSmallestWidthDp();
+
+    /**
+     * @see ApplicationInfo#roundIconRes
+     * @see R.styleable#AndroidManifestApplication_roundIcon
+     */
+    int getRoundIconRes();
+
+    /** @see ApplicationInfo#seInfo */
+    @Nullable
+    String getSeInfo();
+
+    /** @see ApplicationInfo#seInfoUser */
+    @Nullable
+    String getSeInfoUser();
+
+    /** @see ApplicationInfo#secondaryCpuAbi */
+    @Nullable
+    String getSecondaryCpuAbi();
+
+    /** @see ApplicationInfo#secondaryNativeLibraryDir */
+    @Nullable
+    String getSecondaryNativeLibraryDir();
+
+    /**
+     * @see ApplicationInfo#installLocation
+     * @see R.styleable#AndroidManifest_installLocation
+     */
+    int getInstallLocation();
+
+    /**
+     * @see ApplicationInfo#splitClassLoaderNames
+     * @see R.styleable#AndroidManifestApplication_classLoader
+     */
+    @Nullable
+    String[] getSplitClassLoaderNames();
+
+    /** @see ApplicationInfo#splitSourceDirs */
+    @Nullable
+    String[] getSplitCodePaths();
+
+    /** @see ApplicationInfo#splitDependencies */
+    @Nullable
+    SparseArray<int[]> getSplitDependencies();
+
+    /**
+     * @see ApplicationInfo#targetSandboxVersion
+     * @see R.styleable#AndroidManifest_targetSandboxVersion
+     */
+    @Deprecated
+    int getTargetSandboxVersion();
+
+    /**
+     * @see ApplicationInfo#targetSdkVersion
+     * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion
+     */
+    int getTargetSdkVersion();
+
+    /**
+     * @see ApplicationInfo#taskAffinity
+     * @see R.styleable#AndroidManifestApplication_taskAffinity
+     */
+    @Nullable
+    String getTaskAffinity();
+
+    /**
+     * @see ApplicationInfo#theme
+     * @see R.styleable#AndroidManifestApplication_theme
+     */
+    int getTheme();
+
+    /**
+     * @see ApplicationInfo#uiOptions
+     * @see R.styleable#AndroidManifestApplication_uiOptions
+     */
+    int getUiOptions();
+
+    /** @see ApplicationInfo#uid */
+    int getUid();
+
+    /** @see ApplicationInfo#longVersionCode */
+    long getLongVersionCode();
+
+    /** @see ApplicationInfo#versionCode */
+    @Deprecated
+    int getVersionCode();
+
+    /** @see ApplicationInfo#volumeUuid */
+    @Nullable
+    String getVolumeUuid();
+
+    /** @see ApplicationInfo#zygotePreloadName */
+    @Nullable
+    String getZygotePreloadName();
+
+    /** @see ApplicationInfo#FLAG_HAS_CODE */
+    boolean isHasCode();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING */
+    boolean isAllowTaskReparenting();
+
+    /** @see ApplicationInfo#FLAG_MULTIARCH */
+    boolean isMultiArch();
+
+    /** @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS */
+    boolean isExtractNativeLibs();
+
+    /** @see ApplicationInfo#FLAG_DEBUGGABLE */
+    boolean isDebuggable();
+
+    /** @see ApplicationInfo#FLAG_VM_SAFE_MODE */
+    boolean isVmSafeMode();
+
+    /** @see ApplicationInfo#FLAG_PERSISTENT */
+    boolean isPersistent();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_BACKUP */
+    boolean isAllowBackup();
+
+    /** @see ApplicationInfo#FLAG_TEST_ONLY */
+    boolean isTestOnly();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION */
+    boolean isResizeableActivityViaSdkVersion();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS */
+    boolean isHasDomainUrls();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE */
+    boolean isRequestLegacyExternalStorage();
+
+    /** @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED */
+    boolean isBaseHardwareAccelerated();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE */
+    boolean isDefaultToDeviceProtectedStorage();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE */
+    boolean isDirectBootAware();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE */
+    boolean isPartiallyDirectBootAware();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX */
+    boolean isUseEmbeddedDex();
+
+    /** @see ApplicationInfo#FLAG_EXTERNAL_STORAGE */
+    boolean isExternalStorage();
+
+    /** @see ApplicationInfo#nativeLibraryRootRequiresIsa */
+    boolean isNativeLibraryRootRequiresIsa();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ODM */
+    boolean isOdm();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_OEM */
+    boolean isOem();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PRIVILEGED */
+    boolean isPrivileged();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PRODUCT */
+    boolean isProduct();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL */
+    boolean isProfileableByShell();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY */
+    boolean isStaticSharedLibrary();
+
+    /** @see ApplicationInfo#FLAG_SYSTEM */
+    boolean isSystem();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_SYSTEM_EXT */
+    boolean isSystemExt();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_VENDOR */
+    boolean isVendor();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING */
+    boolean isIsolatedSplitLoading();
+
+    /**
+     * @see ApplicationInfo#enabled
+     * @see R.styleable#AndroidManifestApplication_enabled
+     */
+    boolean isEnabled();
+
+    /**
+     * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY
+     * @see ApplicationInfo#isResourceOverlay()
+     */
+    boolean isOverlay();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API */
+    boolean isUsesNonSdkApi();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY */
+    boolean isSignedWithPlatformKey();
+
+    /** @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE */
+    boolean isKillAfterRestore();
+
+    /** @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION */
+    boolean isRestoreAnyVersion();
+
+    /** @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY */
+    boolean isFullBackupOnly();
+
+    /** @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA */
+    boolean isAllowClearUserData();
+
+    /** @see ApplicationInfo#FLAG_LARGE_HEAP */
+    boolean isLargeHeap();
+
+    /** @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC */
+    boolean isUsesCleartextTraffic();
+
+    /** @see ApplicationInfo#FLAG_SUPPORTS_RTL */
+    boolean isSupportsRtl();
+
+    /** @see ApplicationInfo#FLAG_IS_GAME */
+    @Deprecated
+    boolean isGame();
+
+    /** @see ApplicationInfo#FLAG_FACTORY_TEST */
+    boolean isFactoryTest();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_smallScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS
+     */
+    boolean isSupportsSmallScreens();
+
+    /**
+     * If omitted from manifest, returns true.
+     * @see R.styleable#AndroidManifestSupportsScreens_normalScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS
+     */
+    boolean isSupportsNormalScreens();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_largeScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS
+     */
+    boolean isSupportsLargeScreens();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#GINGERBREAD}.
+     * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens
+     * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS
+     */
+    boolean isSupportsExtraLargeScreens();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_resizeable
+     * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS
+     */
+    boolean isResizeable();
+
+    /**
+     * If omitted from manifest, returns true if {@link #getTargetSdkVersion()} >=
+     * {@link android.os.Build.VERSION_CODES#DONUT}.
+     * @see R.styleable#AndroidManifestSupportsScreens_anyDensity
+     * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES
+     */
+    boolean isAnyDensity();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND */
+    boolean isBackupInForeground();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE */
+    boolean isAllowClearUserDataOnFailedRestore();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE */
+    boolean isAllowAudioPlaybackCapture();
+
+    /** @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA */
+    boolean isHasFragileUserData();
+}
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java b/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java
new file mode 100644
index 0000000..89330a9
--- /dev/null
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PkgPackageInfo.java
@@ -0,0 +1,225 @@
+/*
+ * 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.pm.parsing.pkg;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ConfigurationInfo;
+import android.content.pm.FeatureGroupInfo;
+import android.content.pm.FeatureInfo;
+import android.content.pm.InstrumentationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PermissionInfo;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
+
+import com.android.internal.R;
+
+import java.util.List;
+
+/**
+ * Container for fields that are eventually exposed through {@link PackageInfo}.
+ *
+ * Done to separate the meaningless, re-directed JavaDoc for methods and to separate what's
+ * exposed vs not exposed to core.
+ *
+ * @hide
+ */
+interface PkgPackageInfo {
+
+    /**
+     * @see PackageInfo#overlayCategory
+     * @see R.styleable#AndroidManifestResourceOverlay_category
+     */
+    @Nullable
+    String getOverlayCategory();
+
+    /**
+     * @see PackageInfo#overlayPriority
+     * @see R.styleable#AndroidManifestResourceOverlay_priority
+     */
+    int getOverlayPriority();
+
+    /**
+     * @see PackageInfo#overlayTarget
+     * @see R.styleable#AndroidManifestResourceOverlay_targetPackage
+     */
+    @Nullable
+    String getOverlayTarget();
+
+    /**
+     * @see PackageInfo#targetOverlayableName
+     * @see R.styleable#AndroidManifestResourceOverlay_targetName
+     */
+    @Nullable
+    String getOverlayTargetName();
+
+    /**
+     * @see PackageInfo#sharedUserId
+     * @see R.styleable#AndroidManifest_sharedUserId
+     */
+    @Deprecated
+    @Nullable
+    String getSharedUserId();
+
+    /**
+     * @see PackageInfo#sharedUserLabel
+     * @see R.styleable#AndroidManifest_sharedUserLabel
+     */
+    @Deprecated
+    int getSharedUserLabel();
+
+    /**
+     * The required account type without which this application will not function.
+     *
+     * @see PackageInfo#requiredAccountType
+     * @see R.styleable#AndroidManifestApplication_requiredAccountType
+     */
+    @Nullable
+    String getRequiredAccountType();
+
+    /**
+     * The restricted account authenticator type that is used by this application
+     *
+     * @see PackageInfo#restrictedAccountType
+     * @see R.styleable#AndroidManifestApplication_restrictedAccountType
+     */
+    @Nullable
+    String getRestrictedAccountType();
+
+    /** @see PackageInfo#splitRevisionCodes */
+    int[] getSplitRevisionCodes();
+
+    /** @see PackageInfo#getLongVersionCode() */
+    long getLongVersionCode();
+
+    /** @see PackageInfo#versionCode */
+    @Deprecated
+    int getVersionCode();
+
+    /** @see PackageInfo#versionCodeMajor */
+    int getVersionCodeMajor();
+
+    /** @see PackageInfo#versionName */
+    @Nullable
+    String getVersionName();
+
+    /** @see PackageInfo#mOverlayIsStatic */
+    boolean isOverlayIsStatic();
+
+    /**
+     * @see PackageInfo#requiredForAllUsers
+     * @see R.styleable#AndroidManifestApplication_requiredForAllUsers
+     */
+    boolean isRequiredForAllUsers();
+
+    /**
+     * @see PackageInfo#reqFeatures
+     * @see R.styleable#AndroidManifestUsesFeature
+     */
+    @NonNull
+    List<FeatureInfo> getReqFeatures();
+
+    /**
+     * @see PackageInfo#configPreferences
+     * @see R.styleable#AndroidManifestUsesConfiguration
+     */
+    @NonNull
+    List<ConfigurationInfo> getConfigPreferences();
+
+    /**
+     * @see PackageInfo#featureGroups
+     * @see R.styleable#AndroidManifestUsesFeature
+     */
+    @NonNull
+    List<FeatureGroupInfo> getFeatureGroups();
+
+    /**
+     * Whether or not the package is a stub and must be replaced by the full version.
+     *
+     * @see PackageInfo#isStub
+     */
+    boolean isStub();
+
+    /**
+     * For marking packages required for a minimal boot state, through the "coreApp" manifest
+     * attribute.
+     * @see PackageInfo#coreApp
+     */
+    boolean isCoreApp();
+
+    /**
+     * All the permissions declared. This is an effective set, and may include permissions
+     * transformed from split/migrated permissions from previous versions, so may not be exactly
+     * what the package declares in its manifest.
+     * @see PackageInfo#requestedPermissions
+     * @see R.styleable#AndroidManifestUsesPermission
+     */
+    @NonNull
+    List<String> getRequestedPermissions();
+
+    /**
+     * @see ActivityInfo
+     * @see PackageInfo#activities
+     */
+    @NonNull
+    List<ParsedActivity> getActivities();
+
+    /**
+     * @see InstrumentationInfo
+     * @see PackageInfo#instrumentation
+     */
+    @NonNull
+    List<ParsedInstrumentation> getInstrumentations();
+
+    /**
+     * @see PermissionInfo
+     * @see PackageInfo#permissions
+     */
+    @NonNull
+    List<ParsedPermission> getPermissions();
+
+    /**
+     * @see ProviderInfo
+     * @see PackageInfo#providers
+     */
+    @NonNull
+    List<ParsedProvider> getProviders();
+
+    /**
+     * Since they share several attributes, receivers are parsed as {@link ParsedActivity}, even
+     * though they represent different functionality.
+     * TODO(b/135203078): Reconsider this and maybe make ParsedReceiver so it's not so confusing
+     * @see ActivityInfo
+     * @see PackageInfo#receivers
+     */
+    @NonNull
+    List<ParsedActivity> getReceivers();
+
+    /**
+     * @see ServiceInfo
+     * @see PackageInfo#services
+     */
+    @NonNull
+    List<ParsedService> getServices();
+}
diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java
index e323c98..f8e5082 100644
--- a/services/core/java/com/android/server/pm/permission/BasePermission.java
+++ b/services/core/java/com/android/server/pm/permission/BasePermission.java
@@ -32,9 +32,7 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PermissionInfo;
 import android.content.pm.Signature;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.PackageInfoUtils;
+import android.content.pm.parsing.component.ParsedPermission;
 import android.os.UserHandle;
 import android.util.Log;
 import android.util.Slog;
@@ -43,6 +41,8 @@
 import com.android.server.pm.PackageManagerService;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.PackageSettingBase;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
@@ -172,12 +172,12 @@
         return 0;
     }
 
-    public boolean isPermission(@NonNull ParsedPermission perm) {
+    public boolean isPermission(ParsedPermission perm) {
         if (this.perm == null) {
             return false;
         }
         return Objects.equals(this.perm.getPackageName(), perm.getPackageName())
-                && Objects.equals(this.perm.className, perm.className);
+                && Objects.equals(this.perm.getName(), perm.getName());
     }
 
     public boolean isDynamic() {
@@ -195,24 +195,24 @@
     }
 
     public boolean isRemoved() {
-        return perm != null && (perm.flags & PermissionInfo.FLAG_REMOVED) != 0;
+        return perm != null && (perm.getFlags() & PermissionInfo.FLAG_REMOVED) != 0;
     }
 
     public boolean isSoftRestricted() {
-        return perm != null && (perm.flags & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0;
+        return perm != null && (perm.getFlags() & PermissionInfo.FLAG_SOFT_RESTRICTED) != 0;
     }
 
     public boolean isHardRestricted() {
-        return perm != null && (perm.flags & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
+        return perm != null && (perm.getFlags() & PermissionInfo.FLAG_HARD_RESTRICTED) != 0;
     }
 
     public boolean isHardOrSoftRestricted() {
-        return perm != null && (perm.flags & (PermissionInfo.FLAG_HARD_RESTRICTED
+        return perm != null && (perm.getFlags() & (PermissionInfo.FLAG_HARD_RESTRICTED
                 | PermissionInfo.FLAG_SOFT_RESTRICTED)) != 0;
     }
 
     public boolean isImmutablyRestricted() {
-        return perm != null && (perm.flags & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
+        return perm != null && (perm.getFlags() & PermissionInfo.FLAG_IMMUTABLY_RESTRICTED) != 0;
     }
 
     public boolean isSignature() {
@@ -326,15 +326,8 @@
             final BasePermission tree = findPermissionTree(permissionTrees, name);
             if (tree != null && tree.perm != null) {
                 sourcePackageSetting = tree.sourcePackageSetting;
-                perm = new ParsedPermission(tree.perm);
-                perm.protectionLevel = pendingPermissionInfo.protectionLevel;
-                perm.flags = pendingPermissionInfo.flags;
-                perm.setGroup(pendingPermissionInfo.group);
-                perm.backgroundPermission = pendingPermissionInfo.backgroundPermission;
-                perm.descriptionRes = pendingPermissionInfo.descriptionRes;
-                perm.requestRes = pendingPermissionInfo.requestRes;
-                perm.setPackageName(tree.perm.getPackageName());
-                perm.setName(name);
+                perm = new ParsedPermission(tree.perm, pendingPermissionInfo,
+                        tree.perm.getPackageName(), name);
                 uid = tree.uid;
             }
         }
@@ -364,7 +357,7 @@
             if (pkg.isSystem()) {
                 if (bp.type == BasePermission.TYPE_BUILTIN && bp.perm == null) {
                     // It's a built-in permission and no owner, take ownership now
-                    p.flags |= PermissionInfo.FLAG_INSTALLED;
+                    p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
                     bp.sourcePackageSetting = pkgSetting;
                     bp.perm = p;
                     bp.uid = pkg.getUid();
@@ -387,7 +380,7 @@
                 final BasePermission tree = findPermissionTree(permissionTrees, p.getName());
                 if (tree == null
                         || tree.sourcePackageName.equals(p.getPackageName())) {
-                    p.flags |= PermissionInfo.FLAG_INSTALLED;
+                    p.setFlags(p.getFlags() | PermissionInfo.FLAG_INSTALLED);
                     bp.sourcePackageSetting = pkgSetting;
                     bp.perm = p;
                     bp.uid = pkg.getUid();
@@ -421,8 +414,8 @@
             r.append(p.getName());
         }
         if (bp.perm != null && Objects.equals(bp.perm.getPackageName(), p.getPackageName())
-                && Objects.equals(bp.perm.className, p.className)) {
-            bp.protectionLevel = p.protectionLevel;
+                && Objects.equals(bp.perm.getName(), p.getName())) {
+            bp.protectionLevel = p.getProtectionLevel();
         }
         if (PackageManagerService.DEBUG_PACKAGE_SCANNING && r != null) {
             Log.d(TAG, "  Permissions: " + r);
@@ -572,9 +565,9 @@
         if (type == BasePermission.TYPE_DYNAMIC) {
             if (perm != null || pendingPermissionInfo != null) {
                 serializer.attribute(null, "type", "dynamic");
-                int icon = perm != null ? perm.icon : pendingPermissionInfo.icon;
+                int icon = perm != null ? perm.getIcon() : pendingPermissionInfo.icon;
                 CharSequence nonLocalizedLabel = perm != null
-                        ? perm.nonLocalizedLabel
+                        ? perm.getNonLocalizedLabel()
                         : pendingPermissionInfo.nonLocalizedLabel;
 
                 if (icon != 0) {
@@ -602,11 +595,11 @@
     }
 
     private static boolean comparePermissionInfos(ParsedPermission pi1, PermissionInfo pi2) {
-        if (pi1.icon != pi2.icon) return false;
-        if (pi1.logo != pi2.logo) return false;
-        if (pi1.protectionLevel != pi2.protectionLevel) return false;
+        if (pi1.getIcon() != pi2.icon) return false;
+        if (pi1.getLogo() != pi2.logo) return false;
+        if (pi1.getProtectionLevel() != pi2.protectionLevel) return false;
         if (!compareStrings(pi1.getName(), pi2.name)) return false;
-        if (!compareStrings(pi1.nonLocalizedLabel, pi2.nonLocalizedLabel)) return false;
+        if (!compareStrings(pi1.getNonLocalizedLabel(), pi2.nonLocalizedLabel)) return false;
         // We'll take care of setting this one.
         if (!compareStrings(pi1.getPackageName(), pi2.packageName)) return false;
         // These are not currently stored in settings.
@@ -644,9 +637,9 @@
                 pw.println(PermissionInfo.protectionToString(protectionLevel));
         if (perm != null) {
             pw.print("    perm="); pw.println(perm);
-            if ((perm.flags & PermissionInfo.FLAG_INSTALLED) == 0
-                    || (perm.flags & PermissionInfo.FLAG_REMOVED) != 0) {
-                pw.print("    flags=0x"); pw.println(Integer.toHexString(perm.flags));
+            if ((perm.getFlags() & PermissionInfo.FLAG_INSTALLED) == 0
+                    || (perm.getFlags() & PermissionInfo.FLAG_REMOVED) != 0) {
+                pw.print("    flags=0x"); pw.println(Integer.toHexString(perm.getFlags()));
             }
         }
         if (sourcePackageSetting != null) {
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index e6eaf21..9c945d5 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -150,6 +150,12 @@
         ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION);
     }
 
+    private static final Set<String> FOREGROUND_LOCATION_PERMISSIONS = new ArraySet<>();
+    static {
+        ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_FINE_LOCATION);
+        ALWAYS_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
+    }
+
     private static final Set<String> COARSE_BACKGROUND_LOCATION_PERMISSIONS = new ArraySet<>();
     static {
         COARSE_BACKGROUND_LOCATION_PERMISSIONS.add(Manifest.permission.ACCESS_COARSE_LOCATION);
@@ -587,11 +593,6 @@
                         DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE, userId),
                 userId, CONTACTS_PERMISSIONS);
 
-        // Maps
-        grantPermissionsToSystemPackage(
-                getDefaultSystemHandlerActivityPackageForCategory(Intent.CATEGORY_APP_MAPS, userId),
-                userId, ALWAYS_LOCATION_PERMISSIONS);
-
         // Email
         grantPermissionsToSystemPackage(
                 getDefaultSystemHandlerActivityPackageForCategory(
@@ -609,7 +610,7 @@
             }
         }
         grantPermissionsToPackage(browserPackage, userId, false /* ignoreSystemPackage */,
-                true /*whitelistRestrictedPermissions*/, ALWAYS_LOCATION_PERMISSIONS);
+                true /*whitelistRestrictedPermissions*/, FOREGROUND_LOCATION_PERMISSIONS);
 
         // Voice interaction
         if (voiceInteractPackageNames != null) {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 36697f9..980aaed 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -71,10 +71,8 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.content.pm.parsing.PackageInfoUtils;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
 import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.metrics.LogMaker;
 import android.os.Binder;
@@ -129,6 +127,8 @@
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.SharedUserSetting;
 import com.android.server.pm.UserManagerService;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultBrowserProvider;
 import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultDialerProvider;
 import com.android.server.pm.permission.PermissionManagerServiceInternal.DefaultHomeProvider;
@@ -1282,7 +1282,7 @@
         }
 
         if (bp.isSoftRestricted() && !SoftRestrictedPermissionPolicy.forPermission(mContext,
-                pkg.toAppInfoWithoutState(), UserHandle.of(userId), permName)
+                pkg.toAppInfoWithoutState(), pkg, UserHandle.of(userId), permName)
                 .mayGrantPermission()) {
             Log.e(TAG, "Cannot grant soft restricted permission " + permName + " for package "
                     + packageName);
@@ -2082,9 +2082,9 @@
         for (int i = 0; i < numOldPackagePermissions; i++) {
             final ParsedPermission permission = oldPackage.getPermissions().get(i);
 
-            if (permission.parsedPermissionGroup != null) {
+            if (permission.getParsedPermissionGroup() != null) {
                 oldPermissionNameToGroupName.put(permission.getName(),
-                        permission.parsedPermissionGroup.getName());
+                        permission.getParsedPermissionGroup().getName());
             }
         }
 
@@ -2098,8 +2098,9 @@
 
             if ((newProtection & PermissionInfo.PROTECTION_DANGEROUS) != 0) {
                 final String permissionName = newPermission.getName();
-                final String newPermissionGroupName = newPermission.parsedPermissionGroup == null
-                        ? null : newPermission.parsedPermissionGroup.getName();
+                final String newPermissionGroupName =
+                        newPermission.getParsedPermissionGroup() == null
+                                ? null : newPermission.getParsedPermissionGroup().getName();
                 final String oldPermissionGroupName = oldPermissionNameToGroupName.get(
                         permissionName);
 
@@ -2144,7 +2145,7 @@
             ParsedPermission p = pkg.getPermissions().get(i);
 
             // Assume by default that we did not install this permission into the system.
-            p.flags &= ~PermissionInfo.FLAG_INSTALLED;
+            p.setFlags(p.getFlags() & ~PermissionInfo.FLAG_INSTALLED);
 
             synchronized (PermissionManagerService.this.mLock) {
                 // Now that permission groups have a special meaning, we ignore permission
@@ -2152,16 +2153,16 @@
                 // permissions for one app being granted to someone just because they happen
                 // to be in a group defined by another app (before this had no implications).
                 if (pkg.getTargetSdkVersion() > Build.VERSION_CODES.LOLLIPOP_MR1) {
-                    p.parsedPermissionGroup = mSettings.mPermissionGroups.get(p.getGroup());
+                    p.setParsedPermissionGroup(mSettings.mPermissionGroups.get(p.getGroup()));
                     // Warn for a permission in an unknown group.
                     if (DEBUG_PERMISSIONS
-                            && p.getGroup() != null && p.parsedPermissionGroup == null) {
+                            && p.getGroup() != null && p.getParsedPermissionGroup() == null) {
                         Slog.i(TAG, "Permission " + p.getName() + " from package "
                                 + p.getPackageName() + " in an unknown group " + p.getGroup());
                     }
                 }
 
-                if (p.tree) {
+                if (p.isTree()) {
                     final BasePermission bp = BasePermission.createOrUpdate(
                             mPackageManagerInt,
                             mSettings.getPermissionTreeLocked(p.getName()), p, pkg,
@@ -2409,14 +2410,16 @@
                     }
                 }
 
+                // TODO(b/140256621): The package instant app method has been removed
+                //  as part of work in b/135203078, so this has been commented out in the meantime
                 // Limit ephemeral apps to ephemeral allowed permissions.
-                if (pkg.isInstantApp() && !bp.isInstant()) {
-                    if (DEBUG_PERMISSIONS) {
-                        Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
-                                + " for package " + pkg.getPackageName());
-                    }
-                    continue;
-                }
+//                if (/*pkg.isInstantApp()*/ false && !bp.isInstant()) {
+//                    if (DEBUG_PERMISSIONS) {
+//                        Log.i(TAG, "Denying non-ephemeral permission " + bp.getName()
+//                                + " for package " + pkg.getPackageName());
+//                    }
+//                    continue;
+//                }
 
                 if (bp.isRuntimeOnly() && !appSupportsRuntimePermissions) {
                     if (DEBUG_PERMISSIONS) {
@@ -2450,7 +2453,7 @@
                     }
                 } else if (bp.isSignature()) {
                     // For all apps signature permissions are install time ones.
-                    allowedSig = grantSignaturePermission(perm, pkg, bp, origPermissions);
+                    allowedSig = grantSignaturePermission(perm, pkg, ps, bp, origPermissions);
                     if (allowedSig) {
                         grant = GRANT_INSTALL;
                     }
@@ -2764,7 +2767,8 @@
                             Slog.i(TAG, "Un-granting permission " + perm
                                     + " from package " + pkg.getPackageName()
                                     + " (protectionLevel=" + bp.getProtectionLevel()
-                                    + " flags=0x" + Integer.toHexString(pkg.getFlags())
+                                    + " flags=0x"
+                                    + Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
                                     + ")");
                         }
                     } else if (bp.isAppOp()) {
@@ -2776,7 +2780,8 @@
                             Slog.i(TAG, "Not granting permission " + perm
                                     + " to package " + pkg.getPackageName()
                                     + " (protectionLevel=" + bp.getProtectionLevel()
-                                    + " flags=0x" + Integer.toHexString(pkg.getFlags())
+                                    + " flags=0x"
+                                    + Integer.toHexString(PackageInfoUtils.appInfoFlags(pkg, ps))
                                     + ")");
                         }
                     }
@@ -2784,7 +2789,7 @@
             }
 
             if ((changedInstallPermission || replace) && !ps.areInstallPermissionsFixed() &&
-                    !ps.isSystem() || ps.isUpdatedSystem()) {
+                    !ps.isSystem() || !ps.getPkgState().isUpdatedSystemApp()) {
                 // This is the first that we have heard about this package, so the
                 // permissions we have now selected are fixed until explicitly
                 // changed.
@@ -2934,7 +2939,7 @@
      */
     private @NonNull int[] checkIfLegacyStorageOpsNeedToBeUpdated(
             @NonNull AndroidPackage pkg, boolean replace, @NonNull int[] updatedUserIds) {
-        if (replace && pkg.hasRequestedLegacyExternalStorage() && (
+        if (replace && pkg.isRequestLegacyExternalStorage() && (
                 pkg.getRequestedPermissions().contains(READ_EXTERNAL_STORAGE)
                         || pkg.getRequestedPermissions().contains(WRITE_EXTERNAL_STORAGE))) {
             return UserManagerService.getInstance().getUserIds();
@@ -3127,7 +3132,7 @@
     }
 
     private boolean grantSignaturePermission(String perm, AndroidPackage pkg,
-            BasePermission bp, PermissionsState origPermissions) {
+            PackageSetting pkgSetting, BasePermission bp, PermissionsState origPermissions) {
         boolean oemPermission = bp.isOEM();
         boolean vendorPrivilegedPermission = bp.isVendorPrivileged();
         boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();
@@ -3139,7 +3144,7 @@
                 && !platformPackage && platformPermission) {
             if (!hasPrivappWhitelistEntry(perm, pkg)) {
                 // Only report violations for apps on system image
-                if (!mSystemReady && !pkg.isUpdatedSystemApp()) {
+                if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
                     // it's only a reportable violation if the permission isn't explicitly denied
                     ArraySet<String> deniedPermissions = null;
                     if (pkg.isVendor()) {
@@ -3205,8 +3210,8 @@
             if (pkg.isSystem()) {
                 // For updated system applications, a privileged/oem permission
                 // is granted only if it had been defined by the original application.
-                if (pkg.isUpdatedSystemApp()) {
-                    final PackageSetting disabledPs = (PackageSetting) mPackageManagerInt
+                if (pkgSetting.getPkgState().isUpdatedSystemApp()) {
+                    final PackageSetting disabledPs = mPackageManagerInt
                             .getDisabledSystemPackage(pkg.getPackageName());
                     final AndroidPackage disabledPkg = disabledPs == null ? null : disabledPs.pkg;
                     if (disabledPs != null
@@ -3612,7 +3617,7 @@
             return EmptyArray.INT;
         }
         for (AndroidPackage pkg : pkgList) {
-            if (pkg.getRequestedPermissions() == null) {
+            if (pkg.getRequestedPermissions().isEmpty()) {
                 continue;
             }
             final int requestedPermCount = pkg.getRequestedPermissions().size();
@@ -3720,9 +3725,9 @@
                 // Only system declares background permissions, hence mapping does never change.
                 mBackgroundPermissions = new ArrayMap<>();
                 for (BasePermission bp : mSettings.getAllPermissionsLocked()) {
-                    if (bp.perm != null && bp.perm.backgroundPermission != null) {
+                    if (bp.perm != null && bp.perm.getBackgroundPermission() != null) {
                         String fgPerm = bp.name;
-                        String bgPerm = bp.perm.backgroundPermission;
+                        String bgPerm = bp.perm.getBackgroundPermission();
 
                         List<String> fgPerms = mBackgroundPermissions.get(bgPerm);
                         if (fgPerms == null) {
@@ -4234,7 +4239,7 @@
         if (pkg == null) {
             return StorageManager.UUID_PRIVATE_INTERNAL;
         }
-        if (pkg.isExternal()) {
+        if (pkg.isExternalStorage()) {
             if (TextUtils.isEmpty(pkg.getVolumeUuid())) {
                 return StorageManager.UUID_PRIMARY_PHYSICAL;
             } else {
@@ -4246,7 +4251,7 @@
     }
 
     private static boolean hasPermission(AndroidPackage pkg, String permName) {
-        if (pkg.getPermissions() == null) {
+        if (pkg.getPermissions().isEmpty()) {
             return false;
         }
 
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 58a9f42..048e487 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -22,9 +22,10 @@
 import android.annotation.UserIdInt;
 import android.content.pm.PackageManager;
 import android.content.pm.PermissionInfo;
-import android.content.pm.parsing.AndroidPackage;
 import android.permission.PermissionManagerInternal;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
diff --git a/services/core/java/com/android/server/pm/permission/PermissionSettings.java b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
index 254b720..355e243 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionSettings.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionSettings.java
@@ -18,7 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.pm.parsing.ComponentParseUtils;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -65,7 +65,7 @@
      * name to permission group object.
      */
     @GuardedBy("mLock")
-    final ArrayMap<String, ComponentParseUtils.ParsedPermissionGroup> mPermissionGroups =
+    final ArrayMap<String, ParsedPermissionGroup> mPermissionGroups =
             new ArrayMap<>();
 
     /**
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
new file mode 100644
index 0000000..c008d93
--- /dev/null
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
@@ -0,0 +1,196 @@
+/*
+ * 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.pm.pkg;
+
+import static java.util.Collections.emptyList;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.SharedLibraryInfo;
+
+import com.android.internal.util.DataClass;
+import com.android.server.pm.PackageSetting;
+
+import java.util.List;
+
+/**
+ * For use by {@link PackageSetting} to maintain functionality that used to exist in
+ * {@link PackageParser.Package}.
+ *
+ * It is assumed that anything inside the package was not cached or written to disk, so none of
+ * these fields are either. They must be set on every boot from other state on the device.
+ */
+@DataClass(genSetters = true, genConstructor = false, genBuilder = false)
+public class PackageStateUnserialized {
+
+    private boolean hiddenUntilInstalled;
+
+    @NonNull
+    private List<SharedLibraryInfo> usesLibraryInfos = emptyList();
+
+    @NonNull
+    private List<String> usesLibraryFiles = emptyList();
+
+    private boolean updatedSystemApp;
+
+    @NonNull
+    private volatile long[] lastPackageUsageTimeInMills;
+
+    @Nullable
+    private String overrideSeInfo;
+
+    private long[] lazyInitLastPackageUsageTimeInMills() {
+        return new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT];
+    }
+
+    public PackageStateUnserialized setLastPackageUsageTimeInMills(int reason, long time) {
+        getLastPackageUsageTimeInMills()[reason] = time;
+        return this;
+    }
+
+    public long getLatestPackageUseTimeInMills() {
+        long latestUse = 0L;
+        for (long use : getLastPackageUsageTimeInMills()) {
+            latestUse = Math.max(latestUse, use);
+        }
+        return latestUse;
+    }
+
+    public long getLatestForegroundPackageUseTimeInMills() {
+        int[] foregroundReasons = {
+                PackageManager.NOTIFY_PACKAGE_USE_ACTIVITY,
+                PackageManager.NOTIFY_PACKAGE_USE_FOREGROUND_SERVICE
+        };
+
+        long latestUse = 0L;
+        for (int reason : foregroundReasons) {
+            latestUse = Math.max(latestUse, getLastPackageUsageTimeInMills()[reason]);
+        }
+        return latestUse;
+    }
+
+
+
+    // Code below generated by codegen v1.0.14.
+    //
+    // DO NOT MODIFY!
+    // CHECKSTYLE:OFF Generated code
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java
+    //
+    // To exclude the generated code from IntelliJ auto-formatting enable (one-time):
+    //   Settings > Editor > Code Style > Formatter Control
+    //@formatter:off
+
+
+    @DataClass.Generated.Member
+    public boolean isHiddenUntilInstalled() {
+        return hiddenUntilInstalled;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<SharedLibraryInfo> getUsesLibraryInfos() {
+        return usesLibraryInfos;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull List<String> getUsesLibraryFiles() {
+        return usesLibraryFiles;
+    }
+
+    @DataClass.Generated.Member
+    public boolean isUpdatedSystemApp() {
+        return updatedSystemApp;
+    }
+
+    @DataClass.Generated.Member
+    public @NonNull long[] getLastPackageUsageTimeInMills() {
+        long[] _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills;
+        if (_lastPackageUsageTimeInMills == null) {
+            synchronized(this) {
+                _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills;
+                if (_lastPackageUsageTimeInMills == null) {
+                    _lastPackageUsageTimeInMills = lastPackageUsageTimeInMills = lazyInitLastPackageUsageTimeInMills();
+                }
+            }
+        }
+        return _lastPackageUsageTimeInMills;
+    }
+
+    @DataClass.Generated.Member
+    public @Nullable String getOverrideSeInfo() {
+        return overrideSeInfo;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setHiddenUntilInstalled(boolean value) {
+        hiddenUntilInstalled = value;
+        return this;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setUsesLibraryInfos(@NonNull List<SharedLibraryInfo> value) {
+        usesLibraryInfos = value;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, usesLibraryInfos);
+        return this;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setUsesLibraryFiles(@NonNull List<String> value) {
+        usesLibraryFiles = value;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, usesLibraryFiles);
+        return this;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setUpdatedSystemApp(boolean value) {
+        updatedSystemApp = value;
+        return this;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setLastPackageUsageTimeInMills(@NonNull long... value) {
+        lastPackageUsageTimeInMills = value;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, lastPackageUsageTimeInMills);
+        return this;
+    }
+
+    @DataClass.Generated.Member
+    public PackageStateUnserialized setOverrideSeInfo(@Nullable String value) {
+        overrideSeInfo = value;
+        return this;
+    }
+
+    @DataClass.Generated(
+            time = 1580422870209L,
+            codegenVersion = "1.0.14",
+            sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java",
+            inputSignatures = "private  boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate  boolean updatedSystemApp\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\n @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate  long[] lazyInitLastPackageUsageTimeInMills()\npublic  com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic  long getLatestPackageUseTimeInMills()\npublic  long getLatestForegroundPackageUseTimeInMills()\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)")
+    @Deprecated
+    private void __metadata() {}
+
+
+    //@formatter:on
+    // End of generated code
+
+}
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index c13cb38..139c844 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -40,6 +40,7 @@
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PermissionInfo;
 import android.os.Build;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
@@ -50,26 +51,25 @@
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.LongSparseLongArray;
+import android.util.Pair;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsCallback;
 import com.android.internal.app.IAppOpsService;
 import com.android.internal.infra.AndroidFuture;
-import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.IntPair;
 import com.android.internal.util.function.pooled.PooledLambda;
 import com.android.server.FgThread;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.pm.permission.PermissionManagerServiceInternal;
 import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
 
 import java.util.ArrayList;
 import java.util.List;
-import java.util.Objects;
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -100,7 +100,7 @@
      * scheduled for a package/user.
      */
     @GuardedBy("mLock")
-    private final ArraySet<Integer> mIsPackageSyncsScheduled = new ArraySet<>();
+    private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
 
     public PermissionPolicyService(@NonNull Context context) {
         super(context);
@@ -125,8 +125,10 @@
 
             @Override
             public void onPackageChanged(String packageName, int uid) {
-                if (isStarted(UserHandle.getUserId(uid))) {
-                    synchronizePackagePermissionsAndAppOpsForUser(uid);
+                final int userId = UserHandle.getUserId(uid);
+
+                if (isStarted(userId)) {
+                    synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
                 }
             }
 
@@ -137,21 +139,12 @@
         });
 
         permManagerInternal.addOnRuntimePermissionStateChangedListener(
-                (packageName, userId) -> {
-                    int uid;
-                    try {
-                        uid = getContext().getPackageManager().getPackageUidAsUser(packageName, 0,
-                                userId);
-                    } catch (NameNotFoundException e) {
-                        Slog.e(LOG_TAG, "Cannot synchronize changed package " + packageName, e);
-                        return;
-                    }
-                    synchronizeUidPermissionsAndAppOpsAsync(uid);
-                });
+                this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
 
         mAppOpsCallback = new IAppOpsCallback.Stub() {
             public void opChanged(int op, int uid, String packageName) {
-                synchronizeUidPermissionsAndAppOpsAsync(uid);
+                synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
+                        UserHandle.getUserId(uid));
             }
         };
 
@@ -170,7 +163,7 @@
                 if (perm.isSoftRestricted()) {
                     SoftRestrictedPermissionPolicy policy =
                             SoftRestrictedPermissionPolicy.forPermission(null, null, null,
-                                    perm.name);
+                                    null, perm.name);
                     int extraAppOp = policy.getExtraAppOpCode();
                     if (extraAppOp != OP_NONE) {
                         appOpsService.startWatchingMode(extraAppOp, null, mAppOpsCallback);
@@ -201,17 +194,19 @@
         return AppOpsManager.opToSwitch(op);
     }
 
-    private void synchronizeUidPermissionsAndAppOpsAsync(int uid) {
-        if (isStarted(UserHandle.getUserId(uid))) {
+    private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
+            @UserIdInt int changedUserId) {
+        if (isStarted(changedUserId)) {
             synchronized (mLock) {
-                if (mIsPackageSyncsScheduled.add(uid)) {
+                if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
                     FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
                             PermissionPolicyService
                                     ::synchronizePackagePermissionsAndAppOpsForUser,
-                            this, uid));
+                            this, packageName, changedUserId));
                 } else {
                     if (DEBUG) {
-                        Slog.v(LOG_TAG, "sync for " + uid + " already scheduled");
+                        Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
+                                + " already scheduled");
                     }
                 }
             }
@@ -340,20 +335,39 @@
     /**
      * Synchronize a single package.
      */
-    private void synchronizePackagePermissionsAndAppOpsForUser(int uid) {
+    private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
+            @UserIdInt int userId) {
         synchronized (mLock) {
-            mIsPackageSyncsScheduled.remove(uid);
+            mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
         }
 
         if (DEBUG) {
             Slog.v(LOG_TAG,
-                    "synchronizePackagePermissionsAndAppOpsForUser(" + uid + ")");
+                    "synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
+                            + userId + ")");
         }
 
+        final PackageManagerInternal packageManagerInternal = LocalServices.getService(
+                PackageManagerInternal.class);
+        final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
+                Process.SYSTEM_UID, userId);
+        if (pkg == null) {
+            return;
+        }
         final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
-                getUserContext(getContext(), UserHandle.getUserHandleForUid(uid)));
-        synchroniser.addUid(uid);
-        synchroniser.syncUids();
+                getUserContext(getContext(), UserHandle.of(userId)));
+        synchroniser.addPackage(pkg.packageName);
+        final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
+                pkg.packageName, userId);
+
+        for (String sharedPkgName : sharedPkgNames) {
+            final AndroidPackage sharedPkg = packageManagerInternal
+                    .getPackage(sharedPkgName);
+            if (sharedPkg != null) {
+                synchroniser.addPackage(sharedPkg.getPackageName());
+            }
+        }
+        synchroniser.syncPackages();
     }
 
     /**
@@ -367,8 +381,8 @@
         final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
                 getUserContext(getContext(), UserHandle.of(userId)));
         packageManagerInternal.forEachPackage(
-                (pkg) -> synchronizer.addUid(pkg.getUid()));
-        synchronizer.syncUids();
+                (pkg) -> synchronizer.addPackage(pkg.getPackageName()));
+        synchronizer.syncPackages();
     }
 
     /**
@@ -383,51 +397,37 @@
 
         private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
 
-        // Cache uid -> packageNames
-        private SparseArray<String[]> mUidToPkg = new SparseArray<>();
-
         /**
          * All ops that need to be flipped to allow.
          *
-         * @see #syncUids
+         * @see #syncPackages
          */
-        private final @NonNull ArraySet<OpToChange> mOpsToAllow = new ArraySet<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to ignore.
          *
-         * @see #syncUids
+         * @see #syncPackages
          */
-        private final @NonNull ArraySet<OpToChange> mOpsToIgnore = new ArraySet<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to ignore if not allowed.
          *
          * Currently, only used by soft restricted permissions logic.
          *
-         * @see #syncUids
+         * @see #syncPackages
          */
-        private final @NonNull ArraySet<OpToChange> mOpsToIgnoreIfNotAllowed = new ArraySet<>();
+        private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>();
 
         /**
          * All ops that need to be flipped to foreground.
          *
          * Currently, only used by the foreground/background permissions logic.
          *
-         * @see #syncUids
+         * @see #syncPackages
          */
-        private final @NonNull ArraySet<OpToChange> mOpsToForeground = new ArraySet<>();
-
-        private @Nullable String[] getPackageNamesForUid(int uid) {
-            String[] pkgs = mUidToPkg.get(uid);
-            if (pkgs != null) {
-                return pkgs;
-            }
-
-            pkgs = mPackageManager.getPackagesForUid(uid);
-            mUidToPkg.put(uid, pkgs);
-            return pkgs;
-        }
+        private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
 
         PermissionToOpSynchroniser(@NonNull Context context) {
             mContext = context;
@@ -449,11 +449,11 @@
         }
 
         /**
-         * Set app ops that were added in {@link #addUid}.
+         * Set app ops that were added in {@link #addPackage}.
          *
          * <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
          */
-        private void syncUids() {
+        private void syncPackages() {
             // Remember which ops were already set. This makes sure that we always set the most
             // permissive mode if two OpChanges are scheduled. This can e.g. happen if two
             // permissions change the same op. See {@link #getSwitchOp}.
@@ -461,42 +461,42 @@
 
             final int allowCount = mOpsToAllow.size();
             for (int i = 0; i < allowCount; i++) {
-                final OpToChange op = mOpsToAllow.valueAt(i);
+                final OpToChange op = mOpsToAllow.get(i);
 
-                setUidModeAllowed(op.code, op.uid);
+                setUidModeAllowed(op.code, op.uid, op.packageName);
                 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
             }
 
             final int foregroundCount = mOpsToForeground.size();
             for (int i = 0; i < foregroundCount; i++) {
-                final OpToChange op = mOpsToForeground.valueAt(i);
+                final OpToChange op = mOpsToForeground.get(i);
                 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
                     continue;
                 }
 
-                setUidModeForeground(op.code, op.uid);
+                setUidModeForeground(op.code, op.uid, op.packageName);
                 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
             }
 
             final int ignoreCount = mOpsToIgnore.size();
             for (int i = 0; i < ignoreCount; i++) {
-                final OpToChange op = mOpsToIgnore.valueAt(i);
+                final OpToChange op = mOpsToIgnore.get(i);
                 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
                     continue;
                 }
 
-                setUidModeIgnored(op.code, op.uid);
+                setUidModeIgnored(op.code, op.uid, op.packageName);
                 alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
             }
 
             final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size();
             for (int i = 0; i < ignoreIfNotAllowedCount; i++) {
-                final OpToChange op = mOpsToIgnoreIfNotAllowed.valueAt(i);
+                final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i);
                 if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
                     continue;
                 }
 
-                boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid);
+                boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName);
                 if (wasSet) {
                     alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
                 }
@@ -506,17 +506,18 @@
         /**
          * Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
          */
-        private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull String permissionName) {
+        private void addAppOps(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
+                @NonNull String permissionName) {
             PermissionInfo permissionInfo = mRuntimePermissionInfos.get(permissionName);
             if (permissionInfo == null) {
                 return;
             }
-            addPermissionAppOp(packageInfo, permissionInfo);
-            addExtraAppOp(packageInfo, permissionInfo);
+            addPermissionAppOp(packageInfo, pkg, permissionInfo);
+            addExtraAppOp(packageInfo, pkg, permissionInfo);
         }
 
         private void addPermissionAppOp(@NonNull PackageInfo packageInfo,
-                @NonNull PermissionInfo permissionInfo) {
+                @NonNull AndroidPackage pkg, @NonNull PermissionInfo permissionInfo) {
             if (!permissionInfo.isRuntime()) {
                 return;
             }
@@ -539,13 +540,13 @@
             }
 
             int appOpMode;
-            boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, permissionInfo);
+            boolean shouldGrantAppOp = shouldGrantAppOp(packageInfo, pkg, permissionInfo);
             if (shouldGrantAppOp) {
                 if (permissionInfo.backgroundPermission != null) {
                     PermissionInfo backgroundPermissionInfo = mRuntimePermissionInfos.get(
                             permissionInfo.backgroundPermission);
                     boolean shouldGrantBackgroundAppOp = backgroundPermissionInfo != null
-                            && shouldGrantAppOp(packageInfo, backgroundPermissionInfo);
+                            && shouldGrantAppOp(packageInfo, pkg, backgroundPermissionInfo);
                     appOpMode = shouldGrantBackgroundAppOp ? MODE_ALLOWED : MODE_FOREGROUND;
                 } else {
                     appOpMode = MODE_ALLOWED;
@@ -555,7 +556,7 @@
             }
 
             int uid = packageInfo.applicationInfo.uid;
-            OpToChange opToChange = new OpToChange(uid, appOpCode);
+            OpToChange opToChange = new OpToChange(uid, packageName, appOpCode);
             switch (appOpMode) {
                 case MODE_ALLOWED:
                     mOpsToAllow.add(opToChange);
@@ -570,7 +571,7 @@
         }
 
         private boolean shouldGrantAppOp(@NonNull PackageInfo packageInfo,
-                @NonNull PermissionInfo permissionInfo) {
+                @NonNull AndroidPackage pkg, @NonNull PermissionInfo permissionInfo) {
             String permissionName = permissionInfo.name;
             String packageName = packageInfo.packageName;
             boolean isGranted = mPackageManager.checkPermission(permissionName, packageName)
@@ -595,14 +596,15 @@
             } else if (permissionInfo.isSoftRestricted()) {
                 SoftRestrictedPermissionPolicy policy =
                         SoftRestrictedPermissionPolicy.forPermission(mContext,
-                                packageInfo.applicationInfo, mContext.getUser(), permissionName);
+                                packageInfo.applicationInfo, pkg, mContext.getUser(),
+                                permissionName);
                 return policy.mayGrantPermission();
             } else {
                 return true;
             }
         }
 
-        private void addExtraAppOp(@NonNull PackageInfo packageInfo,
+        private void addExtraAppOp(@NonNull PackageInfo packageInfo, @NonNull AndroidPackage pkg,
                 @NonNull PermissionInfo permissionInfo) {
             if (!permissionInfo.isSoftRestricted()) {
                 return;
@@ -611,14 +613,15 @@
             String permissionName = permissionInfo.name;
             SoftRestrictedPermissionPolicy policy =
                     SoftRestrictedPermissionPolicy.forPermission(mContext,
-                            packageInfo.applicationInfo, mContext.getUser(), permissionName);
+                            packageInfo.applicationInfo, pkg, mContext.getUser(), permissionName);
             int extraOpCode = policy.getExtraAppOpCode();
             if (extraOpCode == OP_NONE) {
                 return;
             }
 
             int uid = packageInfo.applicationInfo.uid;
-            OpToChange extraOpToChange = new OpToChange(uid, extraOpCode);
+            String packageName = packageInfo.packageName;
+            OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode);
             if (policy.mayAllowExtraAppOp()) {
                 mOpsToAllow.add(extraOpToChange);
             } else {
@@ -631,56 +634,49 @@
         }
 
         /**
-         * Add a Uid for {@link #syncUids() processing} later.
+         * Add a package for {@link #syncPackages() processing} later.
          *
          * <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
          *
-         * @param uid The uid to add for later processing.
+         * @param pkgName The package to add for later processing.
          */
-        void addUid(int uid) {
-            String[] pkgNames = getPackageNamesForUid(uid);
-            if (pkgNames == null) {
+        void addPackage(@NonNull String pkgName) {
+            PackageManagerInternal pmInternal =
+                    LocalServices.getService(PackageManagerInternal.class);
+            final PackageInfo pkgInfo;
+            final AndroidPackage pkg;
+            try {
+                pkgInfo = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
+                pkg = pmInternal.getPackage(pkgName);
+            } catch (NameNotFoundException e) {
                 return;
             }
 
-            for (String pkgName : pkgNames) {
-                final PackageInfo pkg;
-                try {
-                    pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
-                } catch (NameNotFoundException e) {
-                    continue;
-                }
+            if (pkgInfo == null || pkg == null || pkgInfo.requestedPermissions == null) {
+                return;
+            }
 
-                if (pkg.requestedPermissions == null) {
-                    continue;
-                }
-
-                for (String permission : pkg.requestedPermissions) {
-                    addAppOps(pkg, permission);
-                }
+            for (String permission : pkgInfo.requestedPermissions) {
+                addAppOps(pkgInfo, pkg, permission);
             }
         }
 
-        private void setUidModeAllowed(int opCode, int uid) {
-            setUidMode(opCode, uid, MODE_ALLOWED);
+        private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_ALLOWED, packageName);
         }
 
-        private void setUidModeForeground(int opCode, int uid) {
-            setUidMode(opCode, uid, MODE_FOREGROUND);
+        private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
         }
 
-        private void setUidModeIgnored(int opCode, int uid) {
-            setUidMode(opCode, uid, MODE_IGNORED);
+        private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
+            setUidMode(opCode, uid, MODE_IGNORED, packageName);
         }
 
-        private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid) {
-            String[] pkgsOfUid = getPackageNamesForUid(uid);
-            if (ArrayUtils.isEmpty(pkgsOfUid)) {
-                return false;
-            }
-
+        private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid,
+                @NonNull String packageName) {
             final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
-                    opCode), uid, pkgsOfUid[0]);
+                    opCode), uid, packageName);
             if (currentMode != MODE_ALLOWED) {
                 if (currentMode != MODE_IGNORED) {
                     mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, MODE_IGNORED,
@@ -691,24 +687,20 @@
             return false;
         }
 
-        private void setUidMode(int opCode, int uid, int mode) {
-            String[] pkgsOfUid = getPackageNamesForUid(uid);
-            if (ArrayUtils.isEmpty(pkgsOfUid)) {
-                return;
-            }
-
+        private void setUidMode(int opCode, int uid, int mode,
+                @NonNull String packageName) {
             final int oldMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
-                    opCode), uid, pkgsOfUid[0]);
+                    opCode), uid, packageName);
             if (oldMode != mode) {
                 mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, mode,
                         mAppOpsCallback);
                 final int newMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
-                        opCode), uid, pkgsOfUid[0]);
+                        opCode), uid, packageName);
                 if (newMode != mode) {
                     // Work around incorrectly-set package mode. It never makes sense for app ops
                     // related to runtime permissions, but can get in the way and we have to reset
                     // it.
-                    mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, pkgsOfUid[0],
+                    mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, packageName,
                             AppOpsManager.opToDefaultMode(opCode), mAppOpsCallback);
                 }
             }
@@ -716,30 +708,14 @@
 
         private class OpToChange {
             final int uid;
+            final @NonNull String packageName;
             final int code;
 
-            OpToChange(int uid, int code) {
+            OpToChange(int uid, @NonNull String packageName, int code) {
                 this.uid = uid;
+                this.packageName = packageName;
                 this.code = code;
             }
-
-            @Override
-            public boolean equals(Object o) {
-                if (this == o) {
-                    return true;
-                }
-                if (o == null || getClass() != o.getClass()) {
-                    return false;
-                }
-
-                OpToChange other = (OpToChange) o;
-                return uid == other.uid && code == other.code;
-            }
-
-            @Override
-            public int hashCode() {
-                return Objects.hash(uid, code);
-            }
         }
     }
 
diff --git a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
index 740472e..90babcd 100644
--- a/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
+++ b/services/core/java/com/android/server/policy/SoftRestrictedPermissionPolicy.java
@@ -35,7 +35,6 @@
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManagerInternal;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -46,6 +45,7 @@
 
 import com.android.internal.compat.IPlatformCompat;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 /**
  * The behavior of soft restricted permissions is different for each permission. This class collects
@@ -100,8 +100,8 @@
      * @return The policy for this permission
      */
     public static @NonNull SoftRestrictedPermissionPolicy forPermission(@NonNull Context context,
-            @Nullable ApplicationInfo appInfo, @Nullable UserHandle user,
-            @NonNull String permission) {
+            @Nullable ApplicationInfo appInfo, @Nullable AndroidPackage pkg,
+            @Nullable UserHandle user, @NonNull String permission) {
         switch (permission) {
             // Storage uses a special app op to decide the mount state and supports soft restriction
             // where the restricted state allows the permission but only for accessing the medial
@@ -116,8 +116,6 @@
 
                 if (appInfo != null) {
                     PackageManager pm = context.getPackageManager();
-                    PackageManagerInternal pmInternal =
-                            LocalServices.getService(PackageManagerInternal.class);
                     StorageManagerInternal smInternal =
                             LocalServices.getService(StorageManagerInternal.class);
                     int flags = pm.getPermissionFlags(permission, appInfo.packageName, user);
@@ -131,8 +129,7 @@
                     isScopedStorageEnabled =
                             isChangeEnabledForUid(context, appInfo, user, ENABLE_SCOPED_STORAGE)
                             || isScopedStorageRequired;
-                    shouldPreserveLegacyExternalStorage = pmInternal.getPackage(
-                            appInfo.packageName).hasPreserveLegacyExternalStorage()
+                    shouldPreserveLegacyExternalStorage = pkg.hasPreserveLegacyExternalStorage()
                             && smInternal.hasLegacyExternalStorage(appInfo.uid);
                     shouldApplyRestriction = (flags & FLAG_PERMISSION_APPLY_RESTRICTION) != 0
                             || (isScopedStorageRequired && !shouldPreserveLegacyExternalStorage);
diff --git a/services/core/java/com/android/server/power/ThermalManagerService.java b/services/core/java/com/android/server/power/ThermalManagerService.java
index 491c5ab..da3cbf9 100644
--- a/services/core/java/com/android/server/power/ThermalManagerService.java
+++ b/services/core/java/com/android/server/power/ThermalManagerService.java
@@ -16,15 +16,18 @@
 
 package com.android.server.power;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.hardware.thermal.V1_0.ThermalStatus;
 import android.hardware.thermal.V1_0.ThermalStatusCode;
 import android.hardware.thermal.V1_1.IThermalCallback;
 import android.hardware.thermal.V2_0.IThermalChangedCallback;
+import android.hardware.thermal.V2_0.TemperatureThreshold;
 import android.hardware.thermal.V2_0.ThrottlingSeverity;
 import android.os.Binder;
 import android.os.CoolingDevice;
+import android.os.Handler;
 import android.os.HwBinder;
 import android.os.IThermalEventListener;
 import android.os.IThermalService;
@@ -36,6 +39,7 @@
 import android.os.ResultReceiver;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
+import android.os.SystemClock;
 import android.os.Temperature;
 import android.util.ArrayMap;
 import android.util.EventLog;
@@ -43,6 +47,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.DumpUtils;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
@@ -54,6 +59,7 @@
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -100,6 +106,9 @@
     /** Hal ready. */
     private final AtomicBoolean mHalReady = new AtomicBoolean();
 
+    /** Watches temperatures to forecast when throttling will occur */
+    private final TemperatureWatcher mTemperatureWatcher = new TemperatureWatcher();
+
     /** Invalid throttling status */
     private static final int INVALID_THROTTLING = Integer.MIN_VALUE;
 
@@ -154,6 +163,7 @@
                 onTemperatureChanged(temperatures.get(i), false);
             }
             onTemperatureMapChangedLocked();
+            mTemperatureWatcher.updateSevereThresholds();
             mHalReady.set(true);
         }
     }
@@ -462,6 +472,15 @@
             }
         }
 
+        @Override
+        public float getThermalHeadroom(int forecastSeconds) {
+            if (!mHalReady.get()) {
+                return Float.NaN;
+            }
+
+            return mTemperatureWatcher.getForecast(forecastSeconds);
+        }
+
         private void dumpItemsLocked(PrintWriter pw, String prefix,
                 Collection<?> items) {
             for (Iterator iterator = items.iterator(); iterator.hasNext();) {
@@ -616,6 +635,10 @@
         protected abstract List<CoolingDevice> getCurrentCoolingDevices(boolean shouldFilter,
                 int type);
 
+        @NonNull
+        protected abstract List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
+                int type);
+
         protected abstract boolean connectToHal();
 
         protected abstract void dump(PrintWriter pw, String prefix);
@@ -728,6 +751,12 @@
         }
 
         @Override
+        protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
+                int type) {
+            return new ArrayList<>();
+        }
+
+        @Override
         protected boolean connectToHal() {
             synchronized (mHalLock) {
                 try {
@@ -857,6 +886,12 @@
         }
 
         @Override
+        protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
+                int type) {
+            return new ArrayList<>();
+        }
+
+        @Override
         protected boolean connectToHal() {
             synchronized (mHalLock) {
                 try {
@@ -975,6 +1010,32 @@
         }
 
         @Override
+        protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
+                int type) {
+            synchronized (mHalLock) {
+                List<TemperatureThreshold> ret = new ArrayList<>();
+                if (mThermalHal20 == null) {
+                    return ret;
+                }
+                try {
+                    mThermalHal20.getTemperatureThresholds(shouldFilter, type,
+                            (status, thresholds) -> {
+                                if (ThermalStatusCode.SUCCESS == status.code) {
+                                    ret.addAll(thresholds);
+                                } else {
+                                    Slog.e(TAG,
+                                            "Couldn't get temperature thresholds because of HAL "
+                                                    + "error: " + status.debugMessage);
+                                }
+                            });
+                } catch (RemoteException e) {
+                    Slog.e(TAG, "Couldn't getTemperatureThresholds, reconnecting...", e);
+                }
+                return ret;
+            }
+        }
+
+        @Override
         protected boolean connectToHal() {
             synchronized (mHalLock) {
                 try {
@@ -1001,4 +1062,190 @@
         }
     }
 
+    private class TemperatureWatcher {
+        private final Handler mHandler = BackgroundThread.getHandler();
+
+        /** Map of skin temperature sensor name to a corresponding list of samples */
+        @GuardedBy("mSamples")
+        private final ArrayMap<String, ArrayList<Sample>> mSamples = new ArrayMap<>();
+
+        /** Map of skin temperature sensor name to the corresponding SEVERE temperature threshold */
+        @GuardedBy("mSamples")
+        private ArrayMap<String, Float> mSevereThresholds = new ArrayMap<>();
+
+        @GuardedBy("mSamples")
+        private long mLastForecastCallTimeMillis = 0;
+
+        void updateSevereThresholds() {
+            synchronized (mSamples) {
+                List<TemperatureThreshold> thresholds =
+                        mHalWrapper.getTemperatureThresholds(true, Temperature.TYPE_SKIN);
+                for (int t = 0; t < thresholds.size(); ++t) {
+                    TemperatureThreshold threshold = thresholds.get(t);
+                    if (threshold.hotThrottlingThresholds.length <= ThrottlingSeverity.SEVERE) {
+                        continue;
+                    }
+                    float temperature =
+                            threshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE];
+                    if (!Float.isNaN(temperature)) {
+                        mSevereThresholds.put(threshold.name,
+                                threshold.hotThrottlingThresholds[ThrottlingSeverity.SEVERE]);
+                    }
+                }
+            }
+        }
+
+        private static final int INACTIVITY_THRESHOLD_MILLIS = 10000;
+        private static final int RING_BUFFER_SIZE = 30;
+
+        private void updateTemperature() {
+            synchronized (mSamples) {
+                if (SystemClock.elapsedRealtime() - mLastForecastCallTimeMillis
+                        < INACTIVITY_THRESHOLD_MILLIS) {
+                    // Trigger this again after a second as long as forecast has been called more
+                    // recently than the inactivity timeout
+                    mHandler.postDelayed(this::updateTemperature, 1000);
+                } else {
+                    // Otherwise, we've been idle for at least 10 seconds, so we should
+                    // shut down
+                    mSamples.clear();
+                    return;
+                }
+
+                long now = SystemClock.elapsedRealtime();
+                List<Temperature> temperatures = mHalWrapper.getCurrentTemperatures(true,
+                        Temperature.TYPE_SKIN);
+
+                for (int t = 0; t < temperatures.size(); ++t) {
+                    Temperature temperature = temperatures.get(t);
+
+                    // Filter out invalid temperatures. If this results in no values being stored at
+                    // all, the mSamples.empty() check in getForecast() will catch it.
+                    if (Float.isNaN(temperature.getValue())) {
+                        continue;
+                    }
+
+                    ArrayList<Sample> samples = mSamples.computeIfAbsent(temperature.getName(),
+                            k -> new ArrayList<>(RING_BUFFER_SIZE));
+                    if (samples.size() == RING_BUFFER_SIZE) {
+                        samples.remove(0);
+                    }
+                    samples.add(new Sample(now, temperature.getValue()));
+                }
+            }
+        }
+
+        /**
+         * Calculates the trend using a linear regression. As the samples are degrees Celsius with
+         * associated timestamps in milliseconds, the slope is in degrees Celsius per millisecond.
+         */
+        private float getSlopeOf(List<Sample> samples) {
+            long sumTimes = 0L;
+            float sumTemperatures = 0.0f;
+            for (int s = 0; s < samples.size(); ++s) {
+                Sample sample = samples.get(s);
+                sumTimes += sample.time;
+                sumTemperatures += sample.temperature;
+            }
+            long meanTime = sumTimes / samples.size();
+            float meanTemperature = sumTemperatures / samples.size();
+
+            long sampleVariance = 0L;
+            float sampleCovariance = 0.0f;
+            for (int s = 0; s < samples.size(); ++s) {
+                Sample sample = samples.get(s);
+                long timeDelta = sample.time - meanTime;
+                float temperatureDelta = sample.temperature - meanTemperature;
+                sampleVariance += timeDelta * timeDelta;
+                sampleCovariance += timeDelta * temperatureDelta;
+            }
+
+            return sampleCovariance / sampleVariance;
+        }
+
+        /**
+         * Used to determine the temperature corresponding to 0.0. Given that 1.0 is pinned at the
+         * temperature corresponding to the SEVERE threshold, we set 0.0 to be that temperature
+         * minus DEGREES_BETWEEN_ZERO_AND_ONE.
+         */
+        private static final float DEGREES_BETWEEN_ZERO_AND_ONE = 30.0f;
+
+        private float normalizeTemperature(float temperature, float severeThreshold) {
+            synchronized (mSamples) {
+                float zeroNormalized = severeThreshold - DEGREES_BETWEEN_ZERO_AND_ONE;
+                if (temperature <= zeroNormalized) {
+                    return 0.0f;
+                }
+                float delta = temperature - zeroNormalized;
+                return delta / DEGREES_BETWEEN_ZERO_AND_ONE;
+            }
+        }
+
+        private static final int MINIMUM_SAMPLE_COUNT = 3;
+
+        float getForecast(int forecastSeconds) {
+            synchronized (mSamples) {
+                mLastForecastCallTimeMillis = System.currentTimeMillis();
+                if (mSamples.isEmpty()) {
+                    updateTemperature();
+                }
+
+                // If somehow things take much longer than expected or there are no temperatures
+                // to sample, return early
+                if (mSamples.isEmpty()) {
+                    Slog.e(TAG, "No temperature samples found");
+                    return Float.NaN;
+                }
+
+                // If we don't have any thresholds, we can't normalize the temperatures,
+                // so return early
+                if (mSevereThresholds.isEmpty()) {
+                    Slog.e(TAG, "No temperature thresholds found");
+                    return Float.NaN;
+                }
+
+                float maxNormalized = Float.NaN;
+                for (Map.Entry<String, ArrayList<Sample>> entry : mSamples.entrySet()) {
+                    String name = entry.getKey();
+                    ArrayList<Sample> samples = entry.getValue();
+
+                    Float threshold = mSevereThresholds.get(name);
+                    if (threshold == null) {
+                        Slog.e(TAG, "No threshold found for " + name);
+                        continue;
+                    }
+
+                    float currentTemperature = samples.get(0).temperature;
+
+                    if (samples.size() < MINIMUM_SAMPLE_COUNT) {
+                        // Don't try to forecast, just use the latest one we have
+                        float normalized = normalizeTemperature(currentTemperature, threshold);
+                        if (Float.isNaN(maxNormalized) || normalized > maxNormalized) {
+                            maxNormalized = normalized;
+                        }
+                        continue;
+                    }
+
+                    float slope = getSlopeOf(samples);
+                    float normalized = normalizeTemperature(
+                            currentTemperature + slope * forecastSeconds * 1000, threshold);
+                    if (Float.isNaN(maxNormalized) || normalized > maxNormalized) {
+                        maxNormalized = normalized;
+                    }
+                }
+
+                return maxNormalized;
+            }
+        }
+
+        private class Sample {
+            public long time;
+            public float temperature;
+
+            Sample(long time, float temperature) {
+                this.time = time;
+                this.temperature = temperature;
+            }
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
index 4b3746b..42aaec9 100644
--- a/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
+++ b/services/core/java/com/android/server/power/batterysaver/BatterySaverStateMachine.java
@@ -176,8 +176,10 @@
     @GuardedBy("mLock")
     private int mSettingBatterySaverStickyAutoDisableThreshold;
 
-    /** Config flag to track default disable threshold for Dynamic Power Savings enabled battery
-     * saver. */
+    /**
+     * Config flag to track default disable threshold for Dynamic Power Savings enabled battery
+     * saver.
+     */
     @GuardedBy("mLock")
     private final int mDynamicPowerSavingsDefaultDisableThreshold;
 
@@ -192,8 +194,9 @@
     @GuardedBy("mLock")
     private int mSettingAutomaticBatterySaver;
 
-    /** When to disable battery saver again if it was enabled due to an external suggestion.
-     *  Corresponds to Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD.
+    /**
+     * When to disable battery saver again if it was enabled due to an external suggestion.
+     * Corresponds to Settings.Global.DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD.
      */
     @GuardedBy("mLock")
     private int mDynamicPowerSavingsDisableThreshold;
@@ -203,7 +206,7 @@
      * Updates when Settings.Global.DYNAMIC_POWER_SAVINGS_ENABLED changes.
      */
     @GuardedBy("mLock")
-    private boolean mDynamicPowerSavingsBatterySaver;
+    private boolean mDynamicPowerSavingsEnableBatterySaver;
 
     /**
      * Last reason passed to {@link #enableBatterySaverLocked}.
@@ -265,7 +268,7 @@
     /** @return true if the dynamic mode should be used */
     private boolean isDynamicModeActiveLocked() {
         return mSettingAutomaticBatterySaver == PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC
-                && mDynamicPowerSavingsBatterySaver;
+                && mDynamicPowerSavingsEnableBatterySaver;
     }
 
     /**
@@ -428,7 +431,7 @@
         final boolean dynamicPowerSavingsThresholdChanged =
                 mDynamicPowerSavingsDisableThreshold != dynamicPowerSavingsDisableThreshold;
         final boolean dynamicPowerSavingsBatterySaverChanged =
-                mDynamicPowerSavingsBatterySaver != dynamicPowerSavingsBatterySaver;
+                mDynamicPowerSavingsEnableBatterySaver != dynamicPowerSavingsBatterySaver;
 
         if (!(enabledChanged || stickyChanged || thresholdChanged || automaticModeChanged
                 || stickyAutoDisableEnabledChanged || stickyAutoDisableThresholdChanged
@@ -443,7 +446,7 @@
         mSettingBatterySaverStickyAutoDisableThreshold = stickyAutoDisableThreshold;
         mSettingAutomaticBatterySaver = automaticBatterySaver;
         mDynamicPowerSavingsDisableThreshold = dynamicPowerSavingsDisableThreshold;
-        mDynamicPowerSavingsBatterySaver = dynamicPowerSavingsBatterySaver;
+        mDynamicPowerSavingsEnableBatterySaver = dynamicPowerSavingsBatterySaver;
 
         if (thresholdChanged) {
             // To avoid spamming the event log, we throttle logging here.
@@ -923,6 +926,8 @@
             pw.print("  mIsBatteryLevelLow=");
             pw.println(mIsBatteryLevelLow);
 
+            pw.print("  mSettingAutomaticBatterySaver=");
+            pw.println(mSettingAutomaticBatterySaver);
             pw.print("  mSettingBatterySaverEnabled=");
             pw.println(mSettingBatterySaverEnabled);
             pw.print("  mSettingBatterySaverEnabledSticky=");
@@ -936,6 +941,13 @@
             pw.print("  mBatterySaverStickyBehaviourDisabled=");
             pw.println(mBatterySaverStickyBehaviourDisabled);
 
+            pw.print("  mDynamicPowerSavingsDefaultDisableThreshold=");
+            pw.println(mDynamicPowerSavingsDefaultDisableThreshold);
+            pw.print("  mDynamicPowerSavingsDisableThreshold=");
+            pw.println(mDynamicPowerSavingsDisableThreshold);
+            pw.print("  mDynamicPowerSavingsEnableBatterySaver=");
+            pw.println(mDynamicPowerSavingsEnableBatterySaver);
+
             pw.print("  mLastAdaptiveBatterySaverChangedExternallyElapsed=");
             pw.println(mLastAdaptiveBatterySaverChangedExternallyElapsed);
         }
@@ -964,6 +976,8 @@
             proto.write(BatterySaverStateMachineProto.BATTERY_LEVEL, mBatteryLevel);
             proto.write(BatterySaverStateMachineProto.IS_BATTERY_LEVEL_LOW, mIsBatteryLevelLow);
 
+            proto.write(BatterySaverStateMachineProto.SETTING_AUTOMATIC_TRIGGER,
+                    mSettingAutomaticBatterySaver);
             proto.write(BatterySaverStateMachineProto.SETTING_BATTERY_SAVER_ENABLED,
                     mSettingBatterySaverEnabled);
             proto.write(BatterySaverStateMachineProto.SETTING_BATTERY_SAVER_ENABLED_STICKY,
@@ -979,6 +993,16 @@
                     mSettingBatterySaverStickyAutoDisableThreshold);
 
             proto.write(
+                    BatterySaverStateMachineProto.DEFAULT_DYNAMIC_DISABLE_THRESHOLD,
+                    mDynamicPowerSavingsDefaultDisableThreshold);
+            proto.write(
+                    BatterySaverStateMachineProto.DYNAMIC_DISABLE_THRESHOLD,
+                    mDynamicPowerSavingsDisableThreshold);
+            proto.write(
+                    BatterySaverStateMachineProto.DYNAMIC_BATTERY_SAVER_ENABLED,
+                    mDynamicPowerSavingsEnableBatterySaver);
+
+            proto.write(
                     BatterySaverStateMachineProto
                             .LAST_ADAPTIVE_BATTERY_SAVER_CHANGED_EXTERNALLY_ELAPSED,
                     mLastAdaptiveBatterySaverChangedExternallyElapsed);
diff --git a/services/core/java/com/android/server/role/RoleUserState.java b/services/core/java/com/android/server/role/RoleUserState.java
index 9f4ca3c..97ce6bd 100644
--- a/services/core/java/com/android/server/role/RoleUserState.java
+++ b/services/core/java/com/android/server/role/RoleUserState.java
@@ -364,12 +364,12 @@
                     (Map<String, Set<String>>) (Map<String, ?>) snapshotRolesLocked());
         }
 
-        mPersistence.write(roles, UserHandle.of(mUserId));
+        mPersistence.writeAsUser(roles, UserHandle.of(mUserId));
     }
 
     private void readFile() {
         synchronized (mLock) {
-            RolesState roles = mPersistence.read(UserHandle.of(mUserId));
+            RolesState roles = mPersistence.readAsUser(UserHandle.of(mUserId));
             if (roles == null) {
                 readLegacyFileLocked();
                 scheduleWriteFileLocked();
@@ -545,7 +545,7 @@
                 throw new IllegalStateException("This RoleUserState has already been destroyed");
             }
             mWriteHandler.removeCallbacksAndMessages(null);
-            mPersistence.delete(UserHandle.of(mUserId));
+            mPersistence.deleteAsUser(UserHandle.of(mUserId));
             mDestroyed = true;
         }
     }
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java
new file mode 100644
index 0000000..870d909
--- /dev/null
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerHw2Enforcer.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.soundtrigger_middleware;
+
+import android.hardware.soundtrigger.V2_1.ISoundTriggerHw;
+import android.hardware.soundtrigger.V2_1.ISoundTriggerHwCallback;
+import android.hardware.soundtrigger.V2_3.ModelParameterRange;
+import android.hardware.soundtrigger.V2_3.Properties;
+import android.hardware.soundtrigger.V2_3.RecognitionConfig;
+import android.os.IHwBinder;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A decorator around a HAL, which adds some checks that the HAL is behaving as expected.
+ * This is not necessarily a strict enforcement for the HAL contract, but a place to add checks for
+ * common HAL malfunctions, to help track them and assist in debugging.
+ *
+ * The class is not thread-safe.
+ */
+public class SoundTriggerHw2Enforcer implements ISoundTriggerHw2 {
+    static final String TAG = "SoundTriggerHw2Enforcer";
+
+    final ISoundTriggerHw2 mUnderlying;
+    Map<Integer, Boolean> mModelStates = new HashMap<>();
+
+    public SoundTriggerHw2Enforcer(
+            ISoundTriggerHw2 underlying) {
+        mUnderlying = underlying;
+    }
+
+    @Override
+    public Properties getProperties() {
+        return mUnderlying.getProperties();
+    }
+
+    @Override
+    public int loadSoundModel(ISoundTriggerHw.SoundModel soundModel, Callback callback,
+            int cookie) {
+        int handle = mUnderlying.loadSoundModel(soundModel, new CallbackEnforcer(callback), cookie);
+        mModelStates.put(handle, false);
+        return handle;
+    }
+
+    @Override
+    public int loadPhraseSoundModel(ISoundTriggerHw.PhraseSoundModel soundModel, Callback callback,
+            int cookie) {
+        int handle = mUnderlying.loadPhraseSoundModel(soundModel, new CallbackEnforcer(callback),
+                cookie);
+        mModelStates.put(handle, false);
+        return handle;
+    }
+
+    @Override
+    public void unloadSoundModel(int modelHandle) {
+        mUnderlying.unloadSoundModel(modelHandle);
+        mModelStates.remove(modelHandle);
+    }
+
+    @Override
+    public void stopRecognition(int modelHandle) {
+        mUnderlying.stopRecognition(modelHandle);
+        mModelStates.replace(modelHandle, false);
+    }
+
+    @Override
+    public void stopAllRecognitions() {
+        mUnderlying.stopAllRecognitions();
+        for (Map.Entry<Integer, Boolean> entry : mModelStates.entrySet()) {
+            entry.setValue(false);
+        }
+    }
+
+    @Override
+    public void startRecognition(int modelHandle, RecognitionConfig config, Callback callback,
+            int cookie) {
+        mUnderlying.startRecognition(modelHandle, config, new CallbackEnforcer(callback), cookie);
+        mModelStates.replace(modelHandle, true);
+    }
+
+    @Override
+    public void getModelState(int modelHandle) {
+        mUnderlying.getModelState(modelHandle);
+    }
+
+    @Override
+    public int getModelParameter(int modelHandle, int param) {
+        return mUnderlying.getModelParameter(modelHandle, param);
+    }
+
+    @Override
+    public void setModelParameter(int modelHandle, int param, int value) {
+        mUnderlying.setModelParameter(modelHandle, param, value);
+    }
+
+    @Override
+    public ModelParameterRange queryParameter(int modelHandle, int param) {
+        return mUnderlying.queryParameter(modelHandle, param);
+    }
+
+    @Override
+    public boolean linkToDeath(IHwBinder.DeathRecipient recipient, long cookie) {
+        return mUnderlying.linkToDeath(recipient, cookie);
+    }
+
+    @Override
+    public boolean unlinkToDeath(IHwBinder.DeathRecipient recipient) {
+        return mUnderlying.unlinkToDeath(recipient);
+    }
+
+    @Override
+    public String interfaceDescriptor() throws RemoteException {
+        return mUnderlying.interfaceDescriptor();
+    }
+
+    private class CallbackEnforcer implements Callback {
+        private final Callback mUnderlying;
+
+        private CallbackEnforcer(
+                Callback underlying) {
+            mUnderlying = underlying;
+        }
+
+        @Override
+        public void recognitionCallback(ISoundTriggerHwCallback.RecognitionEvent event,
+                int cookie) {
+            int model = event.header.model;
+            if (!mModelStates.getOrDefault(model, false)) {
+                Log.wtfStack(TAG, "Unexpected recognition event for model: " + model);
+            }
+            if (event.header.status
+                    != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) {
+                mModelStates.replace(model, false);
+            }
+            mUnderlying.recognitionCallback(event, cookie);
+        }
+
+        @Override
+        public void phraseRecognitionCallback(ISoundTriggerHwCallback.PhraseRecognitionEvent event,
+                int cookie) {
+            int model = event.common.header.model;
+            if (!mModelStates.getOrDefault(model, false)) {
+                Log.wtfStack(TAG, "Unexpected recognition event for model: " + model);
+            }
+            if (event.common.header.status
+                    != android.media.soundtrigger_middleware.RecognitionStatus.FORCED) {
+                mModelStates.replace(model, false);
+            }
+            mUnderlying.phraseRecognitionCallback(event, cookie);
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
index cd5e360..aa1558e 100644
--- a/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
+++ b/services/core/java/com/android/server/soundtrigger_middleware/SoundTriggerModule.java
@@ -191,7 +191,7 @@
      * Attached to the HAL service via factory.
      */
     private void attachToHal() {
-        mHalService = new SoundTriggerHw2Compat(mHalFactory.create());
+        mHalService = new SoundTriggerHw2Enforcer(new SoundTriggerHw2Compat(mHalFactory.create()));
         mHalService.linkToDeath(this, 0);
     }
 
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 47a26f5..e734528 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -41,6 +41,7 @@
 import android.app.AppOpsManager.HistoricalUidOps;
 import android.app.INotificationManager;
 import android.app.ProcessMemoryState;
+import android.app.RuntimeAppOpAccessMessage;
 import android.app.StatsManager;
 import android.app.StatsManager.PullAtomMetadata;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -377,6 +378,8 @@
                     return pullFaceSettings(atomTag, data);
                 case FrameworkStatsLog.APP_OPS:
                     return pullAppOps(atomTag, data);
+                case FrameworkStatsLog.RUNTIME_APP_OP_ACCESS:
+                    return pullRuntimeAppOpAccessMessage(atomTag, data);
                 case FrameworkStatsLog.NOTIFICATION_REMOTE_VIEWS:
                     return pullNotificationRemoteViews(atomTag, data);
                 case FrameworkStatsLog.DANGEROUS_PERMISSION_STATE_SAMPLED:
@@ -539,6 +542,7 @@
         registerAppsOnExternalStorageInfo();
         registerFaceSettings();
         registerAppOps();
+        registerRuntimeAppOpAccessMessage();
         registerNotificationRemoteViews();
         registerDangerousPermissionState();
         registerDangerousPermissionStateSampled();
@@ -2834,6 +2838,17 @@
 
     }
 
+    private void registerRuntimeAppOpAccessMessage() {
+        int tagId = FrameworkStatsLog.RUNTIME_APP_OP_ACCESS;
+        mStatsManager.registerPullAtomCallback(
+                tagId,
+                null, // use default PullAtomMetadata values
+                BackgroundThread.getExecutor(),
+                mStatsCallbackImpl
+        );
+
+    }
+
     int pullAppOps(int atomTag, List<StatsEvent> pulledData) {
         final long token = Binder.clearCallingIdentity();
         try {
@@ -2894,6 +2909,41 @@
         return StatsManager.PULL_SUCCESS;
     }
 
+    int pullRuntimeAppOpAccessMessage(int atomTag, List<StatsEvent> pulledData) {
+        final long token = Binder.clearCallingIdentity();
+        try {
+            AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+
+            RuntimeAppOpAccessMessage message = appOps.collectRuntimeAppOpAccessMessage();
+            if (message == null) {
+                Slog.i(TAG, "No runtime appop access message collected");
+                return StatsManager.PULL_SUCCESS;
+            }
+
+            StatsEvent.Builder e = StatsEvent.newBuilder();
+            e.setAtomId(atomTag);
+            e.writeInt(message.getUid());
+            e.writeString(message.getPackageName());
+            e.writeString(message.getOp());
+            if (message.getFeatureId() == null) {
+                e.writeString("");
+            } else {
+                e.writeString(message.getFeatureId());
+            }
+            e.writeString(message.getMessage());
+            e.writeInt(message.getSamplingStrategy());
+
+            pulledData.add(e.build());
+        } catch (Throwable t) {
+            // TODO: catch exceptions at a more granular level
+            Slog.e(TAG, "Could not read runtime appop access message", t);
+            return StatsManager.PULL_SKIP;
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+        return StatsManager.PULL_SUCCESS;
+    }
+
     static void unpackStreamedData(int atomTag, List<StatsEvent> pulledData,
             List<ParcelFileDescriptor> statsFiles) throws IOException {
         InputStream stream = new ParcelFileDescriptor.AutoCloseInputStream(statsFiles.get(0));
diff --git a/services/core/java/com/android/server/twilight/TwilightService.java b/services/core/java/com/android/server/twilight/TwilightService.java
index 761fbf8..e72ba8d 100644
--- a/services/core/java/com/android/server/twilight/TwilightService.java
+++ b/services/core/java/com/android/server/twilight/TwilightService.java
@@ -50,7 +50,6 @@
         implements AlarmManager.OnAlarmListener, Handler.Callback, LocationListener {
 
     private static final String TAG = "TwilightService";
-    private static final String FEATURE_ID = "TwilightService";
     private static final boolean DEBUG = false;
 
     private static final int MSG_START_LISTENING = 1;
@@ -74,7 +73,7 @@
     protected TwilightState mLastTwilightState;
 
     public TwilightService(Context context) {
-        super(context.createFeatureContext(FEATURE_ID));
+        super(context);
         mHandler = new Handler(Looper.getMainLooper(), this);
     }
 
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b61a2ce..04fae97 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -1163,8 +1163,12 @@
         // An activity is considered to be in multi-window mode if its task isn't fullscreen.
         final boolean inMultiWindowMode = inMultiWindowMode();
         if (inMultiWindowMode != mLastReportedMultiWindowMode) {
-            mLastReportedMultiWindowMode = inMultiWindowMode;
-            scheduleMultiWindowModeChanged(getConfiguration());
+            if (!inMultiWindowMode && mLastReportedPictureInPictureMode) {
+                updatePictureInPictureMode(null, false);
+            } else {
+                mLastReportedMultiWindowMode = inMultiWindowMode;
+                scheduleMultiWindowModeChanged(getConfiguration());
+            }
         }
     }
 
@@ -1723,10 +1727,9 @@
                 // The snapshot of home is only used once because it won't be updated while screen
                 // is on (see {@link TaskSnapshotController#screenTurningOff}).
                 mWmService.mTaskSnapshotController.removeSnapshotCache(task.mTaskId);
-                // TODO(b/9684093): Use more general condition to specify the case.
-                if (mDisplayContent.mAppTransition
-                        .getAppTransition() != WindowManager.TRANSIT_KEYGUARD_GOING_AWAY) {
-                    // Only use snapshot of home as starting window when unlocking.
+                if ((mDisplayContent.mAppTransition.getTransitFlags()
+                        & WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY_NO_ANIMATION) == 0) {
+                    // Only use snapshot of home as starting window when unlocking directly.
                     return false;
                 }
             }
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 46596e3..2f1cc05 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -111,6 +111,7 @@
 import static com.android.server.wm.TaskProto.ADJUST_IME_AMOUNT;
 import static com.android.server.wm.TaskProto.ANIMATING_BOUNDS;
 import static com.android.server.wm.TaskProto.BOUNDS;
+import static com.android.server.wm.TaskProto.CREATED_BY_ORGANIZER;
 import static com.android.server.wm.TaskProto.DEFER_REMOVAL;
 import static com.android.server.wm.TaskProto.DISPLAYED_BOUNDS;
 import static com.android.server.wm.TaskProto.DISPLAY_ID;
@@ -657,8 +658,8 @@
     }
 
     @Override
-    public void resolveOverrideConfiguration(Configuration newParentConfig) {
-        super.resolveOverrideConfiguration(newParentConfig);
+    public void resolveTileOverrideConfiguration(Configuration newParentConfig) {
+        super.resolveTileOverrideConfiguration(newParentConfig);
         if (mTile != null) {
             // If this is a virtual child of a tile, simulate the parent-child relationship
             mTile.updateResolvedConfig(getResolvedOverrideConfiguration());
@@ -731,57 +732,18 @@
                         newBounds);
                 hasNewOverrideBounds = true;
             }
-
-            // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-            if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
-                    || overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-                // If entering split screen or if something about the available split area changes,
-                // recalculate the split windows to match the new configuration.
-                if (rotationChanged || windowingModeChanged
-                        || prevDensity != getConfiguration().densityDpi
-                        || prevScreenW != getConfiguration().screenWidthDp
-                        || prevScreenH != getConfiguration().screenHeightDp) {
-                    calculateDockedBoundsForConfigChange(newParentConfig, newBounds);
-                    hasNewOverrideBounds = true;
-                }
-            }
         }
 
         if (windowingModeChanged) {
-            // Use override windowing mode to prevent extra bounds changes if inheriting the mode.
-            if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
-                getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
-                        newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
-                // immediately resize so docked bounds are available in onSplitScreenModeActivated
-                setTaskDisplayedBounds(null);
-                setTaskBounds(newBounds);
-                setBounds(newBounds);
-                newBounds.set(newBounds);
-            } else if (overrideWindowingMode == WINDOWING_MODE_SPLIT_SCREEN_SECONDARY) {
-                Rect dockedBounds = display.getRootSplitScreenPrimaryTask().getBounds();
-                final boolean isMinimizedDock =
-                        display.mDisplayContent.getDockedDividerController().isMinimizedDock();
-                if (isMinimizedDock) {
-                    Task topTask = display.getRootSplitScreenPrimaryTask().getTopMostTask();
-                    if (topTask != null) {
-                        dockedBounds = topTask.getBounds();
-                    }
-                }
-                getStackDockedModeBounds(dockedBounds, null /* currentTempTaskBounds */,
-                        newBounds /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
-                hasNewOverrideBounds = true;
-            }
+            display.onStackWindowingModeChanged(this);
         }
         if (hasNewOverrideBounds) {
-            if (inSplitScreenPrimaryWindowingMode()) {
-                mStackSupervisor.resizeDockedStackLocked(new Rect(newBounds),
-                        null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        null /* tempOtherTaskBounds */, null /* tempOtherTaskInsetBounds */,
-                        PRESERVE_WINDOWS, true /* deferResume */);
+            if (inSplitScreenWindowingMode()) {
+                setBounds(newBounds);
             } else if (overrideWindowingMode != WINDOWING_MODE_PINNED) {
                 // For pinned stack, resize is now part of the {@link WindowContainerTransaction}
-                resize(new Rect(newBounds), null /* tempTaskBounds */,
-                        null /* tempTaskInsetBounds */, PRESERVE_WINDOWS, true /* deferResume */);
+                resize(new Rect(newBounds), null /* configBounds */,
+                        PRESERVE_WINDOWS, true /* deferResume */);
             }
         }
         if (prevIsAlwaysOnTop != isAlwaysOnTop()) {
@@ -920,11 +882,7 @@
                 // warning toast about it.
                 mAtmService.getTaskChangeNotificationController()
                         .notifyActivityDismissingDockedStack();
-                final ActivityStack primarySplitStack = display.getRootSplitScreenPrimaryTask();
-                primarySplitStack.setWindowingModeInSurfaceTransaction(WINDOWING_MODE_UNDEFINED,
-                        false /* animate */, false /* showRecents */,
-                        false /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
-                        primarySplitStack == this ? creating : false);
+                display.onSplitScreenModeDismissed();
             }
         }
 
@@ -994,8 +952,8 @@
             }
 
             if (!Objects.equals(getRequestedOverrideBounds(), mTmpRect2)) {
-                resize(mTmpRect2, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        false /* preserveWindows */, true /* deferResume */);
+                resize(mTmpRect2, null /*configBounds*/,
+                        false /*preserveWindows*/, true /*deferResume*/);
             }
         } finally {
             if (showRecents && !alreadyInSplitScreenMode && isOnHomeDisplay()
@@ -1160,20 +1118,15 @@
         return r.getTask().mTaskId != taskId && r.appToken != notTop && r.canBeTopRunning();
     }
 
-    ActivityRecord isInStackLocked(IBinder token) {
-        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
-        return isInStackLocked(r);
-    }
-
     ActivityRecord isInStackLocked(ActivityRecord r) {
         if (r == null) {
             return null;
         }
-        final Task task = r.getTask();
-        final ActivityStack stack = r.getRootTask();
-        if (stack != null && task.mChildren.contains(r) && mChildren.contains(task)) {
-            if (stack != this) Slog.w(TAG,
-                    "Illegal state! task does not point to stack it is in.");
+        final Task task = r.getRootTask();
+        if (task != null && r.isDescendantOf(task)) {
+            if (task != this) Slog.w(TAG, "Illegal state! task does not point to stack it is in. "
+                    + "stack=" + this + " task=" + task + " r=" + r
+                    + " callers=" + Debug.getCallers(15, "\n"));
             return r;
         }
         return null;
@@ -1218,7 +1171,7 @@
                     display.getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
             if (topFullScreenStack != null) {
                 final ActivityStack primarySplitScreenStack = display.getRootSplitScreenPrimaryTask();
-                if (display.getIndexOf(topFullScreenStack)
+                if (primarySplitScreenStack != null && display.getIndexOf(topFullScreenStack)
                         > display.getIndexOf(primarySplitScreenStack)) {
                     primarySplitScreenStack.moveToFront(reason + " splitScreenToTop");
                 }
@@ -1249,7 +1202,7 @@
         }
 
         getDisplay().positionStackAtBottom(this, reason);
-        if (task != null) {
+        if (task != null && task != this) {
             positionChildAtBottom(task);
         }
 
@@ -1293,12 +1246,12 @@
         mCurrentUser = userId;
 
         super.switchUser(userId);
-        forAllTasks((t) -> {
-            if (t.showToCurrentUser()) {
+        forAllLeafTasks((t) -> {
+            if (t.showToCurrentUser() && t != this) {
                 mChildren.remove(t);
                 mChildren.add(t);
             }
-        }, true /* traverseTopToBottom */, this);
+        }, true /* traverseTopToBottom */);
     }
 
     void minimalResumeActivityLocked(ActivityRecord r) {
@@ -2492,16 +2445,16 @@
             boolean newTask, boolean keepCurTransition, ActivityOptions options) {
         Task rTask = r.getTask();
         final boolean allowMoveToFront = options == null || !options.getAvoidMoveToFront();
-        final boolean hasTask = hasChild(rTask);
+        final boolean isOrhasTask = rTask == this || hasChild(rTask);
         // mLaunchTaskBehind tasks get placed at the back of the task stack.
-        if (!r.mLaunchTaskBehind && allowMoveToFront && (!hasTask || newTask)) {
+        if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) {
             // Last activity in task had been removed or ActivityManagerService is reusing task.
             // Insert or replace.
             // Might not even be in.
             positionChildAtTop(rTask);
         }
         Task task = null;
-        if (!newTask && hasTask) {
+        if (!newTask && isOrhasTask) {
             final ActivityRecord occludingActivity = getActivity(
                     (ar) -> !ar.finishing && ar.occludesParent(), true, rTask);
             if (occludingActivity != null) {
@@ -2759,7 +2712,7 @@
     void finishVoiceTask(IVoiceInteractionSession session) {
         final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::finishIfVoiceTask,
                 PooledLambda.__(Task.class), session.asBinder());
-        forAllTasks(c, true /* traverseTopToBottom */, this);
+        forAllLeafTasks(c, true /* traverseTopToBottom */);
         c.recycle();
     }
 
@@ -2860,8 +2813,7 @@
             return false;
         }
         final Task task = srec.getTask();
-
-        if (!mChildren.contains(task) || !task.hasChild(srec)) {
+        if (!srec.isDescendantOf(this)) {
             return false;
         }
 
@@ -2974,20 +2926,20 @@
         getDisplay().mDisplayContent.prepareAppTransition(transit, false);
     }
 
-    final void moveTaskToFrontLocked(Task tr, boolean noAnimation, ActivityOptions options,
+    final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
             AppTimeTracker timeTracker, String reason) {
-        moveTaskToFrontLocked(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason);
+        moveTaskToFront(tr, noAnimation, options, timeTracker, !DEFER_RESUME, reason);
     }
 
-    final void moveTaskToFrontLocked(Task tr, boolean noAnimation, ActivityOptions options,
+    final void moveTaskToFront(Task tr, boolean noAnimation, ActivityOptions options,
             AppTimeTracker timeTracker, boolean deferResume, String reason) {
         if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "moveTaskToFront: " + tr);
 
         final ActivityStack topStack = getDisplay().getTopStack();
-        final ActivityRecord topActivity = topStack != null ? topStack.getTopNonFinishingActivity() : null;
-        final int numTasks = getChildCount();
-        final int index = mChildren.indexOf(tr);
-        if (numTasks == 0 || index < 0)  {
+        final ActivityRecord topActivity = topStack != null
+                ? topStack.getTopNonFinishingActivity() : null;
+
+        if (tr != this && !tr.isDescendantOf(this)) {
             // nothing to do!
             if (noAnimation) {
                 ActivityOptions.abort(options);
@@ -3141,24 +3093,30 @@
 
     // TODO: Can only be called from special methods in ActivityStackSupervisor.
     // Need to consolidate those calls points into this resize method so anyone can call directly.
-    void resize(Rect bounds, Rect tempTaskBounds, Rect tempTaskInsetBounds,
-            boolean preserveWindows, boolean deferResume) {
-        if (!updateBoundsAllowed(bounds)) {
+    void resize(Rect displayedBounds, Rect configBounds, boolean preserveWindows,
+            boolean deferResume) {
+        if (!updateBoundsAllowed(displayedBounds)) {
             return;
         }
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "stack.resize_" + getRootTaskId());
         mAtmService.deferWindowLayout();
         try {
+            // TODO: Why not just set this on the stack directly vs. on each tasks?
             // Update override configurations of all tasks in the stack.
-            final Rect taskBounds = tempTaskBounds != null ? tempTaskBounds : bounds;
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     ActivityStack::processTaskResizeBounds, PooledLambda.__(Task.class),
-                    taskBounds, tempTaskInsetBounds);
-            forAllTasks(c, true /* traverseTopToBottom */, this);
+                    displayedBounds, configBounds);
+            forAllTasks(c, true /* traverseTopToBottom */);
             c.recycle();
 
-            setBounds(bounds);
+            if (mBoundsAnimating) {
+                // Force to update task surface bounds and relayout windows, since configBounds
+                // remains unchanged during bounds animation.
+                updateSurfaceBounds();
+                getDisplay().setLayoutNeeded();
+                mWmService.requestTraversal();
+            }
 
             if (!deferResume) {
                 ensureVisibleActivitiesConfiguration(topRunningActivity(), preserveWindows);
@@ -3169,15 +3127,16 @@
         }
     }
 
-    private static void processTaskResizeBounds(Task task, Rect bounds, Rect insetBounds) {
+    private static void processTaskResizeBounds(
+            Task task, Rect displayedBounds, Rect configBounds) {
         if (!task.isResizeable()) return;
 
-        if (insetBounds != null && !insetBounds.isEmpty()) {
-            task.setOverrideDisplayedBounds(bounds);
-            task.setBounds(insetBounds);
+        if (configBounds != null && !configBounds.isEmpty()) {
+            task.setOverrideDisplayedBounds(displayedBounds);
+            task.setBounds(configBounds);
         } else {
             task.setOverrideDisplayedBounds(null);
-            task.setBounds(bounds);
+            task.setBounds(displayedBounds);
         }
     }
 
@@ -3192,7 +3151,7 @@
 
         final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskBounds,
                 PooledLambda.__(Task.class), bounds);
-        forAllTasks(c, true /* traverseTopToBottom */, this);
+        forAllLeafTasks(c, true /* traverseTopToBottom */);
         c.recycle();
     }
 
@@ -3208,7 +3167,7 @@
 
         final PooledConsumer c = PooledLambda.obtainConsumer(ActivityStack::setTaskDisplayedBounds,
                 PooledLambda.__(Task.class), bounds);
-        forAllTasks(c, true /* traverseTopToBottom */, this);
+        forAllLeafTasks(c, true /* traverseTopToBottom */);
         c.recycle();
     }
 
@@ -3304,7 +3263,7 @@
             return false;
         }
         final String prefix = "    ";
-        forAllTasks((task) -> {
+        forAllLeafTasks((task) -> {
             if (needSep) {
                 pw.println("");
             }
@@ -3322,7 +3281,7 @@
                     false /* traverseTopToBottom */);
             dumpHistoryList(fd, pw, activities, prefix, "Hist", true, !dumpAll, dumpClient,
                     dumpPackage, false, null, task);
-        }, true /* traverseTopToBottom */, this);
+        }, true /* traverseTopToBottom */);
         return true;
     }
 
@@ -3373,19 +3332,33 @@
         }
     }
 
-    Task createTask(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
-        return createTask(taskId, info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
+    Task reuseOrCreateTask(ActivityInfo info, Intent intent, boolean toTop) {
+        return reuseOrCreateTask(info, intent, null /*voiceSession*/, null /*voiceInteractor*/,
                 toTop, null /*activity*/, null /*source*/, null /*options*/);
     }
+    // TODO: Can be removed once we change callpoints creating stacks to be creating tasks.
+    /** Either returns this current task to be re-used or creates a new child task. */
+    Task reuseOrCreateTask(ActivityInfo info, Intent intent, IVoiceInteractionSession voiceSession,
+            IVoiceInteractor voiceInteractor, boolean toTop, ActivityRecord activity,
+            ActivityRecord source, ActivityOptions options) {
 
-    Task createTask(int taskId, ActivityInfo info, Intent intent,
-            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
-            boolean toTop, ActivityRecord activity, ActivityRecord source,
-            ActivityOptions options) {
-        final Task task = Task.create(
-                mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
-        // add the task to stack first, mTaskPositioner might need the stack association
-        addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+        Task task;
+        if (DisplayContent.alwaysCreateStack(getWindowingMode(), getActivityType())) {
+            // This stack will only contain one task, so just return itself since all stacks ara now
+            // tasks and all tasks are now stacks.
+            task = reuseAsLeafTask(voiceSession, voiceInteractor, info, activity);
+        } else {
+            // Create child task since this stack can contain multiple tasks.
+            final int taskId = activity != null
+                    ? mStackSupervisor.getNextTaskIdForUser(activity.mUserId)
+                    : mStackSupervisor.getNextTaskIdForUser();
+            task = Task.create(
+                    mAtmService, taskId, info, intent, voiceSession, voiceInteractor, this);
+
+            // add the task to stack first, mTaskPositioner might need the stack association
+            addChild(task, toTop, (info.flags & FLAG_SHOW_FOR_ALL_USERS) != 0);
+        }
+
         int displayId = getDisplayId();
         if (displayId == INVALID_DISPLAY) displayId = DEFAULT_DISPLAY;
         final boolean isLockscreenShown = mAtmService.mStackSupervisor.getKeyguardController()
@@ -3395,6 +3368,7 @@
                 && !matchParentBounds() && task.isResizeable() && !isLockscreenShown) {
             task.setBounds(getRequestedOverrideBounds());
         }
+
         return task;
     }
 
@@ -3601,10 +3575,6 @@
                     "Can't exit pinned mode if it's not pinned already.");
         }
 
-        if (mChildren.size() != 1) {
-            throw new RuntimeException("There should be only one task in a pinned stack.");
-        }
-
         // give pinned stack a chance to save current bounds, this should happen before reparent.
         final ActivityRecord top = topRunningNonOverlayTaskActivity();
         if (top != null && top.isVisible()) {
@@ -3634,12 +3604,12 @@
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 ActivityStackSupervisor::updatePictureInPictureMode, mStackSupervisor,
                 PooledLambda.__(Task.class), targetStackBounds, forceUpdate);
-        forAllTasks(c, true /* traverseTopToBottom */, this);
+        forAllLeafTasks(c, true /* traverseTopToBottom */);
         c.recycle();
     }
 
     void prepareFreezingTaskBounds() {
-        forAllTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */, this);
+        forAllLeafTasks(Task::prepareFreezingBounds, true /* traverseTopToBottom */);
     }
 
     /**
@@ -3671,7 +3641,7 @@
             final PooledConsumer c = PooledLambda.obtainConsumer(Task::alignToAdjustedBounds,
                     PooledLambda.__(Task.class), adjusted ? mAdjustedBounds : getRawBounds(),
                     insetBounds, alignBottom);
-            forAllTasks(c, true /* traverseTopToBottom */, this);
+            forAllLeafTasks(c, true /* traverseTopToBottom */);
             c.recycle();
         }
 
@@ -3944,6 +3914,12 @@
             return;
         }
 
+        if (child == this) {
+            // TODO: Fix call-points
+            moveToFront("positionChildAtTop");
+            return;
+        }
+
         positionChildAt(POSITION_TOP, child, true /* includingParents */);
         child.updateTaskMovement(true);
 
@@ -3999,17 +3975,6 @@
                 ? ((WindowContainer) oldParent).getDisplayContent() : null;
         super.onParentChanged(newParent, oldParent);
 
-        if (display != null && inSplitScreenPrimaryWindowingMode()
-                // only do this for the base stack
-                && !newParent.inSplitScreenPrimaryWindowingMode()) {
-            // If we created a docked stack we want to resize it so it resizes all other stacks
-            // in the system.
-            getStackDockedModeBounds(null /* dockedBounds */, null /* currentTempTaskBounds */,
-                    mTmpRect /* outStackBounds */, mTmpRect2 /* outTempTaskBounds */);
-            mStackSupervisor.resizeDockedStackLocked(getRequestedOverrideBounds(), mTmpRect,
-                    mTmpRect2, null, null, PRESERVE_WINDOWS);
-        }
-
         // Resume next focusable stack after reparenting to another display if we aren't removing
         // the prevous display.
         if (oldDisplay != null && oldDisplay.isRemoving()) {
@@ -4369,19 +4334,19 @@
      * to the list of to be drawn windows the service is waiting for.
      */
     void beginImeAdjustAnimation() {
-        forAllTasks((t) -> {
+        forAllLeafTasks((t) -> {
             if (t.hasContentToDisplay()) {
                 t.setDragResizing(true, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
                 t.setWaitingForDrawnIfResizingChanged();
             }
-        }, true /* traverseTopToBottom */, this);
+        }, true /* traverseTopToBottom */);
     }
 
     /** Resets the resizing state of all windows. */
     void endImeAdjustAnimation() {
-        forAllTasks((t) -> {
+        forAllLeafTasks((t) -> {
             t.setDragResizing(false, DRAG_RESIZE_MODE_DOCKED_DIVIDER);
-        }, true /* traverseTopToBottom */, this);
+        }, true /* traverseTopToBottom */);
     }
 
     private int getMinTopStackBottom(final Rect displayContentRect, int originalStackBottom) {
@@ -4625,19 +4590,15 @@
         return task != null;
     }
 
-    public boolean setPinnedStackSize(Rect stackBounds, Rect tempTaskBounds) {
+    public boolean setPinnedStackSize(Rect displayedBounds, Rect configBounds) {
         // Hold the lock since this is called from the BoundsAnimator running on the UiThread
         synchronized (mWmService.mGlobalLock) {
             if (mCancelCurrentBoundsAnimation) {
                 return false;
             }
+            mStackSupervisor.resizePinnedStack(displayedBounds, configBounds);
         }
 
-        try {
-            mWmService.mActivityTaskManager.resizePinnedStack(stackBounds, tempTaskBounds);
-        } catch (RemoteException e) {
-            // I don't believe you.
-        }
         return true;
     }
 
@@ -4783,7 +4744,7 @@
     /** Called immediately prior to resizing the tasks at the end of the pinned stack animation. */
     void onPipAnimationEndResize() {
         mBoundsAnimating = false;
-        forAllTasks(Task::clearPreserveNonFloatingState, false /* traverseTopToBottom */, this);
+        forAllLeafTasks(Task::clearPreserveNonFloatingState, false /* traverseTopToBottom */);
         mWmService.requestTraversal();
     }
 
@@ -4955,6 +4916,12 @@
     }
 
     @Override
+    public SurfaceControl getParentSurfaceControl() {
+        // Tile is a "virtual" parent, so we need to intercept the parent surface here
+        return mTile != null ? mTile.getSurfaceControl() : super.getParentSurfaceControl();
+    }
+
+    @Override
     void removeImmediately() {
         // TODO(task-hierarchy): remove this override when tiles are in hierarchy
         if (mTile != null) {
@@ -5007,6 +4974,10 @@
         if (!matchParentBounds()) {
             final Rect bounds = getRequestedOverrideBounds();
             bounds.dumpDebug(proto, BOUNDS);
+        } else if (getStack().getTile() != null) {
+            // use tile's bounds here for cts.
+            final Rect bounds = getStack().getTile().getRequestedOverrideBounds();
+            bounds.dumpDebug(proto, BOUNDS);
         }
         getOverrideDisplayedBounds().dumpDebug(proto, DISPLAYED_BOUNDS);
         mAdjustedBounds.dumpDebug(proto, ADJUSTED_BOUNDS);
@@ -5026,6 +4997,8 @@
             proto.write(SURFACE_HEIGHT, mSurfaceControl.getHeight());
         }
 
+        proto.write(CREATED_BY_ORGANIZER, this instanceof TaskTile);
+
         proto.end(token);
     }
 }
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a582f21..97b6388 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -108,6 +108,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
@@ -418,14 +419,29 @@
             mTopTask = fromStack.getTopMostTask();
 
             final PooledConsumer c = PooledLambda.obtainConsumer(
-                    MoveTaskToFullscreenHelper::processTask, this, PooledLambda.__(Task.class));
-            fromStack.forAllTasks(c, false /* traverseTopToBottom */, fromStack);
+                    MoveTaskToFullscreenHelper::processLeafTask, this, PooledLambda.__(Task.class));
+            fromStack.forAllLeafTasks(c, false /* traverseTopToBottom */);
             c.recycle();
             mToDisplay = null;
             mTopTask = null;
         }
 
-        private void processTask(Task task) {
+        private void processLeafTask(Task task) {
+            // This is a one level task that we don't need to create stack for reparenting to.
+            if (task.isRootTask() && DisplayContent.alwaysCreateStack(WINDOWING_MODE_FULLSCREEN,
+                    task.getActivityType())) {
+                final ActivityStack stack = (ActivityStack) task;
+                stack.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+                if (mToDisplay.getDisplayId() != stack.getDisplayId()) {
+                    mToDisplay.moveStackToDisplay(stack, mOnTop);
+                } else if (mOnTop) {
+                    mToDisplay.positionStackAtTop(stack, false /* includingParents */);
+                } else {
+                    mToDisplay.positionStackAtBottom(stack);
+                }
+                return;
+            }
+
             final ActivityStack toStack = mToDisplay.getOrCreateStack(
                     null, mTmpOptions, task, task.getActivityType(), mOnTop);
 
@@ -755,6 +771,14 @@
                         || (intent.getFlags() & Intent.FLAG_ACTIVITY_MATCH_EXTERNAL) != 0) {
                 modifiedFlags |= PackageManager.MATCH_INSTANT;
             }
+            int privateResolveFlags  = 0;
+            if (intent.isWebIntent()
+                        && (intent.getFlags() & Intent.FLAG_ACTIVITY_REQUIRE_NON_BROWSER) != 0) {
+                privateResolveFlags |= PackageManagerInternal.RESOLVE_NON_BROWSER_ONLY;
+            }
+            if ((intent.getFlags() & Intent.FLAG_ACTIVITY_REQUIRE_DEFAULT) != 0) {
+                privateResolveFlags |= PackageManagerInternal.RESOLVE_NON_RESOLVER_ONLY;
+            }
 
             // In order to allow cross-profile lookup, we clear the calling identity here.
             // Note the binder identity won't affect the result, but filterCallingUid will.
@@ -764,7 +788,8 @@
             final long token = Binder.clearCallingIdentity();
             try {
                 return mService.getPackageManagerInternalLocked().resolveIntent(
-                        intent, resolvedType, modifiedFlags, userId, true, filterCallingUid);
+                        intent, resolvedType, modifiedFlags, privateResolveFlags, userId, true,
+                        filterCallingUid);
             } finally {
                 Binder.restoreCallingIdentity(token);
             }
@@ -1418,8 +1443,7 @@
                 // still need moveTaskToFrontLocked() below for any transition settings.
             }
             if (stack.shouldResizeStackWithLaunchBounds()) {
-                stack.resize(bounds, null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        !PRESERVE_WINDOWS, !DEFER_RESUME);
+                stack.resize(bounds, null /* configBounds */, !PRESERVE_WINDOWS, !DEFER_RESUME);
             } else {
                 // WM resizeTask must be done after the task is moved to the correct stack,
                 // because Task's setBounds() also updates dim layer's bounds, but that has
@@ -1433,7 +1457,7 @@
         }
 
         final ActivityRecord r = task.getTopNonFinishingActivity();
-        currentStack.moveTaskToFrontLocked(task, false /* noAnimation */, options,
+        currentStack.moveTaskToFront(task, false /* noAnimation */, options,
                 r == null ? null : r.appTimeTracker, reason);
 
         if (DEBUG_STACK) Slog.d(TAG_STACK,
@@ -1579,7 +1603,7 @@
                 false /* deferResume */);
     }
 
-    void resizeDockedStackLocked(Rect dockedBounds, Rect tempDockedTaskBounds,
+    void resizeDockedStackLocked(Rect displayedBounds, Rect tempDockedTaskBounds,
             Rect tempDockedTaskInsetBounds, Rect tempOtherTaskBounds, Rect tempOtherTaskInsetBounds,
             boolean preserveWindows, boolean deferResume) {
 
@@ -1597,7 +1621,7 @@
 
         if (mDockedStackResizing) {
             mHasPendingDockedBounds = true;
-            mPendingDockedBounds = copyOrNull(dockedBounds);
+            mPendingDockedBounds = copyOrNull(displayedBounds);
             mPendingTempDockedTaskBounds = copyOrNull(tempDockedTaskBounds);
             mPendingTempDockedTaskInsetBounds = copyOrNull(tempDockedTaskInsetBounds);
             mPendingTempOtherTaskBounds = copyOrNull(tempOtherTaskBounds);
@@ -1610,13 +1634,13 @@
             // Don't allow re-entry while resizing. E.g. due to docked stack detaching.
             mAllowDockedStackResize = false;
             ActivityRecord r = stack.topRunningActivity();
-            stack.resize(dockedBounds, tempDockedTaskBounds, tempDockedTaskInsetBounds,
+            stack.resize(displayedBounds, tempDockedTaskBounds,
                     !PRESERVE_WINDOWS, DEFER_RESUME);
 
             // TODO: Checking for isAttached might not be needed as if the user passes in null
             // dockedBounds then they want the docked stack to be dismissed.
             if (stack.getWindowingMode() == WINDOWING_MODE_FULLSCREEN
-                    || (dockedBounds == null && !stack.isAttached())) {
+                    || (displayedBounds == null && !stack.isAttached())) {
                 // The dock stack either was dismissed or went fullscreen, which is kinda the same.
                 // In this case we make all other static stacks fullscreen and move all
                 // docked stack tasks to the fullscreen stack.
@@ -1644,7 +1668,7 @@
                         // interaction.
                         continue;
                     }
-                    current.getStackDockedModeBounds(dockedBounds,
+                    current.getStackDockedModeBounds(displayedBounds,
                             tempOtherTaskBounds /* currentTempTaskBounds */,
                             tempRect /* outStackBounds */,
                             otherTaskRect /* outTempTaskBounds */);
@@ -1659,9 +1683,7 @@
                                 + " non-fullscreen stack");
                     }
 
-                    current.resize(tempRect,
-                            !otherTaskRect.isEmpty() ? otherTaskRect : tempOtherTaskBounds,
-                            tempOtherTaskInsetBounds, preserveWindows, deferResume);
+                    current.resize(tempRect, tempOtherTaskBounds, preserveWindows, deferResume);
                 }
             }
             if (!deferResume) {
@@ -1674,7 +1696,7 @@
         }
     }
 
-    void resizePinnedStackLocked(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+    void resizePinnedStack(Rect displayedBounds, Rect inConfigBounds) {
         // TODO(multi-display): The display containing the stack should be passed in.
         final ActivityStack stack =
                 mRootWindowContainer.getDefaultDisplay().getRootPinnedTask();
@@ -1686,23 +1708,22 @@
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "resizePinnedStack");
         mService.deferWindowLayout();
         try {
-            Rect insetBounds = null;
-            if (tempPinnedTaskBounds != null && stack.isAnimatingBoundsToFullscreen()) {
+            Rect configBounds = null;
+            if (inConfigBounds != null) {
                 // Use 0,0 as the position for the inset rect because we are headed for fullscreen.
-                insetBounds = tempRect;
-                insetBounds.top = 0;
-                insetBounds.left = 0;
-                insetBounds.right = tempPinnedTaskBounds.width();
-                insetBounds.bottom = tempPinnedTaskBounds.height();
+                configBounds = tempRect;
+                configBounds.top = 0;
+                configBounds.left = 0;
+                configBounds.right = inConfigBounds.width();
+                configBounds.bottom = inConfigBounds.height();
             }
-            if (pinnedBounds != null && tempPinnedTaskBounds == null) {
+            if (displayedBounds != null && inConfigBounds == null) {
                 // We have finished the animation into PiP, and are resizing the tasks to match the
                 // stack bounds, while layouts are deferred, update any task state as a part of
                 // transitioning it from fullscreen into a floating state.
                 stack.onPipAnimationEndResize();
             }
-            stack.resize(pinnedBounds, tempPinnedTaskBounds, insetBounds, !PRESERVE_WINDOWS,
-                    !DEFER_RESUME);
+            stack.resize(displayedBounds, configBounds, !PRESERVE_WINDOWS, !DEFER_RESUME);
         } finally {
             mService.continueWindowLayout();
             Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
@@ -1732,7 +1753,7 @@
         } else {
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     ActivityStackSupervisor::processRemoveTask, this, PooledLambda.__(Task.class));
-            stack.forAllTasks(c, true /* traverseTopToBottom */, stack);
+            stack.forAllLeafTasks(c, true /* traverseTopToBottom */);
             c.recycle();
         }
     }
@@ -2447,7 +2468,9 @@
                 // split-screen in split-screen.
                 mService.getTaskChangeNotificationController()
                         .notifyActivityDismissingDockedStack();
-                moveTasksToFullscreenStackLocked(dockedStack, actualStack == dockedStack);
+                dockedStack.getDisplay().onSplitScreenModeDismissed();
+                dockedStack.getDisplay().ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS,
+                        true /* notifyClients */);
             }
             return;
         }
@@ -2743,6 +2766,10 @@
                 deferUpdateRecentsHomeStackBounds();
                 // TODO(multi-display): currently recents animation only support default display.
                 mWindowManager.prepareAppTransition(TRANSIT_DOCK_TASK_FROM_RECENTS, false);
+                // TODO(task-hierarchy): Remove when tiles are in hierarchy.
+                // Unset launching windowing mode to prevent creating split-screen-primary stack
+                // in RWC#anyTaskForId() below.
+                activityOptions.setLaunchWindowingMode(WINDOWING_MODE_UNDEFINED);
             }
 
             task = mRootWindowContainer.anyTaskForId(taskId,
@@ -2752,6 +2779,9 @@
                 mWindowManager.executeAppTransition();
                 throw new IllegalArgumentException(
                         "startActivityFromRecents: Task " + taskId + " not found.");
+            } else if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY
+                    && task.getWindowingMode() != windowingMode) {
+                mService.moveTaskToSplitScreenPrimaryTile(task, true /* toTop */);
             }
 
             if (windowingMode != WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
@@ -2809,7 +2839,7 @@
                 final DisplayContent display = task.getStack().getDisplay();
                 final ActivityStack topSecondaryStack =
                         display.getTopStackInWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-                if (topSecondaryStack.isActivityTypeHome()) {
+                if (topSecondaryStack != null && topSecondaryStack.isActivityTypeHome()) {
                     // If the home activity is the top split-screen secondary stack, then the
                     // primary split-screen stack is in the minimized mode which means it can't
                     // receive input keys, so we should move the focused app to the home app so that
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 2a2ab4b..600a125 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -2366,7 +2366,7 @@
                     // task on top there.
                     // Defer resuming the top activity while moving task to top, since the
                     // current task-top activity may not be the activity that should be resumed.
-                    mTargetStack.moveTaskToFrontLocked(intentTask, mNoAnimation, mOptions,
+                    mTargetStack.moveTaskToFront(intentTask, mNoAnimation, mOptions,
                             mStartActivity.appTimeTracker, DEFER_RESUME,
                             "bringingFoundTaskToFront");
                     mMovedToFront = !isSplitScreenTopStack;
@@ -2396,8 +2396,7 @@
 
     private void setNewTask(Task taskToAffiliate) {
         final boolean toTop = !mLaunchTaskBehind && !mAvoidMoveToFront;
-        final Task task = mTargetStack.createTask(
-                mSupervisor.getNextTaskIdForUser(mStartActivity.mUserId),
+        final Task task = mTargetStack.reuseOrCreateTask(
                 mNewTaskInfo != null ? mNewTaskInfo : mStartActivity.info,
                 mNewTaskIntent != null ? mNewTaskIntent : mIntent, mVoiceSession,
                 mVoiceInteractor, toTop, mStartActivity, mSourceRecord, mOptions);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 132e486..344d4a5 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -37,7 +37,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.content.Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@@ -229,6 +228,7 @@
 import android.view.IRecentsAnimationRunner;
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
+import android.view.WindowContainerTransaction;
 import android.view.WindowManager;
 
 import com.android.internal.R;
@@ -2269,6 +2269,9 @@
         synchronized (mGlobalLock) {
             final long ident = Binder.clearCallingIdentity();
             try {
+                if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
+                    return setTaskWindowingModeSplitScreen(taskId, windowingMode, toTop);
+                }
                 final Task task = mRootWindowContainer.anyTaskForId(taskId,
                         MATCH_TASK_IN_STACKS_ONLY);
                 if (task == null) {
@@ -2286,10 +2289,16 @@
                 }
 
                 final ActivityStack stack = task.getStack();
+                // Convert some windowing-mode changes into root-task reparents for split-screen.
+                if (stack.getTile() != null) {
+                    stack.getDisplay().onSplitScreenModeDismissed();
+                }
                 if (toTop) {
                     stack.moveToFront("setTaskWindowingMode", task);
                 }
                 stack.setWindowingMode(windowingMode);
+                stack.getDisplay().ensureActivitiesVisible(null, 0, PRESERVE_WINDOWS,
+                        true /* notifyClients */);
                 return true;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -2719,36 +2728,8 @@
         synchronized (mGlobalLock) {
             final long ident = Binder.clearCallingIdentity();
             try {
-                if (isInLockTaskMode()) {
-                    Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: Is in lock task mode="
-                            + getLockTaskModeState());
-                    return false;
-                }
-
-                final Task task = mRootWindowContainer.anyTaskForId(taskId,
-                        MATCH_TASK_IN_STACKS_ONLY);
-                if (task == null) {
-                    Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId);
-                    return false;
-                }
-                if (!task.isActivityTypeStandardOrUndefined()) {
-                    throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
-                            + " non-standard task " + taskId + " to split-screen windowing mode");
-                }
-
-                if (DEBUG_STACK) Slog.d(TAG_STACK,
-                        "setTaskWindowingModeSplitScreenPrimary: moving task=" + taskId
-                                + " to createMode=" + createMode + " toTop=" + toTop);
-                mWindowManager.setDockedStackCreateStateLocked(createMode, initialBounds);
-                final int windowingMode = task.getWindowingMode();
-                final ActivityStack stack = task.getStack();
-                if (toTop) {
-                    stack.moveToFront("setTaskWindowingModeSplitScreenPrimary", task);
-                }
-                stack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, animate, showRecents,
-                        false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
-                        false /* creating */);
-                return windowingMode != task.getWindowingMode();
+                return setTaskWindowingModeSplitScreen(taskId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,
+                        toTop);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -2756,6 +2737,56 @@
     }
 
     /**
+     * Moves the specified task into a split-screen tile.
+     */
+    private boolean setTaskWindowingModeSplitScreen(int taskId, int windowingMode, boolean toTop) {
+        if (!WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
+            throw new IllegalArgumentException("Calling setTaskWindowingModeSplitScreen with non"
+                    + "split-screen mode: " + windowingMode);
+        }
+        if (isInLockTaskMode()) {
+            Slog.w(TAG, "setTaskWindowingModeSplitScreen: Is in lock task mode="
+                    + getLockTaskModeState());
+            return false;
+        }
+
+        final Task task = mRootWindowContainer.anyTaskForId(taskId,
+                MATCH_TASK_IN_STACKS_ONLY);
+        if (task == null) {
+            Slog.w(TAG, "setTaskWindowingModeSplitScreenPrimary: No task for id=" + taskId);
+            return false;
+        }
+        if (!task.isActivityTypeStandardOrUndefined()) {
+            throw new IllegalArgumentException("setTaskWindowingMode: Attempt to move"
+                    + " non-standard task " + taskId + " to split-screen windowing mode");
+        }
+        if (!task.supportsSplitScreenWindowingMode()) {
+            return false;
+        }
+
+        final int prevMode = task.getWindowingMode();
+        moveTaskToSplitScreenPrimaryTile(task, toTop);
+        return prevMode != task.getWindowingMode();
+    }
+
+    void moveTaskToSplitScreenPrimaryTile(Task task, boolean toTop) {
+        ActivityStack stack = task.getStack();
+        TaskTile tile = null;
+        for (int i = stack.getDisplay().getStackCount() - 1; i >= 0; --i) {
+            tile = stack.getDisplay().getStackAt(i).asTile();
+            if (tile != null && tile.getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+                break;
+            }
+        }
+        if (tile == null) {
+            throw new IllegalStateException("Can't enter split without associated tile");
+        }
+        WindowContainerTransaction wct = new WindowContainerTransaction();
+        wct.reparent(stack.mRemoteToken, tile.mRemoteToken, toTop);
+        mTaskOrganizerController.applyContainerTransaction(wct, null);
+    }
+
+    /**
      * Removes stacks in the input windowing modes from the system if they are of activity type
      * ACTIVITY_TYPE_STANDARD or ACTIVITY_TYPE_UNDEFINED
      */
@@ -3223,8 +3254,9 @@
                 }
 
                 final ActivityStack stack = r.getRootTask();
-                final Task task = stack.createTask(
-                        mStackSupervisor.getNextTaskIdForUser(r.mUserId), ainfo, intent, !ON_TOP);
+                final Task task = stack.getDisplay().createStack(stack.getWindowingMode(),
+                        stack.getActivityType(), !ON_TOP, ainfo, intent);
+
                 if (!mRecentTasks.addToBottom(task)) {
                     // The app has too many tasks already and we can't add any more
                     stack.removeChild(task, "addAppTask");
@@ -3963,46 +3995,6 @@
     }
 
     /**
-     * Dismisses split-screen multi-window mode.
-     * @param toTop If true the current primary split-screen stack will be placed or left on top.
-     */
-    @Override
-    public void dismissSplitScreenMode(boolean toTop) {
-        enforceCallerIsRecentsOrHasPermission(
-                MANAGE_ACTIVITY_STACKS, "dismissSplitScreenMode()");
-        final long ident = Binder.clearCallingIdentity();
-        try {
-            synchronized (mGlobalLock) {
-                final ActivityStack stack =
-                        mRootWindowContainer.getDefaultDisplay().getRootSplitScreenPrimaryTask();
-                if (stack == null) {
-                    Slog.w(TAG, "dismissSplitScreenMode: primary split-screen stack not found.");
-                    return;
-                }
-
-                if (toTop) {
-                    // Caller wants the current split-screen primary stack to be the top stack after
-                    // it goes fullscreen, so move it to the front.
-                    stack.moveToFront("dismissSplitScreenMode");
-                } else {
-                    // In this case the current split-screen primary stack shouldn't be the top
-                    // stack after it goes fullscreen, so we move the focus to the top-most
-                    // split-screen secondary stack next to it.
-                    final ActivityStack otherStack = stack.getDisplay().getTopStackInWindowingMode(
-                            WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
-                    if (otherStack != null) {
-                        otherStack.moveToFront("dismissSplitScreenMode_other");
-                    }
-                }
-
-                stack.setWindowingMode(WINDOWING_MODE_UNDEFINED);
-            }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-    }
-
-    /**
      * Dismisses Pip
      * @param animate True if the dismissal should be animated.
      * @param animationDuration The duration of the resize animation in milliseconds or -1 if the
@@ -4442,12 +4434,12 @@
     }
 
     @Override
-    public void resizePinnedStack(Rect pinnedBounds, Rect tempPinnedTaskBounds) {
+    public void resizePinnedStack(Rect displayedBounds, Rect configBounds) {
         enforceCallerIsRecentsOrHasPermission(MANAGE_ACTIVITY_STACKS, "resizePinnedStack()");
         final long ident = Binder.clearCallingIdentity();
         try {
             synchronized (mGlobalLock) {
-                mStackSupervisor.resizePinnedStackLocked(pinnedBounds, tempPinnedTaskBounds);
+                mStackSupervisor.resizePinnedStack(displayedBounds, configBounds);
             }
         } finally {
             Binder.restoreCallingIdentity(ident);
diff --git a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
index 9f54e49e0..b1d5359 100644
--- a/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
+++ b/services/core/java/com/android/server/wm/BoundsAnimationTarget.java
@@ -52,7 +52,7 @@
      * animation is now invalid and not required. In such a case, the cancel will trigger the
      * animation end callback as well, but will not send any further size changes.
      */
-    boolean setPinnedStackSize(Rect stackBounds, Rect taskBounds);
+    boolean setPinnedStackSize(Rect displayedBounds, Rect configBounds);
 
     /** Sets the alpha of the animation target */
     boolean setPinnedStackAlpha(float alpha);
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 840abb1..0029dc8 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -16,9 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.app.ActivityTaskManager.INVALID_STACK_ID;
 import static android.app.ActivityTaskManager.INVALID_TASK_ID;
-import static android.app.ActivityTaskManager.SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
@@ -32,6 +30,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.app.WindowConfiguration.isSplitScreenWindowingMode;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -56,9 +55,6 @@
 import static android.view.View.GONE;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
 import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_TOP;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
@@ -84,9 +80,6 @@
 import static android.view.WindowManager.TRANSIT_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_TASK_TO_FRONT;
 
-import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
-import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
-import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -105,12 +98,15 @@
 import static com.android.server.wm.DisplayContentProto.DOCKED_STACK_DIVIDER_CONTROLLER;
 import static com.android.server.wm.DisplayContentProto.DPI;
 import static com.android.server.wm.DisplayContentProto.FOCUSED_APP;
+import static com.android.server.wm.DisplayContentProto.FOCUSED_ROOT_TASK_ID;
 import static com.android.server.wm.DisplayContentProto.ID;
 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
 import static com.android.server.wm.DisplayContentProto.OVERLAY_WINDOWS;
+import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
 import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
 import static com.android.server.wm.DisplayContentProto.ROTATION;
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayContentProto.SINGLE_TASK_INSTANCE;
 import static com.android.server.wm.DisplayContentProto.TASKS;
 import static com.android.server.wm.DisplayContentProto.WINDOW_CONTAINER;
 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
@@ -1553,6 +1549,20 @@
     }
 
     /**
+     * If the provided {@link ActivityRecord} can be displayed in an orientation different from the
+     * display's, it will be rotated to match its requested orientation.
+     *
+     * @see #rotationForActivityInDifferentOrientation(ActivityRecord).
+     * @see WindowToken#applyFixedRotationTransform(DisplayInfo, DisplayFrames, Configuration)
+     */
+    void rotateInDifferentOrientationIfNeeded(ActivityRecord activityRecord) {
+        int rotation = rotationForActivityInDifferentOrientation(activityRecord);
+        if (rotation != NO_ROTATION) {
+            startFixedRotationTransform(activityRecord, rotation);
+        }
+    }
+
+    /**
      * Update rotation of the display.
      *
      * @return {@code true} if the rotation has been changed.  In this case YOU MUST CALL
@@ -2794,54 +2804,9 @@
 
     void adjustForImeIfNeeded() {
         final WindowState imeWin = mInputMethodWindow;
-        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw() && imeWin.isDisplayedLw()
-                && !mDividerControllerLocked.isImeHideRequested();
-        final ActivityStack dockedStack = getRootSplitScreenPrimaryTask();
-        final boolean dockVisible = dockedStack != null;
-        final Task topDockedTask = dockVisible ? dockedStack.getTask((t) -> true): null;
-        final ActivityStack imeTargetStack = mWmService.getImeFocusStackLocked();
-        final int imeDockSide = (dockVisible && imeTargetStack != null) ?
-                imeTargetStack.getDockSide() : DOCKED_INVALID;
-        final boolean imeOnTop = (imeDockSide == DOCKED_TOP);
-        final boolean imeOnBottom = (imeDockSide == DOCKED_BOTTOM);
+        final boolean imeVisible = imeWin != null && imeWin.isVisibleLw()
+                && imeWin.isDisplayedLw();
         final int imeHeight = mDisplayFrames.getInputMethodWindowVisibleHeight();
-        final boolean imeHeightChanged = imeVisible &&
-                imeHeight != mDividerControllerLocked.getImeHeightAdjustedFor();
-
-        // This includes a case where the docked stack is unminimizing and IME is visible for the
-        // bottom side stack. The condition prevents adjusting the override task bounds for IME to
-        // the minimized docked stack bounds.
-        final boolean dockMinimized = mDividerControllerLocked.isMinimizedDock()
-                || (topDockedTask != null && imeOnBottom && !dockedStack.isAdjustedForIme()
-                && dockedStack.getBounds().height() < topDockedTask.getBounds().height());
-
-        // The divider could be adjusted for IME position, or be thinner than usual,
-        // or both. There are three possible cases:
-        // - If IME is visible, and focus is on top, divider is not moved for IME but thinner.
-        // - If IME is visible, and focus is on bottom, divider is moved for IME and thinner.
-        // - If IME is not visible, divider is not moved and is normal width.
-
-        if (imeVisible && dockVisible && (imeOnTop || imeOnBottom) && !dockMinimized) {
-            for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = mTaskContainers.getChildAt(i);
-                final boolean isDockedOnBottom = stack.getDockSide() == DOCKED_BOTTOM;
-                if (stack.isVisible() && (imeOnBottom || isDockedOnBottom)
-                        && stack.inSplitScreenWindowingMode()) {
-                    stack.setAdjustedForIme(imeWin, imeOnBottom && imeHeightChanged);
-                } else {
-                    stack.resetAdjustedForIme(false);
-                }
-            }
-            mDividerControllerLocked.setAdjustedForIme(
-                    imeOnBottom /*ime*/, true /*divider*/, true /*animate*/, imeWin, imeHeight);
-        } else {
-            for (int i = mTaskContainers.getChildCount() - 1; i >= 0; --i) {
-                final ActivityStack stack = mTaskContainers.getChildAt(i);
-                stack.resetAdjustedForIme(!dockVisible);
-            }
-            mDividerControllerLocked.setAdjustedForIme(
-                    false /*ime*/, false /*divider*/, dockVisible /*animate*/, imeWin, imeHeight);
-        }
         mPinnedStackControllerLocked.setAdjustedForIme(imeVisible, imeHeight);
     }
 
@@ -3625,20 +3590,25 @@
         mInputMethodTarget = target;
         mInputMethodTargetWaitingAnim = targetWaitingAnim;
         assignWindowLayers(false /* setLayoutNeeded */);
-        mInputMethodControlTarget = computeImeControlTarget();
-        mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
+        updateImeControlTarget(mInputMethodTarget);
         updateImeParent();
     }
 
     /**
      * IME control target is the window that controls the IME visibility and animation.
      * This window is same as the window on which startInput is called.
-     * @param target the window that receives IME control.
+     * @param target the window that receives IME control. This is ignored if we aren't attaching
+     *               the IME to an app (eg. when in multi-window mode).
      *
      * @see #getImeControlTarget()
      */
-    void updateImeControlTarget(WindowState target) {
-        mInputMethodControlTarget = target;
+    void updateImeControlTarget(InsetsControlTarget target) {
+        if (!isImeAttachedToApp() && mRemoteInsetsControlTarget != null) {
+            mInputMethodControlTarget = mRemoteInsetsControlTarget;
+        } else {
+            // Otherwise, we just use the ime target
+            mInputMethodControlTarget = target;
+        }
         mInsetsStateController.onImeControlTargetChanged(mInputMethodControlTarget);
     }
 
@@ -3671,19 +3641,6 @@
         return mWindowContainers.getSurfaceControl();
     }
 
-    /**
-     * Computes which control-target the IME should be attached to.
-     */
-    @VisibleForTesting
-    InsetsControlTarget computeImeControlTarget() {
-        if (!isImeAttachedToApp() && mRemoteInsetsControlTarget != null) {
-            return mRemoteInsetsControlTarget;
-        }
-
-        // Otherwise, we just use the ime target
-        return mInputMethodTarget;
-    }
-
     void setLayoutNeeded() {
         if (DEBUG_LAYOUT) Slog.w(TAG_WM, "setLayoutNeeded: callers=" + Debug.getCallers(3));
         mLayoutNeeded = true;
@@ -4069,7 +4026,7 @@
         }
     }
 
-    /** @returns the orientation of the display when it's rotation is ROTATION_0. */
+    /** @return the orientation of the display when it's rotation is ROTATION_0. */
     int getNaturalOrientation() {
         return mBaseDisplayWidth < mBaseDisplayHeight
                 ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;
@@ -4458,7 +4415,7 @@
         ArrayList<Task> getVisibleTasks() {
             final ArrayList<Task> visibleTasks = new ArrayList<>();
             forAllTasks(task -> {
-                if (!task.isRootTask() && task.isVisible()) {
+                if (task.isLeafTask() && task.isVisible()) {
                     visibleTasks.add(task);
                 }
             });
@@ -4510,8 +4467,6 @@
                     }
                 } else {
                     mRootSplitScreenPrimaryTask = stack;
-                    mDisplayContent.onSplitScreenModeActivated();
-                    mDividerControllerLocked.notifyDockedStackExistsChanged(true);
                 }
             }
         }
@@ -4523,11 +4478,6 @@
                 mRootPinnedTask = null;
             } else if (stack == mRootSplitScreenPrimaryTask) {
                 mRootSplitScreenPrimaryTask = null;
-                mDisplayContent.onSplitScreenModeDismissed();
-                // Re-set the split-screen create mode whenever the split-screen stack is removed.
-                mWmService.setDockedStackCreateStateLocked(
-                        SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, null /* initialBounds */);
-                mDividerControllerLocked.notifyDockedStackExistsChanged(false);
             }
         }
 
@@ -4587,6 +4537,8 @@
                         true /* includingParents */);
             }
 
+            child.updateTaskMovement(moveToTop);
+
             setLayoutNeeded();
         }
 
@@ -5840,7 +5792,7 @@
         return null;
     }
 
-    boolean alwaysCreateStack(int windowingMode, int activityType) {
+    static boolean alwaysCreateStack(int windowingMode, int activityType) {
         // Always create a stack for fullscreen, freeform, and split-screen-secondary windowing
         // modes so that we can manage visual ordering and return types correctly.
         return activityType == ACTIVITY_TYPE_STANDARD
@@ -5943,6 +5895,33 @@
         return createStackUnchecked(windowingMode, activityType, stackId, onTop, info, intent);
     }
 
+    /** @return the tile to create the next stack in. */
+    private TaskTile updateLaunchTile(int windowingMode) {
+        if (!isSplitScreenWindowingMode(windowingMode)) {
+            // Only split-screen windowing modes interact with tiles.
+            return null;
+        }
+        for (int i = getStackCount() - 1; i >= 0; --i) {
+            final TaskTile t = getStackAt(i).asTile();
+            if (t == null || t.getRequestedOverrideWindowingMode() != windowingMode) {
+                continue;
+            }
+            // If not already set, pick a launch tile which is not the one we are launching
+            // into.
+            if (mLaunchTile == null) {
+                for (int j = 0, n = getStackCount(); j < n; ++j) {
+                    TaskTile tt = getStackAt(j).asTile();
+                    if (tt != t) {
+                        mLaunchTile = tt;
+                        break;
+                    }
+                }
+            }
+            return t;
+        }
+        return mLaunchTile;
+    }
+
     @VisibleForTesting
     ActivityStack createStackUnchecked(int windowingMode, int activityType,
             int stackId, boolean onTop, ActivityInfo info, Intent intent) {
@@ -5955,13 +5934,20 @@
             info.applicationInfo = new ApplicationInfo();
         }
 
+        TaskTile tile = updateLaunchTile(windowingMode);
+        if (tile != null) {
+            // Since this stack will be put into a tile, its windowingMode will be inherited.
+            windowingMode = WINDOWING_MODE_UNDEFINED;
+        }
         final ActivityStack stack = new ActivityStack(this, stackId,
                 mRootWindowContainer.mStackSupervisor, activityType, info, intent);
         addStack(stack, onTop ? POSITION_TOP : POSITION_BOTTOM);
         stack.setWindowingMode(windowingMode, false /* animate */, false /* showRecents */,
                 false /* enteringSplitScreenMode */, false /* deferEnsuringVisibility */,
                 true /* creating */);
-
+        if (tile != null) {
+            tile.addChild(stack, 0 /* index */);
+        }
         return stack;
     }
 
@@ -6181,16 +6167,15 @@
     void onSplitScreenModeDismissed() {
         mAtmService.deferWindowLayout();
         try {
-            // Adjust the windowing mode of any stack in secondary split-screen to fullscreen.
+            mLaunchTile = null;
             for (int i = getStackCount() - 1; i >= 0; --i) {
-                final ActivityStack otherStack = getStackAt(i);
-                if (!otherStack.inSplitScreenSecondaryWindowingMode()) {
-                    continue;
+                final TaskTile t = getStackAt(i).asTile();
+                if (t != null) {
+                    t.removeAllChildren();
                 }
-                otherStack.setWindowingMode(WINDOWING_MODE_UNDEFINED, false /* animate */,
-                        false /* showRecents */, false /* enteringSplitScreenMode */,
-                        true /* deferEnsuringVisibility */, false /* creating */);
             }
+            mDividerControllerLocked.setMinimizedDockedStack(false /* minimized */,
+                    false /* animate */);
         } finally {
             final ActivityStack topFullscreenStack =
                     getTopStackInWindowingMode(WINDOWING_MODE_FULLSCREEN);
@@ -6208,27 +6193,6 @@
         }
     }
 
-    void onSplitScreenModeActivated() {
-        mAtmService.deferWindowLayout();
-        try {
-            // Adjust the windowing mode of any affected by split-screen to split-screen secondary.
-            final ActivityStack splitScreenPrimaryStack = getRootSplitScreenPrimaryTask();
-            for (int i = getStackCount() - 1; i >= 0; --i) {
-                final ActivityStack otherStack = getStackAt(i);
-                if (otherStack == splitScreenPrimaryStack
-                        || !otherStack.affectedBySplitScreenResize()) {
-                    continue;
-                }
-                otherStack.setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,
-                        false /* animate */, false /* showRecents */,
-                        true /* enteringSplitScreenMode */, true /* deferEnsuringVisibility */,
-                        false /* creating */);
-            }
-        } finally {
-            mAtmService.continueWindowLayout();
-        }
-    }
-
     /**
      * Returns true if the {@param windowingMode} is supported based on other parameters passed in.
      * @param windowingMode The windowing mode we are checking support for.
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index a96e3a61..f02a9dd 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -131,7 +131,6 @@
 import android.graphics.Region;
 import android.hardware.input.InputManager;
 import android.hardware.power.V1_0.PowerHint;
-import android.os.Binder;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -304,6 +303,8 @@
 
     private boolean mIsFreeformWindowOverlappingWithNavBar;
 
+    private boolean mLastImmersiveMode;
+
     private final StatusBarController mStatusBarController;
 
     private final BarController mNavigationBarController;
@@ -1183,6 +1184,11 @@
 
         if (transit == TRANSIT_PREVIEW_DONE) {
             if (win.hasAppShownWindows()) {
+                if (win.isActivityTypeHome()) {
+                    // Dismiss the starting window as soon as possible to avoid the crossfade out
+                    // with old content because home is easier to have different UI states.
+                    return ANIMATION_NONE;
+                }
                 if (DEBUG_ANIM) Slog.i(TAG, "**** STARTING EXIT");
                 return R.anim.app_starting_exit;
             }
@@ -3177,8 +3183,8 @@
                     if (nb) mNavigationBarController.showTransient();
                     updateSystemUiVisibilityLw();
                 }
-                mImmersiveModeConfirmation.confirmCurrentPrompt();
             }
+            mImmersiveModeConfirmation.confirmCurrentPrompt();
         }
     }
 
@@ -3205,7 +3211,7 @@
         updateSystemUiVisibilityLw();
     }
 
-    private int updateSystemUiVisibilityLw() {
+    int updateSystemUiVisibilityLw() {
         // If there is no window focused, there will be nobody to handle the events
         // anyway, so just hang on in whatever state we're in until things settle down.
         WindowState winCandidate = mFocusedWindow != null ? mFocusedWindow
@@ -3561,9 +3567,11 @@
         vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
 
         // update navigation bar
-        boolean oldImmersiveMode = isImmersiveMode(oldVis);
-        boolean newImmersiveMode = isImmersiveMode(vis);
+        boolean newInsetsMode = ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_FULL;
+        boolean oldImmersiveMode = newInsetsMode ? mLastImmersiveMode : isImmersiveMode(oldVis);
+        boolean newImmersiveMode = newInsetsMode ? isImmersiveMode(win) : isImmersiveMode(vis);
         if (oldImmersiveMode != newImmersiveMode) {
+            mLastImmersiveMode = newImmersiveMode;
             final String pkg = win.getOwningPackage();
             mImmersiveModeConfirmation.immersiveModeChangedLw(pkg, newImmersiveMode,
                     mService.mPolicy.isUserSetupComplete(),
@@ -3668,6 +3676,7 @@
         }
     }
 
+    // TODO(b/118118435): Remove this after migration
     private boolean isImmersiveMode(int vis) {
         final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
         return mNavigationBar != null
@@ -3676,6 +3685,16 @@
                 && canHideNavigationBar();
     }
 
+    private boolean isImmersiveMode(WindowState win) {
+        final int behavior = win.mAttrs.insetsFlags.behavior;
+        return mNavigationBar != null
+                && canHideNavigationBar()
+                && (behavior == BEHAVIOR_SHOW_BARS_BY_SWIPE
+                        || behavior == BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE)
+                && getInsetsPolicy().isHidden(ITYPE_NAVIGATION_BAR)
+                && win != getNotificationShade();
+    }
+
     /**
      * @return whether the navigation bar can be hidden, e.g. the device has a navigation bar
      */
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 1a0dcb9..57babb0 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -527,9 +527,15 @@
             }
             mService.mH.removeCallbacks(mDisplayRotationHandlerTimeout);
             mIsWaitingForRemoteRotation = false;
-            mDisplayContent.sendNewConfiguration();
-            if (t != null) {
-                mService.mAtmService.mTaskOrganizerController.applyContainerTransaction(t, null);
+            mService.mAtmService.deferWindowLayout();
+            try {
+                mDisplayContent.sendNewConfiguration();
+                if (t != null) {
+                    mService.mAtmService.mTaskOrganizerController.applyContainerTransaction(t,
+                            null /* organizer */);
+                }
+            } finally {
+                mService.mAtmService.continueWindowLayout();
             }
         }
     }
@@ -552,16 +558,14 @@
 
     @VisibleForTesting
     boolean shouldRotateSeamlessly(int oldRotation, int newRotation, boolean forceUpdate) {
-        final WindowState w = mDisplayPolicy.getTopFullscreenOpaqueWindow();
-        if (w == null) {
-            return false;
-        }
         // Display doesn't need to be frozen because application has been started in correct
         // rotation already, so the rest of the windows can use seamless rotation.
-        if (w.mToken.hasFixedRotationTransform()) {
+        if (mDisplayContent.mFixedRotationLaunchingApp != null) {
             return true;
         }
-        if (w != mDisplayContent.mCurrentFocus) {
+
+        final WindowState w = mDisplayPolicy.getTopFullscreenOpaqueWindow();
+        if (w == null || w != mDisplayContent.mCurrentFocus) {
             return false;
         }
         // We only enable seamless rotation if the top window has requested it and is in the
diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java
index 872379e..6431e11 100644
--- a/services/core/java/com/android/server/wm/DockedStackDividerController.java
+++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java
@@ -745,7 +745,7 @@
      * @param minimizedDock Whether the docked stack is currently minimized.
      * @param animate Whether to animate the change.
      */
-    private void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
+    void setMinimizedDockedStack(boolean minimizedDock, boolean animate) {
         final boolean wasMinimized = mMinimizedDock;
         mMinimizedDock = minimizedDock;
         if (minimizedDock == wasMinimized) {
diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index 9d985d7..c92de2b 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -76,7 +76,7 @@
         // to be visible (such as performing Recents animation).
         final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
                 && mContiner.isTopActivityFocusable()
-                && mContiner.isInStackLocked(starting) == null;
+                && (starting == null || !starting.isDescendantOf(mContiner));
 
         final PooledConsumer f = PooledLambda.obtainConsumer(
                 EnsureActivitiesVisibleHelper::setActivityVisibilityState, this,
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index a8fe349..b3890cd 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -182,6 +182,7 @@
         }
         if (changed) {
             notifyInsetsChanged();
+            mDisplayContent.getDisplayPolicy().updateSystemUiVisibilityLw();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 00947d7..44034ed 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -31,14 +31,14 @@
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_TO_SHADE;
 import static android.view.WindowManagerPolicyConstants.KEYGUARD_GOING_AWAY_FLAG_WITH_WALLPAPER;
 
+import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
+import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.KeyguardControllerProto.AOD_SHOWING;
 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_OCCLUDED_STATES;
 import static com.android.server.wm.KeyguardControllerProto.KEYGUARD_SHOWING;
 import static com.android.server.wm.KeyguardOccludedProto.DISPLAY_ID;
 import static com.android.server.wm.KeyguardOccludedProto.KEYGUARD_OCCLUDED;
-import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
-import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -411,8 +411,7 @@
             if (stack == null) {
                 return;
             }
-            mStackSupervisor.moveTasksToFullscreenStackLocked(stack,
-                    stack.isFocusedStackOnDisplay());
+            mRootWindowContainer.getDefaultDisplay().onSplitScreenModeDismissed();
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index b0492be..e92bbaa 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -334,7 +334,7 @@
                         if (sendUserLeaveHint) {
                             // Setting this allows the previous app to PiP.
                             mStackSupervisor.mUserLeaving = true;
-                            targetStack.moveTaskToFrontLocked(targetActivity.getTask(),
+                            targetStack.moveTaskToFront(targetActivity.getTask(),
                                     true /* noAnimation */, null /* activityOptions */,
                                     targetActivity.appTimeTracker,
                                     "RecentsAnimation.onAnimationFinished()");
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 251d0f1..57c877f 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -20,7 +20,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.RemoteAnimationTarget.MODE_CLOSING;
 import static android.view.RemoteAnimationTarget.MODE_OPENING;
-import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 
@@ -34,6 +33,7 @@
 import static com.android.server.wm.WindowManagerInternal.AppTransitionListener;
 
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.WindowConfiguration;
 import android.graphics.Point;
@@ -376,7 +376,7 @@
             final PooledConsumer c = PooledLambda.obtainConsumer((t, outList) ->
 	            { if (!outList.contains(t)) outList.add(t); }, PooledLambda.__(Task.class),
                     visibleTasks);
-            targetStack.forAllTasks(c, true /* traverseTopToBottom */, targetStack);
+            targetStack.forAllLeafTasks(c, true /* traverseTopToBottom */);
             c.recycle();
         }
 
@@ -414,15 +414,15 @@
         }
 
         // Save the minimized home height
-        final ActivityStack dockedStack =
-                mDisplayContent.getRootSplitScreenPrimaryTask();
-        mDisplayContent.getDockedDividerController().getHomeStackBoundsInDockedMode(
-                mDisplayContent.getConfiguration(),
-                dockedStack == null ? DOCKED_INVALID : dockedStack.getDockSide(),
-                mMinimizedHomeBounds);
+        mMinimizedHomeBounds = mDisplayContent.getRootHomeTask().getBounds();
 
         mService.mWindowPlacerLocked.performSurfacePlacement();
 
+        // If the target activity has a fixed orientation which is different from the current top
+        // activity, it will be rotated before being shown so we avoid a screen rotation
+        // animation when showing the Recents view.
+        mDisplayContent.rotateInDifferentOrientationIfNeeded(mTargetActivityRecord);
+
         // Notify that the animation has started
         if (mStatusBar != null) {
             mStatusBar.onRecentsAnimationStateChanged(true /* running */);
@@ -695,6 +695,9 @@
                 mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(
                         mTargetActivityRecord.token);
             }
+            if (mTargetActivityRecord.hasFixedRotationTransform()) {
+                mTargetActivityRecord.clearFixedRotationTransform();
+            }
         }
 
         // Notify that the animation has ended
@@ -828,6 +831,19 @@
         return task != null && isAnimatingTask(task) && !isTargetApp(windowState.mActivityRecord);
     }
 
+    /**
+     * If the animation target ActivityRecord has a fixed rotation ({@link
+     * WindowToken#hasFixedRotationTransform()}, the provided wallpaper will be rotated accordingly.
+     *
+     * This avoids any screen rotation animation when animating to the Recents view.
+     */
+    void applyFixedRotationTransformIfNeeded(@NonNull WindowToken wallpaper) {
+        if (mTargetActivityRecord == null) {
+            return;
+        }
+        wallpaper.applyFixedRotationTransform(mTargetActivityRecord);
+    }
+
     @VisibleForTesting
     class TaskAnimationAdapter implements AnimationAdapter {
 
@@ -844,8 +860,8 @@
             mTask = task;
             mIsRecentTaskInvisible = isRecentTaskInvisible;
             final WindowContainer container = mTask.getParent();
-            container.getRelativeDisplayedPosition(mPosition);
             mBounds.set(container.getDisplayedBounds());
+            mPosition.set(mBounds.left, mBounds.top);
         }
 
         RemoteAnimationTarget createRemoteAnimationTarget() {
diff --git a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
index 63346b9..45f8a15 100644
--- a/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
+++ b/services/core/java/com/android/server/wm/ResetTargetTaskHelper.java
@@ -67,7 +67,7 @@
 
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 ResetTargetTaskHelper::processTask, this, PooledLambda.__(Task.class));
-        targetTask.mWmService.mRoot.forAllTasks(c, true /*traverseTopToBottom*/, mTargetStack);
+        targetTask.mWmService.mRoot.forAllLeafTasks(c, true /*traverseTopToBottom*/);
         c.recycle();
 
         processPendingReparentActivities();
@@ -245,9 +245,8 @@
                 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
                         + r + " out to bottom task " + targetTask);
             } else {
-                targetTask = mTargetStack.createTask(
-                        atmService.mStackSupervisor.getNextTaskIdForUser(r.mUserId), r.info,
-                        null /* intent */, false /* toTop */);
+                targetTask = mTargetStack.reuseOrCreateTask(
+                        r.info, null /*intent*/, false /*toTop*/);
                 targetTask.affinityIntent = r.intent;
                 createdTasks.add(targetTask);
                 if (DEBUG_TASKS) Slog.v(TAG_TASKS, "Start pushing activity "
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 2596452..aa6bdfd 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2137,10 +2137,7 @@
                         r.getActivityType(), ON_TOP, r.info, r.intent);
                 // There are multiple activities in the task and moving the top activity should
                 // reveal/leave the other activities in their original task.
-
-                Task newTask = stack.createTask(mStackSupervisor.getNextTaskIdForUser(r.mUserId),
-                        r.info, r.intent, true);
-                r.reparent(newTask, MAX_VALUE, "moveActivityToStack");
+                r.reparent(stack, MAX_VALUE, "moveActivityToStack");
             }
 
             stack.setWindowingMode(WINDOWING_MODE_PINNED);
@@ -2407,7 +2404,7 @@
         final PooledConsumer c = PooledLambda.obtainConsumer(
                 RootWindowContainer::processTaskForStackInfo, PooledLambda.__(Task.class), info,
                 currentIndex);
-        stack.forAllTasks(c, false /* traverseTopToBottom */, stack);
+        stack.forAllLeafTasks(c, false /* traverseTopToBottom */);
         c.recycle();
 
         final ActivityRecord top = stack.topRunningActivity();
@@ -3302,7 +3299,7 @@
             final PooledConsumer c = PooledLambda.obtainConsumer(
                     RootWindowContainer::taskTopActivityIsUser, this, PooledLambda.__(Task.class),
                     userId);
-            forAllTasks(c);
+            forAllLeafTasks(c, true /* traverseTopToBottom */);
             c.recycle();
         } finally {
             mService.continueWindowLayout();
@@ -3321,14 +3318,6 @@
      * @return {@code true} if the top activity looks like it belongs to {@param userId}.
      */
     private void taskTopActivityIsUser(Task task, @UserIdInt int userId) {
-        // TODO(b/80414790): having utilities to loop for all leaf tasks from caller vs. checking
-        //  leaf tasks here.
-        if (!task.isLeafTask()) {
-            // No op if not a leaf task since we don't want to report root tasks to
-            // TaskStackListeners.
-            return;
-        }
-
         // To handle the case that work app is in the task but just is not the top one.
         final ActivityRecord activityRecord = task.getTopNonFinishingActivity();
         final ActivityRecord resultTo = (activityRecord != null ? activityRecord.resultTo : null);
@@ -3430,18 +3419,8 @@
     }
 
     ActivityRecord isInAnyStack(IBinder token) {
-        int numDisplays = getChildCount();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final DisplayContent display = getChildAt(displayNdx);
-            for (int stackNdx = display.getStackCount() - 1; stackNdx >= 0; --stackNdx) {
-                final ActivityStack stack = display.getStackAt(stackNdx);
-                final ActivityRecord r = stack.isInStackLocked(token);
-                if (r != null) {
-                    return r;
-                }
-            }
-        }
-        return null;
+        final ActivityRecord r = ActivityRecord.forTokenLocked(token);
+        return (r != null && r.isDescendantOf(this)) ? r : null;
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java
index 6ebbf77..9593ea0 100644
--- a/services/core/java/com/android/server/wm/RunningTasks.java
+++ b/services/core/java/com/android/server/wm/RunningTasks.java
@@ -76,7 +76,7 @@
 
         final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
                 PooledLambda.__(Task.class));
-        root.forAllTasks(c, false);
+        root.forAllLeafTasks(c, false);
         c.recycle();
 
         // Take the first {@param maxNum} tasks and create running task infos for them
@@ -93,9 +93,6 @@
     }
 
     private void processTask(Task task) {
-        if (task.isRootTask()) {
-            return;
-        }
         if (task.getTopNonFinishingActivity() == null) {
             // Skip if there are no activities in the task
             return;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 34b5c11..f93e392 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -225,8 +225,8 @@
 
     String affinity;        // The affinity name for this task, or null; may change identity.
     String rootAffinity;    // Initial base affinity, or null; does not change from initial root.
-    final IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
-    final IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
+    IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
+    IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
     Intent intent;          // The original intent that started the task. Note that this value can
                             // be null.
     Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
@@ -422,6 +422,8 @@
     /** When set, will force the task to report as invisible. */
     boolean mForceHidden = false;
 
+    SurfaceControl.Transaction mMainWindowSizeChangeTransaction;
+
     private final FindRootHelper mFindRootHelper = new FindRootHelper();
     private class FindRootHelper {
         private ActivityRecord mRoot;
@@ -571,6 +573,15 @@
         mAtmService.getTaskChangeNotificationController().notifyTaskCreated(_taskId, realActivity);
     }
 
+    Task reuseAsLeafTask(IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor,
+            ActivityInfo info, ActivityRecord activity) {
+        voiceSession = _voiceSession;
+        voiceInteractor = _voiceInteractor;
+        setIntent(activity);
+        setMinDimensions(info);
+        return this;
+    }
+
     private void cleanUpResourcesForDestroy(ConfigurationContainer oldParent) {
         if (hasChild()) {
             return;
@@ -1004,7 +1015,7 @@
     }
 
     /** Sets the original minimal width and height. */
-    private void setMinDimensions(ActivityInfo info) {
+    void setMinDimensions(ActivityInfo info) {
         if (info != null && info.windowLayout != null) {
             mMinWidth = info.windowLayout.minWidth;
             mMinHeight = info.windowLayout.minHeight;
@@ -2145,12 +2156,6 @@
                     // For floating tasks, calculate the smallest width from the bounds of the task
                     inOutConfig.smallestScreenWidthDp = (int) (
                             Math.min(mTmpFullBounds.width(), mTmpFullBounds.height()) / density);
-                } else if (WindowConfiguration.isSplitScreenWindowingMode(windowingMode)) {
-                    // Iterating across all screen orientations, and return the minimum of the task
-                    // width taking into account that the bounds might change because the snap
-                    // algorithm snaps to a different value
-                    inOutConfig.smallestScreenWidthDp =
-                            getSmallestScreenWidthDpForDockedBounds(mTmpFullBounds);
                 }
                 // otherwise, it will just inherit
             }
@@ -2182,16 +2187,20 @@
         return Configuration.reduceScreenLayout(sourceScreenLayout, longSize, shortSize);
     }
 
+    void resolveTileOverrideConfiguration(Configuration newParentConfig) {
+        super.resolveOverrideConfiguration(newParentConfig);
+    }
+
     @Override
     void resolveOverrideConfiguration(Configuration newParentConfig) {
-        if (isRootTask()) {
-            super.resolveOverrideConfiguration(newParentConfig);
+        if (!isLeafTask()) {
+            resolveTileOverrideConfiguration(newParentConfig);
             return;
         }
         mTmpBounds.set(getResolvedOverrideConfiguration().windowConfiguration.getBounds());
-        super.resolveOverrideConfiguration(newParentConfig);
+        resolveTileOverrideConfiguration(newParentConfig);
         int windowingMode =
-                getRequestedOverrideConfiguration().windowConfiguration.getWindowingMode();
+                getResolvedOverrideConfiguration().windowConfiguration.getWindowingMode();
         if (windowingMode == WINDOWING_MODE_UNDEFINED) {
             windowingMode = newParentConfig.windowConfiguration.getWindowingMode();
         }
@@ -2398,7 +2407,7 @@
         final int[] currentCount = {0};
         final PooledConsumer c = PooledLambda.obtainConsumer((t, count) -> { count[0]++; },
                 PooledLambda.__(Task.class), currentCount);
-        forAllTasks(c, false /* traverseTopToBottom */, this);
+        forAllLeafTasks(c, false /* traverseTopToBottom */);
         c.recycle();
         return currentCount[0];
     }
@@ -2620,6 +2629,7 @@
      */
     void setOverrideDisplayedBounds(Rect overrideDisplayedBounds) {
         if (overrideDisplayedBounds != null) {
+            adjustForMinimalTaskDimensions(overrideDisplayedBounds, mOverrideDisplayedBounds);
             mOverrideDisplayedBounds.set(overrideDisplayedBounds);
         } else {
             mOverrideDisplayedBounds.setEmpty();
@@ -3080,16 +3090,33 @@
     }
 
     @Override
-    void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
-        super.forAllTasks(callback, traverseTopToBottom, excludedTask);
-        if (excludedTask != this) {
-            callback.accept(this);
+    void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
+        final int count = mChildren.size();
+        boolean isLeafTask = true;
+        if (traverseTopToBottom) {
+            for (int i = count - 1; i >= 0; --i) {
+                final Task child = mChildren.get(i).asTask();
+                if (child != null) {
+                    isLeafTask = false;
+                    child.forAllLeafTasks(callback, traverseTopToBottom);
+                }
+            }
+        } else {
+            for (int i = 0; i < count; i++) {
+                final Task child = mChildren.get(i).asTask();
+                if (child != null) {
+                    isLeafTask = false;
+                    child.forAllLeafTasks(callback, traverseTopToBottom);
+                }
+            }
         }
+        if (isLeafTask) callback.accept(this);
     }
 
     @Override
     void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
-        forAllTasks(callback, traverseTopToBottom, null /* excludedTask */);
+        super.forAllTasks(callback, traverseTopToBottom);
+        callback.accept(this);
     }
 
     @Override
@@ -3257,6 +3284,10 @@
         return this;
     }
 
+    TaskTile asTile() {
+        return null;
+    }
+
     // TODO(task-merge): Figure-out how this should work with hierarchy tasks.
     boolean shouldBeVisible(ActivityRecord starting) {
         return true;
@@ -3267,7 +3298,7 @@
         pw.print(" effectiveUid="); UserHandle.formatUid(pw, effectiveUid);
         pw.print(" mCallingUid="); UserHandle.formatUid(pw, mCallingUid);
         pw.print(" mUserSetupComplete="); pw.print(mUserSetupComplete);
-        pw.print(" mCallingPackage="); pw.println(mCallingPackage);
+        pw.print(" mCallingPackage="); pw.print(mCallingPackage);
         pw.print(" mCallingFeatureId="); pw.println(mCallingFeatureId);
         if (affinity != null || rootAffinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.print(affinity);
@@ -3981,4 +4012,17 @@
         mAtmService.mTaskOrganizerController.dispatchTaskInfoChanged(
                 this, true /* force */);
     }
+
+    /**
+     * See {@link WindowContainerTransaction#setBoundsChangeTransaction}. In short this
+     * transaction will be consumed by the next BASE_APPLICATION window within our hierarchy
+     * to resize, and it will defer the transaction until that resize frame completes.
+     */
+    void setMainWindowSizeChangeTransaction(SurfaceControl.Transaction t) {
+        mMainWindowSizeChangeTransaction = t;
+    }
+
+    SurfaceControl.Transaction getMainWindowSizeChangeTransaction() {
+        return mMainWindowSizeChangeTransaction;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/TaskOrganizerController.java b/services/core/java/com/android/server/wm/TaskOrganizerController.java
index 4b13a0c..6caa27c 100644
--- a/services/core/java/com/android/server/wm/TaskOrganizerController.java
+++ b/services/core/java/com/android/server/wm/TaskOrganizerController.java
@@ -492,6 +492,10 @@
         if (!(container instanceof Task)) {
             throw new IllegalArgumentException("Invalid container in hierarchy op");
         }
+        if (container.getDisplayContent() == null) {
+            Slog.w(TAG, "Container is no longer attached: " + container);
+            return 0;
+        }
         if (hop.isReparent()) {
             // special case for tiles since they are "virtual" parents
             if (container instanceof ActivityStack && ((ActivityStack) container).isRootTask()) {
@@ -543,8 +547,7 @@
             final ActivityStack stack = (ActivityStack) container;
             if (stack.inPinnedWindowingMode()) {
                 stack.resize(config.windowConfiguration.getBounds(),
-                        null /* tempTaskBounds */, null /* tempTaskInsetBounds */,
-                        PRESERVE_WINDOWS, true /* deferResume */);
+                        null /* configBounds */, PRESERVE_WINDOWS, true /* deferResume */);
             }
         }
     }
@@ -553,6 +556,12 @@
             WindowContainerTransaction.Change c) {
         int effects = sanitizeAndApplyChange(wc, c);
 
+        final SurfaceControl.Transaction t = c.getBoundsChangeTransaction();
+        if (t != null) {
+            Task tr = (Task) wc;
+            tr.setMainWindowSizeChangeTransaction(t);
+        }
+
         Rect enterPipBounds = c.getEnterPipBounds();
         if (enterPipBounds != null) {
             Task tr = (Task) wc;
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotController.java b/services/core/java/com/android/server/wm/TaskSnapshotController.java
index 10d6823..d8091ed 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotController.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotController.java
@@ -559,8 +559,10 @@
                         }
                     });
                     // Allow taking snapshot of home when turning screen off to reduce the delay of
-                    // unlocking/waking to home.
-                    snapshotTasks(mTmpTasks, true /* allowSnapshotHome */);
+                    // waking from secure lock to home.
+                    final boolean allowSnapshotHome =
+                            mService.mPolicy.isKeyguardSecure(mService.mCurrentUserId);
+                    snapshotTasks(mTmpTasks, allowSnapshotHome);
                 }
             } finally {
                 listener.onScreenOff();
diff --git a/services/core/java/com/android/server/wm/TaskTile.java b/services/core/java/com/android/server/wm/TaskTile.java
index 369db05..74d5c33 100644
--- a/services/core/java/com/android/server/wm/TaskTile.java
+++ b/services/core/java/com/android/server/wm/TaskTile.java
@@ -31,7 +31,6 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.util.Slog;
-import android.view.SurfaceControl;
 
 import java.util.ArrayList;
 import java.util.Comparator;
@@ -78,30 +77,9 @@
         // Virtual parent, so don't notify children.
     }
 
-    /**
-     * If there is a disconnection, this will clean up any vestigial surfaces left on the tile
-     * leash by moving known children to a new surfacecontrol and then removing the old one.
-     */
-    void cleanupSurfaces() {
-        if (mSurfaceControl == null) {
-            return;
-        }
-        SurfaceControl oldSurface = mSurfaceControl;
-        WindowContainer parentWin = getParent();
-        if (parentWin == null) {
-            return;
-        }
-        mSurfaceControl = parentWin.makeChildSurface(null).setName("TaskTile " + mTaskId + " - "
-                    + getRequestedOverrideWindowingMode()).setContainerLayer().build();
-        SurfaceControl.Transaction t = parentWin.getPendingTransaction();
-        t.show(mSurfaceControl);
-        for (int i = 0; i < mChildren.size(); ++i) {
-            if (mChildren.get(i).getSurfaceControl() == null) {
-                continue;
-            }
-            mChildren.get(i).reparentSurfaceControl(t, mSurfaceControl);
-        }
-        t.remove(oldSurface);
+    @Override
+    TaskTile asTile() {
+        return this;
     }
 
     @Override
@@ -215,6 +193,12 @@
         super.removeImmediately();
     }
 
+    @Override
+    void taskOrganizerDied() {
+        super.taskOrganizerDied();
+        removeImmediately();
+    }
+
     static TaskTile forToken(IBinder token) {
         try {
             return (TaskTile) ((TaskToken) token).getContainer();
diff --git a/services/core/java/com/android/server/wm/WallpaperWindowToken.java b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
index d23bf97..1e22141 100644
--- a/services/core/java/com/android/server/wm/WallpaperWindowToken.java
+++ b/services/core/java/com/android/server/wm/WallpaperWindowToken.java
@@ -122,10 +122,37 @@
             mDisplayContent.setLayoutNeeded();
         }
 
-        final DisplayInfo displayInfo = mDisplayContent.getDisplayInfo();
+        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+
+        if (visible) {
+            final WindowState wallpaperTarget = wallpaperController.getWallpaperTarget();
+            final RecentsAnimationController recentsAnimationController =
+                    mWmService.getRecentsAnimationController();
+            if (wallpaperTarget != null
+                    && recentsAnimationController != null
+                    && recentsAnimationController.isAnimatingTask(wallpaperTarget.getTask())) {
+                // If the Recents animation is running, and the wallpaper target is the animating
+                // task we want the wallpaper to be rotated in the same orientation as the
+                // RecentsAnimation's target (e.g the launcher)
+                recentsAnimationController.applyFixedRotationTransformIfNeeded(this);
+            } else if (wallpaperTarget != null
+                    && wallpaperTarget.mToken.hasFixedRotationTransform()) {
+                // If the wallpaper target has a fixed rotation, we want the wallpaper to follow its
+                // rotation
+                applyFixedRotationTransform(wallpaperTarget.mToken);
+            } else if (hasFixedRotationTransform()) {
+                clearFixedRotationTransform();
+            }
+        }
+
+        DisplayInfo displayInfo = getFixedRotationTransformDisplayInfo();
+        if (displayInfo == null) {
+            displayInfo = mDisplayContent.getDisplayInfo();
+        }
+
         final int dw = displayInfo.logicalWidth;
         final int dh = displayInfo.logicalHeight;
-        final WallpaperController wallpaperController = mDisplayContent.mWallpaperController;
+
         for (int wallpaperNdx = mChildren.size() - 1; wallpaperNdx >= 0; wallpaperNdx--) {
             final WindowState wallpaper = mChildren.get(wallpaperNdx);
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index da996dc..7a4d0b0 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -615,7 +615,7 @@
     void positionChildAt(int position, E child, boolean includingParents) {
 
         if (child.getParent() != this) {
-            throw new IllegalArgumentException("removeChild: container=" + child.getName()
+            throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
                     + " is not a child of container=" + getName()
                     + " current parent=" + child.getParent());
         }
@@ -1459,15 +1459,15 @@
         }
     }
 
-    void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom, Task excludedTask) {
+    void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
         final int count = mChildren.size();
         if (traverseTopToBottom) {
             for (int i = count - 1; i >= 0; --i) {
-                mChildren.get(i).forAllTasks(callback, traverseTopToBottom, excludedTask);
+                mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
             }
         } else {
             for (int i = 0; i < count; i++) {
-                mChildren.get(i).forAllTasks(callback, traverseTopToBottom, excludedTask);
+                mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index e1f713e..68b8348 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -912,7 +912,7 @@
 
     private void setShadowRenderer() {
         mRenderShadowsInCompositor = Settings.Global.getInt(mContext.getContentResolver(),
-                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 0) != 0;
+                DEVELOPMENT_RENDER_SHADOWS_IN_COMPOSITOR, 1) != 0;
     }
 
     PowerManager mPowerManager;
@@ -1169,9 +1169,10 @@
         mAnimator = new WindowAnimator(this);
         mRoot = new RootWindowContainer(this);
 
-        mUseBLAST = DeviceConfig.getBoolean(
+        mUseBLAST = SystemProperties.getBoolean(
+                    String.join(".", "persist.device_config",
                     DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
-                    WM_USE_BLAST_ADAPTER_FLAG, false);
+                    WM_USE_BLAST_ADAPTER_FLAG), false);
 
         mWindowPlacerLocked = new WindowSurfacePlacer(this);
         mTaskSnapshotController = new TaskSnapshotController(this);
@@ -7491,15 +7492,14 @@
             synchronized (mGlobalLock) {
                 final DisplayContent dc = mRoot.getDisplayContent(displayId);
                 if (dc != null) {
-                    WindowState imeTarget = dc.getImeControlTarget();
-                    if (imeTarget == null) {
+                    InsetsControlTarget imeControlTarget = dc.mInputMethodControlTarget;
+                    if (imeControlTarget == null) {
                         return;
                     }
                     // If there was a pending IME show(), reset it as IME has been
                     // requested to be hidden.
-                    imeTarget.getDisplayContent().getInsetsStateController().getImeSourceProvider()
-                            .abortShowImePostLayout();
-                    imeTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
+                    dc.getInsetsStateController().getImeSourceProvider().abortShowImePostLayout();
+                    imeControlTarget.hideInsets(WindowInsets.Type.ime(), true /* fromIme */);
                 }
             }
         }
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 78d6b9631..b250083 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -1513,8 +1513,7 @@
         // Some system windows (e.g. "Power off" dialog) don't have a task, but we would still
         // associate them with some stack to enable dimming.
         final DisplayContent dc = getDisplayContent();
-        return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null
-                ? dc.getOrCreateRootHomeTask() : null;
+        return mAttrs.type >= FIRST_SYSTEM_WINDOW && dc != null ? dc.getRootHomeTask() : null;
     }
 
     /**
@@ -2687,18 +2686,6 @@
                             mWmService.mTaskSnapshotController.onAppDied(win.mActivityRecord);
                         }
                         win.removeIfPossible(shouldKeepVisibleDeadAppWindow());
-                        if (win.mAttrs.type == TYPE_DOCK_DIVIDER) {
-                            // The owner of the docked divider died :( We reset the docked stack,
-                            // just in case they have the divider at an unstable position. Better
-                            // also reset drag resizing state, because the owner can't do it
-                            // anymore.
-                            final ActivityStack stack =
-                                    dc.getRootSplitScreenPrimaryTask();
-                            if (stack != null) {
-                                stack.resetDockedStackToMiddle();
-                            }
-                            resetSplitScreenResizing = true;
-                        }
                     } else if (mHasSurface) {
                         Slog.e(TAG, "!!! LEAK !!! Window removed but surface still valid.");
                         WindowState.this.removeIfPossible();
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 9552df7..a1a9af6 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -873,6 +873,14 @@
             clipRect = mTmpClipRect;
         }
 
+        if (mSurfaceResized && (mAttrType == TYPE_BASE_APPLICATION) &&
+            (task != null) && (task.getMainWindowSizeChangeTransaction() != null)) {
+            mSurfaceController.deferTransactionUntil(mWin.getDeferTransactionBarrier(),
+                    mWin.getFrameNumber());
+            SurfaceControl.mergeToGlobalTransaction(task.getMainWindowSizeChangeTransaction());
+            task.setMainWindowSizeChangeTransaction(null);
+        }
+
         float surfaceWidth = mSurfaceController.getWidth();
         float surfaceHeight = mSurfaceController.getHeight();
 
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 1180566..48c7812 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -377,6 +377,19 @@
         onConfigurationChanged(getParent().getConfiguration());
     }
 
+    /**
+     * Copies the {@link FixedRotationTransformState} (if any) from the other WindowToken to this
+     * one.
+     */
+    void applyFixedRotationTransform(WindowToken other) {
+        final FixedRotationTransformState fixedRotationState = other.mFixedRotationTransformState;
+        if (fixedRotationState != null) {
+            applyFixedRotationTransform(fixedRotationState.mDisplayInfo,
+                    fixedRotationState.mDisplayFrames,
+                    fixedRotationState.mRotatedOverrideConfiguration);
+        }
+    }
+
     /** Clears the transformation and continue updating the orientation change of display. */
     void clearFixedRotationTransform() {
         if (mFixedRotationTransformState == null) {
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e1615af..336934e 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -55,10 +55,9 @@
 static jclass class_gnssNavigationMessage;
 static jclass class_gnssClock;
 static jclass class_gnssConfiguration_halInterfaceVersion;
-static jclass class_gnssAntennaInfo;
-static jclass class_phaseCenterOffsetCoordinates;
-static jclass class_phaseCenterVariationCorrections;
-static jclass class_signalGainCorrections;
+static jclass class_gnssAntennaInfoBuilder;
+static jclass class_phaseCenterOffset;
+static jclass class_sphericalCorrections;
 static jclass class_arrayList;
 static jclass class_doubleArray;
 
@@ -122,12 +121,16 @@
 static jmethodID method_gnssClockCtor;
 static jmethodID method_gnssMeasurementCtor;
 static jmethodID method_halInterfaceVersionCtor;
-static jmethodID method_gnssAntennaInfoCtor;
-static jmethodID method_phaseCenterOffsetCoordinatesCtor;
-static jmethodID method_phaseCenterVariationCorrectionsCtor;
-static jmethodID method_signalGainCorrectionsCtor;
+static jmethodID method_gnssAntennaInfoBuilderCtor;
+static jmethodID method_phaseCenterOffsetCtor;
+static jmethodID method_sphericalCorrectionsCtor;
 static jmethodID method_arrayListCtor;
 static jmethodID method_arrayListAdd;
+static jmethodID method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz;
+static jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterOffset;
+static jmethodID method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections;
+static jmethodID method_gnssAntennaInfoBuilderSetSignalGainCorrections;
+static jmethodID method_gnssAntennaInfoBuilderBuild;
 
 /*
  * Save a pointer to JavaVm to attach/detach threads executing
@@ -163,7 +166,10 @@
 using MeasurementCorrections_V1_0 = android::hardware::gnss::measurement_corrections::V1_0::MeasurementCorrections;
 using MeasurementCorrections_V1_1 = android::hardware::gnss::measurement_corrections::V1_1::MeasurementCorrections;
 
-using android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+using SingleSatCorrection_V1_0 =
+        android::hardware::gnss::measurement_corrections::V1_0::SingleSatCorrection;
+using SingleSatCorrection_V1_1 =
+        android::hardware::gnss::measurement_corrections::V1_1::SingleSatCorrection;
 using android::hardware::gnss::measurement_corrections::V1_0::ReflectingPlane;
 
 using android::hidl::base::V1_0::IBase;
@@ -1088,7 +1094,7 @@
             const hidl_vec<IGnssAntennaInfoCallback::GnssAntennaInfo>& gnssAntennaInfos);
     jobject translateSingleGnssAntennaInfo(
             JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
-    jobject translatePhaseCenterOffsetCoordinates(
+    jobject translatePhaseCenterOffset(
             JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
     jobject translatePhaseCenterVariationCorrections(
             JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo);
@@ -1150,11 +1156,10 @@
     return arrayList;
 }
 
-jobject GnssAntennaInfoCallback::translatePhaseCenterOffsetCoordinates(
+jobject GnssAntennaInfoCallback::translatePhaseCenterOffset(
         JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
-    jobject phaseCenterOffsetCoordinates =
-            env->NewObject(class_phaseCenterOffsetCoordinates,
-                           method_phaseCenterOffsetCoordinatesCtor,
+    jobject phaseCenterOffset =
+            env->NewObject(class_phaseCenterOffset, method_phaseCenterOffsetCtor,
                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.x,
                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.xUncertainty,
                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.y,
@@ -1162,7 +1167,7 @@
                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.z,
                            gnssAntennaInfo.phaseCenterOffsetCoordinateMillimeters.zUncertainty);
 
-    return phaseCenterOffsetCoordinates;
+    return phaseCenterOffset;
 }
 
 jobject GnssAntennaInfoCallback::translatePhaseCenterVariationCorrections(
@@ -1185,8 +1190,7 @@
     }
 
     jobject phaseCenterVariationCorrections =
-            env->NewObject(class_phaseCenterVariationCorrections,
-                           method_phaseCenterVariationCorrectionsCtor,
+            env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
                            phaseCenterVariationCorrectionsArray,
                            phaseCenterVariationCorrectionsUncertaintiesArray);
 
@@ -1212,7 +1216,7 @@
     }
 
     jobject signalGainCorrections =
-            env->NewObject(class_signalGainCorrections, method_signalGainCorrectionsCtor,
+            env->NewObject(class_sphericalCorrections, method_sphericalCorrectionsCtor,
                            signalGainCorrectionsArray, signalGainCorrectionsUncertaintiesArray);
 
     env->DeleteLocalRef(signalGainCorrectionsArray);
@@ -1223,8 +1227,7 @@
 
 jobject GnssAntennaInfoCallback::translateSingleGnssAntennaInfo(
         JNIEnv* env, const IGnssAntennaInfoCallback::GnssAntennaInfo& gnssAntennaInfo) {
-    jobject phaseCenterOffsetCoordinates =
-            translatePhaseCenterOffsetCoordinates(env, gnssAntennaInfo);
+    jobject phaseCenterOffset = translatePhaseCenterOffset(env, gnssAntennaInfo);
 
     // Nullable
     jobject phaseCenterVariationCorrections =
@@ -1233,13 +1236,29 @@
     // Nullable
     jobject signalGainCorrections = translateSignalGainCorrections(env, gnssAntennaInfo);
 
+    // Get builder
+    jobject gnssAntennaInfoBuilderObject =
+            env->NewObject(class_gnssAntennaInfoBuilder, method_gnssAntennaInfoBuilderCtor);
+
+    // Set fields
+    env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+                          method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz,
+                          gnssAntennaInfo.carrierFrequencyMHz);
+    env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+                          method_gnssAntennaInfoBuilderSetPhaseCenterOffset, phaseCenterOffset);
+    env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+                          method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections,
+                          phaseCenterVariationCorrections);
+    env->CallObjectMethod(gnssAntennaInfoBuilderObject,
+                          method_gnssAntennaInfoBuilderSetSignalGainCorrections,
+                          signalGainCorrections);
+
+    // build
     jobject gnssAntennaInfoObject =
-            env->NewObject(class_gnssAntennaInfo, method_gnssAntennaInfoCtor,
-                           gnssAntennaInfo.carrierFrequencyMHz, phaseCenterOffsetCoordinates,
-                           phaseCenterVariationCorrections, signalGainCorrections);
+            env->CallObjectMethod(gnssAntennaInfoBuilderObject, method_gnssAntennaInfoBuilderBuild);
 
     // Delete Local Refs
-    env->DeleteLocalRef(phaseCenterOffsetCoordinates);
+    env->DeleteLocalRef(phaseCenterOffset);
     env->DeleteLocalRef(phaseCenterVariationCorrections);
     env->DeleteLocalRef(signalGainCorrections);
 
@@ -2004,35 +2023,38 @@
     class_gnssMeasurement = (jclass) env->NewGlobalRef(gnssMeasurementClass);
     method_gnssMeasurementCtor = env->GetMethodID(class_gnssMeasurement, "<init>", "()V");
 
-    jclass gnssAntennaInfoClass = env->FindClass("android/location/GnssAntennaInfo");
-    class_gnssAntennaInfo = (jclass)env->NewGlobalRef(gnssAntennaInfoClass);
-    method_gnssAntennaInfoCtor =
-            env->GetMethodID(class_gnssAntennaInfo, "<init>",
-                             "(D"
-                             "Landroid/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates;"
-                             "Landroid/location/GnssAntennaInfo$PhaseCenterVariationCorrections;"
-                             "Landroid/location/GnssAntennaInfo$SignalGainCorrections;"
-                             ")V");
+    jclass gnssAntennaInfoBuilder = env->FindClass("android/location/GnssAntennaInfo$Builder");
+    class_gnssAntennaInfoBuilder = (jclass)env->NewGlobalRef(gnssAntennaInfoBuilder);
+    method_gnssAntennaInfoBuilderCtor =
+            env->GetMethodID(class_gnssAntennaInfoBuilder, "<init>", "()V");
+    method_gnssAntennaInfoBuilderSetCarrierFrequencyMHz =
+            env->GetMethodID(class_gnssAntennaInfoBuilder, "setCarrierFrequencyMHz",
+                             "(D)Landroid/location/GnssAntennaInfo$Builder;");
+    method_gnssAntennaInfoBuilderSetPhaseCenterOffset =
+            env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterOffset",
+                             "(Landroid/location/GnssAntennaInfo$PhaseCenterOffset;)"
+                             "Landroid/location/GnssAntennaInfo$Builder;");
+    method_gnssAntennaInfoBuilderSetPhaseCenterVariationCorrections =
+            env->GetMethodID(class_gnssAntennaInfoBuilder, "setPhaseCenterVariationCorrections",
+                             "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
+                             "Landroid/location/GnssAntennaInfo$Builder;");
+    method_gnssAntennaInfoBuilderSetSignalGainCorrections =
+            env->GetMethodID(class_gnssAntennaInfoBuilder, "setSignalGainCorrections",
+                             "(Landroid/location/GnssAntennaInfo$SphericalCorrections;)"
+                             "Landroid/location/GnssAntennaInfo$Builder;");
+    method_gnssAntennaInfoBuilderBuild = env->GetMethodID(class_gnssAntennaInfoBuilder, "build",
+                                                          "()Landroid/location/GnssAntennaInfo;");
 
-    jclass phaseCenterOffsetCoordinatesClass =
-            env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffsetCoordinates");
-    class_phaseCenterOffsetCoordinates =
-            (jclass)env->NewGlobalRef(phaseCenterOffsetCoordinatesClass);
-    method_phaseCenterOffsetCoordinatesCtor =
-            env->GetMethodID(class_phaseCenterOffsetCoordinates, "<init>", "(DDDDDD)V");
+    jclass phaseCenterOffsetClass =
+            env->FindClass("android/location/GnssAntennaInfo$PhaseCenterOffset");
+    class_phaseCenterOffset = (jclass)env->NewGlobalRef(phaseCenterOffsetClass);
+    method_phaseCenterOffsetCtor = env->GetMethodID(class_phaseCenterOffset, "<init>", "(DDDDDD)V");
 
-    jclass phaseCenterVariationCorrectionsClass =
-            env->FindClass("android/location/GnssAntennaInfo$PhaseCenterVariationCorrections");
-    class_phaseCenterVariationCorrections =
-            (jclass)env->NewGlobalRef(phaseCenterVariationCorrectionsClass);
-    method_phaseCenterVariationCorrectionsCtor =
-            env->GetMethodID(class_phaseCenterVariationCorrections, "<init>", "([[D[[D)V");
-
-    jclass signalGainCorrectionsClass =
-            env->FindClass("android/location/GnssAntennaInfo$SignalGainCorrections");
-    class_signalGainCorrections = (jclass)env->NewGlobalRef(signalGainCorrectionsClass);
-    method_signalGainCorrectionsCtor =
-            env->GetMethodID(class_signalGainCorrections, "<init>", "([[D[[D)V");
+    jclass sphericalCorrectionsClass =
+            env->FindClass("android/location/GnssAntennaInfo$SphericalCorrections");
+    class_sphericalCorrections = (jclass)env->NewGlobalRef(sphericalCorrectionsClass);
+    method_sphericalCorrectionsCtor =
+            env->GetMethodID(class_sphericalCorrections, "<init>", "([[D[[D)V");
 
     jclass locationClass = env->FindClass("android/location/Location");
     class_location = (jclass) env->NewGlobalRef(locationClass);
@@ -3105,6 +3127,91 @@
     return JNI_FALSE;
 }
 
+static SingleSatCorrection_V1_0 getSingleSatCorrection_1_0_withoutConstellation(
+        JNIEnv* env, jobject singleSatCorrectionObj) {
+    jint correctionFlags = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
+    jint satId = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
+    jfloat carrierFreqHz =
+            env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatCarrierFreq);
+    jfloat probSatIsLos =
+            env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatIsLosProb);
+    jfloat eplMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
+    jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEplUnc);
+    uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
+    jobject reflectingPlaneObj;
+    bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0;
+    if (has_ref_plane) {
+        reflectingPlaneObj =
+                env->CallObjectMethod(singleSatCorrectionObj, method_correctionSatRefPlane);
+    }
+
+    ReflectingPlane reflectingPlane;
+    if (has_ref_plane) {
+        jdouble latitudeDegreesRefPlane =
+                env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLatDeg);
+        jdouble longitudeDegreesRefPlane =
+                env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneLngDeg);
+        jdouble altitudeDegreesRefPlane =
+                env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneAltDeg);
+        jdouble azimuthDegreeRefPlane =
+                env->CallDoubleMethod(reflectingPlaneObj, method_correctionPlaneAzimDeg);
+        reflectingPlane = {
+                .latitudeDegrees = latitudeDegreesRefPlane,
+                .longitudeDegrees = longitudeDegreesRefPlane,
+                .altitudeMeters = altitudeDegreesRefPlane,
+                .azimuthDegrees = azimuthDegreeRefPlane,
+        };
+    }
+
+    SingleSatCorrection_V1_0 singleSatCorrection = {
+            .singleSatCorrectionFlags = corrFlags,
+            .svid = static_cast<uint16_t>(satId),
+            .carrierFrequencyHz = carrierFreqHz,
+            .probSatIsLos = probSatIsLos,
+            .excessPathLengthMeters = eplMeters,
+            .excessPathLengthUncertaintyMeters = eplUncMeters,
+            .reflectingPlane = reflectingPlane,
+    };
+
+    return singleSatCorrection;
+}
+
+static void getSingleSatCorrectionList_1_1(JNIEnv* env, jobject singleSatCorrectionList,
+                                           hidl_vec<SingleSatCorrection_V1_1>& list) {
+    for (uint16_t i = 0; i < list.size(); ++i) {
+        jobject singleSatCorrectionObj =
+                env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+
+        SingleSatCorrection_V1_0 singleSatCorrection_1_0 =
+                getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
+
+        jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
+
+        SingleSatCorrection_V1_1 singleSatCorrection_1_1 = {
+                .v1_0 = singleSatCorrection_1_0,
+                .constellation = static_cast<GnssConstellationType_V2_0>(constType),
+        };
+
+        list[i] = singleSatCorrection_1_1;
+    }
+}
+
+static void getSingleSatCorrectionList_1_0(JNIEnv* env, jobject singleSatCorrectionList,
+                                           hidl_vec<SingleSatCorrection_V1_0>& list) {
+    for (uint16_t i = 0; i < list.size(); ++i) {
+        jobject singleSatCorrectionObj =
+                env->CallObjectMethod(singleSatCorrectionList, method_correctionListGet, i);
+
+        SingleSatCorrection_V1_0 singleSatCorrection =
+                getSingleSatCorrection_1_0_withoutConstellation(env, singleSatCorrectionObj);
+
+        jint constType = env->CallIntMethod(singleSatCorrectionObj, method_correctionSatConstType);
+
+        singleSatCorrection.constellation = static_cast<GnssConstellationType_V1_0>(constType),
+
+        list[i] = singleSatCorrection;
+    }
+}
 static jboolean
     android_location_GnssMeasurementCorrectionsProvider_inject_gnss_measurement_corrections(
         JNIEnv* env,
@@ -3127,64 +3234,6 @@
         ALOGI("Empty correction list injected....Returning with no HAL injection");
         return JNI_TRUE;
     }
-    hidl_vec<SingleSatCorrection> list(len);
-
-    for (uint16_t i = 0; i < len; ++i) {
-        jobject singleSatCorrectionObj = env->CallObjectMethod(
-            singleSatCorrectionList, method_correctionListGet, i);
-
-        jint correctionFlags =
-            env->CallIntMethod(singleSatCorrectionObj, method_correctionSatFlags);
-        jint constType = env->CallIntMethod(singleSatCorrectionObj,
-            method_correctionSatConstType);
-        jint satId =
-            env->CallIntMethod(singleSatCorrectionObj, method_correctionSatId);
-        jfloat carrierFreqHz = env->CallFloatMethod(
-            singleSatCorrectionObj, method_correctionSatCarrierFreq);
-        jfloat probSatIsLos = env->CallFloatMethod(singleSatCorrectionObj,
-            method_correctionSatIsLosProb);
-        jfloat eplMeters =
-            env->CallFloatMethod(singleSatCorrectionObj, method_correctionSatEpl);
-        jfloat eplUncMeters = env->CallFloatMethod(singleSatCorrectionObj,
-            method_correctionSatEplUnc);
-        uint16_t corrFlags = static_cast<uint16_t>(correctionFlags);
-        jobject reflectingPlaneObj;
-        bool has_ref_plane = (corrFlags & GnssSingleSatCorrectionFlags::HAS_REFLECTING_PLANE) != 0;
-        if (has_ref_plane) {
-            reflectingPlaneObj = env->CallObjectMethod(
-                singleSatCorrectionObj, method_correctionSatRefPlane);
-        }
-
-        ReflectingPlane reflectingPlane;
-        if (has_ref_plane) {
-            jdouble latitudeDegreesRefPlane = env->CallDoubleMethod(
-                reflectingPlaneObj, method_correctionPlaneLatDeg);
-            jdouble longitudeDegreesRefPlane = env->CallDoubleMethod(
-                reflectingPlaneObj, method_correctionPlaneLngDeg);
-            jdouble altitudeDegreesRefPlane = env->CallDoubleMethod(
-                reflectingPlaneObj, method_correctionPlaneAltDeg);
-            jdouble azimuthDegreeRefPlane = env->CallDoubleMethod(
-                reflectingPlaneObj, method_correctionPlaneAzimDeg);
-            reflectingPlane = {
-                .latitudeDegrees = latitudeDegreesRefPlane,
-                .longitudeDegrees = longitudeDegreesRefPlane,
-                .altitudeMeters = altitudeDegreesRefPlane,
-                .azimuthDegrees = azimuthDegreeRefPlane,
-            };
-        }
-
-        SingleSatCorrection singleSatCorrection = {
-            .singleSatCorrectionFlags = corrFlags,
-            .constellation = static_cast<GnssConstellationType_V1_0>(constType),
-            .svid = static_cast<uint16_t>(satId),
-            .carrierFrequencyHz = carrierFreqHz,
-            .probSatIsLos = probSatIsLos,
-            .excessPathLengthMeters = eplMeters,
-            .excessPathLengthUncertaintyMeters = eplUncMeters,
-            .reflectingPlane = reflectingPlane,
-        };
-        list[i] = singleSatCorrection;
-    }
 
     jdouble latitudeDegreesCorr = env->CallDoubleMethod(
         correctionsObj, method_correctionsGetLatitudeDegrees);
@@ -3206,7 +3255,6 @@
         .horizontalPositionUncertaintyMeters = horizontalPositionUncertaintyMeters,
         .verticalPositionUncertaintyMeters = verticalPositionUncertaintyMeters,
         .toaGpsNanosecondsOfWeek = static_cast<uint64_t>(toaGpsNanosOfWeek),
-        .satCorrections = list,
     };
 
     if (gnssCorrectionsIface_V1_1 != nullptr) {
@@ -3218,17 +3266,25 @@
         jfloat environmentBearingUncertaintyDegreesCorr = env->CallFloatMethod(
             correctionsObj, method_correctionsGetEnvironmentBearingUncertaintyDegrees);
 
+        hidl_vec<SingleSatCorrection_V1_1> list(len);
+        getSingleSatCorrectionList_1_1(env, singleSatCorrectionList, list);
+
         MeasurementCorrections_V1_1 measurementCorrections_1_1 = {
-            .v1_0 = measurementCorrections_1_0,
-            .hasEnvironmentBearing = static_cast<bool>(hasEnvironmentBearingCorr),
-            .environmentBearingDegrees = environmentBearingDegreesCorr,
-            .environmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegreesCorr,
+                .v1_0 = measurementCorrections_1_0,
+                .hasEnvironmentBearing = static_cast<bool>(hasEnvironmentBearingCorr),
+                .environmentBearingDegrees = environmentBearingDegreesCorr,
+                .environmentBearingUncertaintyDegrees = environmentBearingUncertaintyDegreesCorr,
+                .satCorrections = list,
         };
 
         auto result = gnssCorrectionsIface_V1_1->setCorrections_1_1(measurementCorrections_1_1);
         return checkHidlReturn(result, "IMeasurementCorrections 1.1 setCorrections() failed.");
     }
 
+    hidl_vec<SingleSatCorrection_V1_0> list(len);
+    getSingleSatCorrectionList_1_0(env, singleSatCorrectionList, list);
+    measurementCorrections_1_0.satCorrections = list;
+
     auto result = gnssCorrectionsIface_V1_0->setCorrections(measurementCorrections_1_0);
     return checkHidlReturn(result, "IMeasurementCorrections 1.0 setCorrections() failed.");
 }
diff --git a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
index 70a9c09..f445aa8 100644
--- a/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
+++ b/services/core/jni/com_android_server_pm_PackageManagerShellCommandDataLoader.cpp
@@ -190,6 +190,7 @@
 }
 
 static inline int32_t skipIdSigHeaders(borrowed_fd fd) {
+    readBEInt32(fd);        // version
     readBytes(fd);          // verityRootHash
     readBytes(fd);          // v3Digest
     readBytes(fd);          // pkcs7SignatureBlock
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 9b85a7b..eff222a 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -82,4 +82,8 @@
     public long getManagedProfileMaximumTimeOff(ComponentName admin) {
         return 0;
     }
+
+    public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
+        return false;
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 731cd1e..46d8800 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -48,6 +48,7 @@
 import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.ENCRYPTION_STATUS_ACTIVE_PER_USER;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_INDIVIDUAL_ATTESTATION;
@@ -179,14 +180,12 @@
 import android.content.pm.ServiceInfo;
 import android.content.pm.StringParceledListSlice;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.location.LocationManager;
-import android.location.LocationManagerInternal;
 import android.media.AudioManager;
 import android.media.IAudioService;
 import android.net.ConnectivityManager;
@@ -289,6 +288,7 @@
 import com.android.server.inputmethod.InputMethodManagerInternal;
 import com.android.server.net.NetworkPolicyManagerInternal;
 import com.android.server.pm.UserRestrictionsUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.storage.DeviceStorageMonitorInternal;
 import com.android.server.uri.UriGrantsManagerInternal;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -444,10 +444,13 @@
     });
 
     /**
-     *  System property whose value is either "true" or "false", indicating whether
-     *  device owner is present.
+     * System property whose value indicates whether the device is fully owned by an organization:
+     * it can be either a device owner device, or a device with an organization-owned managed
+     * profile.
+     *
+     * <p>The state is stored as a Boolean string.
      */
-    private static final String PROPERTY_DEVICE_OWNER_PRESENT = "ro.device_owner";
+    private static final String PROPERTY_ORGANIZATION_OWNED = "ro.organization_owned";
 
     private static final int STATUS_BAR_DISABLE_MASK =
             StatusBarManager.DISABLE_EXPAND |
@@ -480,6 +483,7 @@
 
         GLOBAL_SETTINGS_WHITELIST = new ArraySet<>();
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_ENABLED);
+        GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.ADB_WIFI_ENABLED);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.AUTO_TIME_ZONE);
         GLOBAL_SETTINGS_WHITELIST.add(Settings.Global.DATA_ROAMING);
@@ -1072,7 +1076,8 @@
         private static final String TAG_SUSPEND_PERSONAL_APPS = "suspend-personal-apps";
         private static final String TAG_PROFILE_MAXIMUM_TIME_OFF = "profile-max-time-off";
         private static final String TAG_PROFILE_OFF_DEADLINE = "profile-off-deadline";
-
+        private static final String TAG_ALWAYS_ON_VPN_PACKAGE = "vpn-package";
+        private static final String TAG_ALWAYS_ON_VPN_LOCKDOWN = "vpn-lockdown";
         DeviceAdminInfo info;
 
 
@@ -1201,6 +1206,9 @@
         // Time by which the profile should be turned on according to System.currentTimeMillis().
         long mProfileOffDeadline = 0;
 
+        public String mAlwaysOnVpnPackage;
+        public boolean mAlwaysOnVpnLockdown;
+
 
         ActiveAdmin(DeviceAdminInfo _info, boolean parent) {
             info = _info;
@@ -1441,6 +1449,12 @@
             if (mProfileMaximumTimeOff != 0) {
                 writeAttributeValueToXml(out, TAG_PROFILE_OFF_DEADLINE, mProfileOffDeadline);
             }
+            if (!TextUtils.isEmpty(mAlwaysOnVpnPackage)) {
+                writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_PACKAGE, mAlwaysOnVpnPackage);
+            }
+            if (mAlwaysOnVpnLockdown) {
+                writeAttributeValueToXml(out, TAG_ALWAYS_ON_VPN_LOCKDOWN, mAlwaysOnVpnLockdown);
+            }
         }
 
         void writeTextToXml(XmlSerializer out, String tag, String text) throws IOException {
@@ -1686,6 +1700,11 @@
                 } else if (TAG_PROFILE_OFF_DEADLINE.equals(tag)) {
                     mProfileOffDeadline =
                             Long.parseLong(parser.getAttributeValue(null, ATTR_VALUE));
+                } else if (TAG_ALWAYS_ON_VPN_PACKAGE.equals(tag)) {
+                    mAlwaysOnVpnPackage = parser.getAttributeValue(null, ATTR_VALUE);
+                } else if (TAG_ALWAYS_ON_VPN_LOCKDOWN.equals(tag)) {
+                    mAlwaysOnVpnLockdown = Boolean.parseBoolean(
+                            parser.getAttributeValue(null, ATTR_VALUE));
                 } else {
                     Slog.w(LOG_TAG, "Unknown admin tag: " + tag);
                     XmlUtils.skipCurrentTag(parser);
@@ -1918,6 +1937,10 @@
                 pw.println(mProfileMaximumTimeOff);
             pw.print("mProfileOffDeadline=");
                 pw.println(mProfileOffDeadline);
+            pw.print("mAlwaysOnVpnPackage=");
+            pw.println(mAlwaysOnVpnPackage);
+            pw.print("mAlwaysOnVpnLockdown=");
+            pw.println(mAlwaysOnVpnLockdown);
         }
     }
 
@@ -2111,10 +2134,6 @@
             return mContext.getSystemService(LocationManager.class);
         }
 
-        LocationManagerInternal getLocationManagerInternal() {
-            return LocalServices.getService(LocationManagerInternal.class);
-        }
-
         IWindowManager getIWindowManager() {
             return IWindowManager.Stub
                     .asInterface(ServiceManager.getService(Context.WINDOW_SERVICE));
@@ -2290,6 +2309,11 @@
                     context, requestCode, intent, flags, options, user);
         }
 
+        PendingIntent pendingIntentGetBroadcast(
+                Context context, int requestCode, Intent intent, int flags) {
+            return PendingIntent.getBroadcast(context, requestCode, intent, flags);
+        }
+
         void registerContentObserver(Uri uri, boolean notifyForDescendents,
                 ContentObserver observer, int userHandle) {
             mContext.getContentResolver().registerContentObserver(uri, notifyForDescendents,
@@ -2530,7 +2554,7 @@
     void loadOwners() {
         synchronized (getLockObject()) {
             mOwners.load();
-            setDeviceOwnerSystemPropertyLocked();
+            setDeviceOwnershipSystemPropertyLocked();
             findOwnerComponentIfNecessaryLocked();
             migrateUserRestrictionsIfNecessaryLocked();
 
@@ -2732,34 +2756,36 @@
         }
     }
 
-    private void setDeviceOwnerSystemPropertyLocked() {
-        final boolean deviceProvisioned =
-                mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-        final boolean hasDeviceOwner = mOwners.hasDeviceOwner();
-        // If the device is not provisioned and there is currently no device owner, do not set the
-        // read-only system property yet, since Device owner may still be provisioned.
-        if (!hasDeviceOwner && !deviceProvisioned) {
-            return;
-        }
-        // Still at the first stage of CryptKeeper double bounce, mOwners.hasDeviceOwner is
-        // always false at this point.
+    private void setDeviceOwnershipSystemPropertyLocked() {
+        // Still at the first stage of CryptKeeper double bounce, nothing can be learnt about
+        // the real system at this point.
         if (StorageManager.inCryptKeeperBounce()) {
             return;
         }
-
-        if (!mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT, "").isEmpty()) {
-            Slog.w(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
-        } else {
-            final String value = Boolean.toString(hasDeviceOwner);
-            mInjector.systemPropertiesSet(PROPERTY_DEVICE_OWNER_PRESENT, value);
-            Slog.i(LOG_TAG, "Set ro.device_owner property to " + value);
+        final boolean deviceProvisioned =
+                mInjector.settingsGlobalGetInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        final boolean hasDeviceOwner = mOwners.hasDeviceOwner();
+        final boolean hasOrgOwnedProfile = isOrganizationOwnedDeviceWithManagedProfile();
+        // If the device is not provisioned and there is currently no management, do not set the
+        // read-only system property yet, since device owner / org-owned profile may still be
+        // provisioned.
+        if (!hasDeviceOwner && !hasOrgOwnedProfile && !deviceProvisioned) {
+            return;
+        }
+        final String value = Boolean.toString(hasDeviceOwner || hasOrgOwnedProfile);
+        final String currentVal = mInjector.systemPropertiesGet(PROPERTY_ORGANIZATION_OWNED, null);
+        if (TextUtils.isEmpty(currentVal)) {
+            Slog.i(LOG_TAG, "Set ro.organization_owned property to " + value);
+            mInjector.systemPropertiesSet(PROPERTY_ORGANIZATION_OWNED, value);
+        } else if (!value.equals(currentVal)) {
+            Slog.w(LOG_TAG, "Cannot change existing ro.organization_owned to " + value);
         }
     }
 
     private void maybeStartSecurityLogMonitorOnActivityManagerReady() {
         synchronized (getLockObject()) {
             if (mInjector.securityLogIsLoggingEnabled()) {
-                mSecurityLogMonitor.start();
+                mSecurityLogMonitor.start(getSecurityLoggingEnabledUser());
                 mInjector.runCryptoSelfTest();
                 maybePauseDeviceWideLoggingLocked();
             }
@@ -6775,10 +6801,10 @@
      * @throws UnsupportedOperationException if the package does not support being set as always-on.
      */
     @Override
-    public boolean setAlwaysOnVpnPackage(ComponentName admin, String vpnPackage, boolean lockdown,
+    public boolean setAlwaysOnVpnPackage(ComponentName who, String vpnPackage, boolean lockdown,
             List<String> lockdownWhitelist)
             throws SecurityException {
-        enforceProfileOrDeviceOwner(admin);
+        enforceProfileOrDeviceOwner(who);
 
         final int userId = mInjector.userHandleGetCallingUserId();
         mInjector.binderWithCleanCallingIdentity(() -> {
@@ -6804,12 +6830,22 @@
             }
             DevicePolicyEventLogger
                     .createEvent(DevicePolicyEnums.SET_ALWAYS_ON_VPN_PACKAGE)
-                    .setAdmin(admin)
+                    .setAdmin(who)
                     .setStrings(vpnPackage)
                     .setBoolean(lockdown)
                     .setInt(lockdownWhitelist != null ? lockdownWhitelist.size() : 0)
                     .write();
         });
+        synchronized (getLockObject()) {
+            ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+                    DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            if (!TextUtils.equals(vpnPackage, admin.mAlwaysOnVpnPackage)
+                    || lockdown != admin.mAlwaysOnVpnLockdown) {
+                admin.mAlwaysOnVpnPackage = vpnPackage;
+                admin.mAlwaysOnVpnLockdown = lockdown;
+                saveSettingsLocked(userId);
+            }
+        }
         return true;
     }
 
@@ -6823,6 +6859,15 @@
     }
 
     @Override
+    public String getAlwaysOnVpnPackageForUser(int userHandle) {
+        enforceSystemCaller("getAlwaysOnVpnPackageForUser");
+        synchronized (getLockObject()) {
+            ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle);
+            return admin != null ? admin.mAlwaysOnVpnPackage : null;
+        }
+    }
+
+    @Override
     public boolean isAlwaysOnVpnLockdownEnabled(ComponentName admin) throws SecurityException {
         enforceProfileOrDeviceOwner(admin);
 
@@ -6832,6 +6877,15 @@
     }
 
     @Override
+    public boolean isAlwaysOnVpnLockdownEnabledForUser(int userHandle) {
+        enforceSystemCaller("isAlwaysOnVpnLockdownEnabledForUser");
+        synchronized (getLockObject()) {
+            ActiveAdmin admin = getDeviceOrProfileOwnerAdminLocked(userHandle);
+            return admin != null ? admin.mAlwaysOnVpnLockdown : null;
+        }
+    }
+
+    @Override
     public List<String> getAlwaysOnVpnLockdownWhitelist(ComponentName admin)
             throws SecurityException {
         enforceProfileOrDeviceOwner(admin);
@@ -7036,9 +7090,13 @@
             saveSettingsLocked(userId);
         }
 
-        mInjector.binderWithCleanCallingIdentity(() -> mContext.sendBroadcastAsUser(
-                new Intent(DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED),
-                UserHandle.getUserHandleForUid(frpManagementAgentUid)));
+        final Intent intent = new Intent(
+                DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED).addFlags(
+                Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND | Intent.FLAG_RECEIVER_FOREGROUND);
+
+        mInjector.binderWithCleanCallingIdentity(() -> mContext.sendBroadcastAsUser(intent,
+                UserHandle.getUserHandleForUid(frpManagementAgentUid),
+                android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.SET_FACTORY_RESET_PROTECTION)
@@ -8339,7 +8397,7 @@
             mOwners.setDeviceOwner(admin, ownerName, userId);
             mOwners.writeDeviceOwner();
             updateDeviceOwnerLocked();
-            setDeviceOwnerSystemPropertyLocked();
+            setDeviceOwnershipSystemPropertyLocked();
 
             mInjector.binderWithCleanCallingIdentity(() -> {
                 // Restrict adding a managed profile when a device owner is set on the device.
@@ -8977,6 +9035,19 @@
         return null;
     }
 
+    /**
+     * Returns the ActiveAdmin associated wit the PO or DO on the given user.
+     * @param userHandle
+     * @return
+     */
+    private @Nullable ActiveAdmin getDeviceOrProfileOwnerAdminLocked(int userHandle) {
+        ActiveAdmin admin = getProfileOwnerAdminLocked(userHandle);
+        if (admin == null && getDeviceOwnerUserId() == userHandle) {
+            admin = getDeviceOwnerAdminLocked();
+        }
+        return admin;
+    }
+
     @GuardedBy("getLockObject()")
     ActiveAdmin getProfileOwnerOfOrganizationOwnedDeviceLocked(int userHandle) {
         return mInjector.binderWithCleanCallingIdentity(() -> {
@@ -9006,21 +9077,21 @@
         return getApplicationLabel(profileOwner.getPackageName(), userHandle);
     }
 
+    private @UserIdInt int getOrganizationOwnedProfileUserId() {
+        for (UserInfo ui : mUserManagerInternal.getUserInfos()) {
+            if (ui.isManagedProfile() && isProfileOwnerOfOrganizationOwnedDevice(ui.id)) {
+                return ui.id;
+            }
+        }
+        return UserHandle.USER_NULL;
+    }
+
     @Override
     public boolean isOrganizationOwnedDeviceWithManagedProfile() {
         if (!mHasFeature) {
             return false;
         }
-
-        return mInjector.binderWithCleanCallingIdentity(() -> {
-            for (UserInfo ui : mUserManager.getUsers()) {
-                if (ui.isManagedProfile() && isProfileOwnerOfOrganizationOwnedDevice(ui.id)) {
-                    return true;
-                }
-            }
-
-            return false;
-        });
+        return getOrganizationOwnedProfileUserId() != UserHandle.USER_NULL;
     }
 
     @Override
@@ -10036,35 +10107,6 @@
         }
     }
 
-    private boolean checkCallerIsCurrentUserOrProfile() {
-        final int callingUserId = UserHandle.getCallingUserId();
-        final long token = mInjector.binderClearCallingIdentity();
-        try {
-            UserInfo currentUser;
-            UserInfo callingUser = getUserInfo(callingUserId);
-            try {
-                currentUser = mInjector.getIActivityManager().getCurrentUser();
-            } catch (RemoteException e) {
-                Slog.e(LOG_TAG, "Failed to talk to activity managed.", e);
-                return false;
-            }
-
-            if (callingUser.isManagedProfile() && callingUser.profileGroupId != currentUser.id) {
-                Slog.e(LOG_TAG, "Cannot set permitted input methods for managed profile "
-                        + "of a user that isn't the foreground user.");
-                return false;
-            }
-            if (!callingUser.isManagedProfile() && callingUserId != currentUser.id ) {
-                Slog.e(LOG_TAG, "Cannot set permitted input methods "
-                        + "of a user that isn't the foreground user.");
-                return false;
-            }
-        } finally {
-            mInjector.binderRestoreCallingIdentity(token);
-        }
-        return true;
-    }
-
     @Override
     public boolean setPermittedInputMethods(ComponentName who, List packageList) {
         if (!mHasFeature) {
@@ -11662,17 +11704,6 @@
     }
 
     @Override
-    public void requestSetLocationProviderAllowed(ComponentName who, String provider,
-            boolean providerAllowed) {
-        Objects.requireNonNull(who, "ComponentName is null");
-        enforceDeviceOwner(who);
-
-        mInjector.binderWithCleanCallingIdentity(
-                () -> mInjector.getLocationManagerInternal().requestSetProviderAllowed(provider,
-                        providerAllowed));
-    }
-
-    @Override
     public boolean setTime(ComponentName who, long millis) {
         Objects.requireNonNull(who, "ComponentName is null in setTime");
         enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(who);
@@ -12021,7 +12052,7 @@
                 synchronized (getLockObject()) {
                     // Set PROPERTY_DEVICE_OWNER_PRESENT, for the SUW case where setting the property
                     // is delayed until device is marked as provisioned.
-                    setDeviceOwnerSystemPropertyLocked();
+                    setDeviceOwnershipSystemPropertyLocked();
                 }
             } else if (mDefaultImeChanged.equals(uri)) {
                 synchronized (getLockObject()) {
@@ -13646,6 +13677,22 @@
         });
     }
 
+    private boolean canStartSecurityLogging() {
+        synchronized (getLockObject()) {
+            return isOrganizationOwnedDeviceWithManagedProfile()
+                    || areAllUsersAffiliatedWithDeviceLocked();
+        }
+    }
+
+    private @UserIdInt int getSecurityLoggingEnabledUser() {
+        synchronized (getLockObject()) {
+            if (mOwners.hasDeviceOwner()) {
+                return UserHandle.USER_ALL;
+            }
+        }
+        return getOrganizationOwnedProfileUserId();
+    }
+
     @Override
     public void setSecurityLoggingEnabled(ComponentName admin, boolean enabled) {
         if (!mHasFeature) {
@@ -13654,13 +13701,14 @@
         Objects.requireNonNull(admin);
 
         synchronized (getLockObject()) {
-            getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+            getActiveAdminForCallerLocked(admin,
+                    DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
             if (enabled == mInjector.securityLogGetLoggingEnabledProperty()) {
                 return;
             }
             mInjector.securityLogSetLoggingEnabledProperty(enabled);
             if (enabled) {
-                mSecurityLogMonitor.start();
+                mSecurityLogMonitor.start(getSecurityLoggingEnabledUser());
                 maybePauseDeviceWideLoggingLocked();
             } else {
                 mSecurityLogMonitor.stop();
@@ -13682,7 +13730,8 @@
         synchronized (getLockObject()) {
             if (!isCallerWithSystemUid()) {
                 Objects.requireNonNull(admin);
-                getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
+                getActiveAdminForCallerLocked(admin,
+                        DeviceAdminInfo.USES_POLICY_ORGANIZATION_OWNED_PROFILE_OWNER);
             }
             return mInjector.securityLogGetLoggingEnabledProperty();
         }
@@ -13706,7 +13755,10 @@
         }
 
         Objects.requireNonNull(admin);
-        ensureDeviceOwnerAndAllUsersAffiliated(admin);
+        enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
+        if (!isOrganizationOwnedDeviceWithManagedProfile()) {
+            ensureAllUsersAffiliated();
+        }
 
         DevicePolicyEventLogger
                 .createEvent(DevicePolicyEnums.RETRIEVE_PRE_REBOOT_SECURITY_LOGS)
@@ -13722,6 +13774,10 @@
         ArrayList<SecurityEvent> output = new ArrayList<SecurityEvent>();
         try {
             SecurityLog.readPreviousEvents(output);
+            int enabledUser = getSecurityLoggingEnabledUser();
+            if (enabledUser != UserHandle.USER_ALL) {
+                SecurityLog.redactEvents(output, enabledUser);
+            }
             return new ParceledListSlice<SecurityEvent>(output);
         } catch (IOException e) {
             Slog.w(LOG_TAG, "Fail to read previous events" , e);
@@ -13736,7 +13792,10 @@
         }
 
         Objects.requireNonNull(admin);
-        ensureDeviceOwnerAndAllUsersAffiliated(admin);
+        enforceDeviceOwnerOrProfileOwnerOnOrganizationOwnedDevice(admin);
+        if (!isOrganizationOwnedDeviceWithManagedProfile()) {
+            ensureAllUsersAffiliated();
+        }
 
         if (!mInjector.securityLogGetLoggingEnabledProperty()) {
             return null;
@@ -14262,26 +14321,34 @@
     @GuardedBy("getLockObject()")
     private void maybePauseDeviceWideLoggingLocked() {
         if (!areAllUsersAffiliatedWithDeviceLocked()) {
-            Slog.i(LOG_TAG, "There are unaffiliated users, security and network logging will be "
+            Slog.i(LOG_TAG, "There are unaffiliated users, network logging will be "
                     + "paused if enabled.");
-            mSecurityLogMonitor.pause();
             if (mNetworkLogger != null) {
                 mNetworkLogger.pause();
             }
+            if (!isOrganizationOwnedDeviceWithManagedProfile()) {
+                Slog.i(LOG_TAG, "Not org-owned managed profile device, security logging will be "
+                        + "paused if enabled.");
+                mSecurityLogMonitor.pause();
+            }
         }
     }
 
     /** Resumes security and network logging (if they are enabled) if all users are affiliated */
     @GuardedBy("getLockObject()")
     private void maybeResumeDeviceWideLoggingLocked() {
-        if (areAllUsersAffiliatedWithDeviceLocked()) {
-            mInjector.binderWithCleanCallingIdentity(() -> {
+        boolean allUsersAffiliated = areAllUsersAffiliatedWithDeviceLocked();
+        boolean orgOwnedProfileDevice = isOrganizationOwnedDeviceWithManagedProfile();
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            if (allUsersAffiliated || orgOwnedProfileDevice) {
                 mSecurityLogMonitor.resume();
+            }
+            if (allUsersAffiliated) {
                 if (mNetworkLogger != null) {
                     mNetworkLogger.resume();
                 }
-            });
-        }
+            }
+        });
     }
 
     /** Deletes any security and network logs that might have been collected so far */
@@ -14513,12 +14580,15 @@
             final int userHandle = mInjector.userHandleGetCallingUserId();
             getActiveAdminForCallerLocked(admin, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
 
-            DevicePolicyData policy = getUserData(userHandle);
-            if (policy.mPasswordTokenHandle != 0) {
-                return mInjector.binderWithCleanCallingIdentity(
-                        () -> mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle,
-                                userHandle));
-            }
+            return isResetPasswordTokenActiveForUserLocked(userHandle);
+        }
+    }
+
+    private boolean isResetPasswordTokenActiveForUserLocked(int userHandle) {
+        DevicePolicyData policy = getUserData(userHandle);
+        if (policy.mPasswordTokenHandle != 0) {
+            return mInjector.binderWithCleanCallingIdentity(() ->
+                    mLockPatternUtils.isEscrowTokenActive(policy.mPasswordTokenHandle, userHandle));
         }
         return false;
     }
@@ -15666,8 +15736,8 @@
 
     private void updateProfileOffAlarm(long profileOffDeadline) {
         final AlarmManager am = mInjector.getAlarmManager();
-        final PendingIntent pi = PendingIntent.getBroadcast(mContext, REQUEST_PROFILE_OFF_DEADLINE,
-                new Intent(ACTION_PROFILE_OFF_DEADLINE),
+        final PendingIntent pi = mInjector.pendingIntentGetBroadcast(
+                mContext, REQUEST_PROFILE_OFF_DEADLINE, new Intent(ACTION_PROFILE_OFF_DEADLINE),
                 PendingIntent.FLAG_ONE_SHOT | PendingIntent.FLAG_UPDATE_CURRENT);
         am.cancel(pi);
         if (profileOffDeadline != 0) {
@@ -15802,4 +15872,34 @@
             return admin.mProfileMaximumTimeOff;
         }
     }
+
+    @Override
+    public boolean canProfileOwnerResetPasswordWhenLocked(int userId) {
+        enforceSystemCaller("call canProfileOwnerResetPasswordWhenLocked");
+        synchronized (getLockObject()) {
+            final ActiveAdmin poAdmin = getProfileOwnerAdminLocked(userId);
+            if (poAdmin == null
+                    || getEncryptionStatus() != ENCRYPTION_STATUS_ACTIVE_PER_USER
+                    || !isResetPasswordTokenActiveForUserLocked(userId)) {
+                return false;
+            }
+            final ApplicationInfo poAppInfo;
+            try {
+                poAppInfo = mIPackageManager.getApplicationInfo(
+                        poAdmin.info.getPackageName(), 0 /* flags */, userId);
+            } catch (RemoteException e) {
+                Slog.e(LOG_TAG, "Failed to query PO app info", e);
+                return false;
+            }
+            if (poAppInfo == null) {
+                Slog.wtf(LOG_TAG, "Cannot find AppInfo for profile owner");
+                return false;
+            }
+            if (!poAppInfo.isEncryptionAware()) {
+                return false;
+            }
+            Slog.d(LOG_TAG, "PO should be able to reset password from direct boot");
+            return true;
+        }
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
index 1ab3b98..3c445ca 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/SecurityLogMonitor.java
@@ -51,15 +51,17 @@
 
     private final Lock mLock = new ReentrantLock();
 
+    private int mEnabledUser;
+
     SecurityLogMonitor(DevicePolicyManagerService service) {
         this(service, 0 /* id */);
     }
 
     @VisibleForTesting
     SecurityLogMonitor(DevicePolicyManagerService service, long id) {
-        this.mService = service;
-        this.mId = id;
-        this.mLastForceNanos = System.nanoTime();
+        mService = service;
+        mId = id;
+        mLastForceNanos = System.nanoTime();
     }
 
     private static final boolean DEBUG = false;  // STOPSHIP if true.
@@ -136,8 +138,15 @@
     @GuardedBy("mForceSemaphore")
     private long mLastForceNanos = 0;
 
-    void start() {
-        Slog.i(TAG, "Starting security logging.");
+    /**
+     * Start security logging.
+     *
+     * @param enabledUser which user logging is enabled on, or USER_ALL to enable logging for all
+     *     users on the device.
+     */
+    void start(int enabledUser) {
+        Slog.i(TAG, "Starting security logging for user " + enabledUser);
+        mEnabledUser = enabledUser;
         SecurityLog.writeEvent(SecurityLog.TAG_LOGGING_STARTED);
         mLock.lock();
         try {
@@ -286,7 +295,7 @@
                 break;
             }
         }
-
+        SecurityLog.redactEvents(newLogs, mEnabledUser);
         if (DEBUG) Slog.d(TAG, "Got " + newLogs.size() + " new events.");
     }
 
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 569986c..b5d3d18 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -44,7 +44,6 @@
 import android.graphics.GraphicsStatsService;
 import android.hardware.display.DisplayManagerInternal;
 import android.net.ConnectivityModuleConnector;
-import android.net.ITetheringConnector;
 import android.net.NetworkStackClient;
 import android.os.BaseBundle;
 import android.os.Binder;
@@ -298,6 +297,9 @@
             "com.android.server.blob.BlobStoreManagerService";
     private static final String APP_SEARCH_MANAGER_SERVICE_CLASS =
             "com.android.server.appsearch.AppSearchManagerService";
+
+    private static final String TETHERING_CONNECTOR_CLASS = "android.net.ITetheringConnector";
+
     private static final String PERSISTENT_DATA_BLOCK_PROP = "ro.frp.pst";
 
     private static final String UNCRYPT_PACKAGE_FILE = "/cache/recovery/uncrypt_file";
@@ -2331,7 +2333,7 @@
             try {
                 // TODO: hide implementation details, b/146312721.
                 ConnectivityModuleConnector.getInstance().startModuleService(
-                        ITetheringConnector.class.getName(),
+                        TETHERING_CONNECTOR_CLASS,
                         PERMISSION_MAINLINE_NETWORK_STACK, service -> {
                             ServiceManager.addService(Context.TETHERING_SERVICE, service,
                                     false /* allowIsolated */,
diff --git a/services/people/java/com/android/server/people/PeopleService.java b/services/people/java/com/android/server/people/PeopleService.java
index 663bf4f..2499614 100644
--- a/services/people/java/com/android/server/people/PeopleService.java
+++ b/services/people/java/com/android/server/people/PeopleService.java
@@ -88,7 +88,7 @@
         @Override
         public void onCreatePredictionSession(AppPredictionContext context,
                 AppPredictionSessionId sessionId) {
-            mSessions.put(sessionId, new SessionInfo(context, mDataManager));
+            mSessions.put(sessionId, new SessionInfo(context, mDataManager, sessionId.getUserId()));
         }
 
         @Override
diff --git a/services/people/java/com/android/server/people/SessionInfo.java b/services/people/java/com/android/server/people/SessionInfo.java
index eaa0781..28612f1 100644
--- a/services/people/java/com/android/server/people/SessionInfo.java
+++ b/services/people/java/com/android/server/people/SessionInfo.java
@@ -16,6 +16,7 @@
 
 package com.android.server.people;
 
+import android.annotation.UserIdInt;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppTarget;
 import android.app.prediction.IPredictionCallback;
@@ -38,9 +39,10 @@
     private final RemoteCallbackList<IPredictionCallback> mCallbacks =
             new RemoteCallbackList<>();
 
-    SessionInfo(AppPredictionContext predictionContext, DataManager dataManager) {
+    SessionInfo(AppPredictionContext predictionContext, DataManager dataManager,
+            @UserIdInt int callingUserId) {
         mAppTargetPredictor = AppTargetPredictor.create(predictionContext,
-                this::updatePredictions, dataManager);
+                this::updatePredictions, dataManager, callingUserId);
     }
 
     void addCallback(IPredictionCallback callback) {
diff --git a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
index 203e980..7672cd0 100644
--- a/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
+++ b/services/people/java/com/android/server/people/data/AbstractProtoDiskReadWriter.java
@@ -51,15 +51,18 @@
 abstract class AbstractProtoDiskReadWriter<T> {
 
     private static final String TAG = AbstractProtoDiskReadWriter.class.getSimpleName();
+
+    // Common disk write delay that will be appropriate for most scenarios.
+    private static final long DEFAULT_DISK_WRITE_DELAY = 2L * DateUtils.MINUTE_IN_MILLIS;
     private static final long SHUTDOWN_DISK_WRITE_TIMEOUT = 5L * DateUtils.SECOND_IN_MILLIS;
 
     private final File mRootDir;
     private final ScheduledExecutorService mScheduledExecutorService;
-    private final long mWriteDelayMs;
 
     @GuardedBy("this")
     private ScheduledFuture<?> mScheduledFuture;
 
+    // File name -> data class
     @GuardedBy("this")
     private Map<String, T> mScheduledFileDataMap = new ArrayMap<>();
 
@@ -75,15 +78,15 @@
      */
     abstract ProtoStreamReader<T> protoStreamReader();
 
-    AbstractProtoDiskReadWriter(@NonNull File rootDir, long writeDelayMs,
+    AbstractProtoDiskReadWriter(@NonNull File rootDir,
             @NonNull ScheduledExecutorService scheduledExecutorService) {
         mRootDir = rootDir;
-        mWriteDelayMs = writeDelayMs;
         mScheduledExecutorService = scheduledExecutorService;
     }
 
     @WorkerThread
-    void delete(@NonNull String fileName) {
+    synchronized void delete(@NonNull String fileName) {
+        mScheduledFileDataMap.remove(fileName);
         final File file = getFile(fileName);
         if (!file.exists()) {
             return;
@@ -174,7 +177,7 @@
         }
 
         mScheduledFuture = mScheduledExecutorService.schedule(this::flushScheduledData,
-                mWriteDelayMs, TimeUnit.MILLISECONDS);
+                DEFAULT_DISK_WRITE_DELAY, TimeUnit.MILLISECONDS);
     }
 
     /**
@@ -183,7 +186,13 @@
      */
     @MainThread
     synchronized void saveImmediately(@NonNull String fileName, @NonNull T data) {
-        if (mScheduledExecutorService.isShutdown()) {
+        mScheduledFileDataMap.put(fileName, data);
+        triggerScheduledFlushEarly();
+    }
+
+    @MainThread
+    private synchronized void triggerScheduledFlushEarly() {
+        if (mScheduledFileDataMap.isEmpty() || mScheduledExecutorService.isShutdown()) {
             return;
         }
         // Cancel existing future.
@@ -194,7 +203,6 @@
             mScheduledFuture.cancel(true);
         }
 
-        mScheduledFileDataMap.put(fileName, data);
         // Submit flush and blocks until it completes. Blocking will prevent the device from
         // shutting down before flushing completes.
         Future<?> future = mScheduledExecutorService.submit(this::flushScheduledData);
@@ -212,9 +220,10 @@
             return;
         }
         for (String fileName : mScheduledFileDataMap.keySet()) {
-            T data = mScheduledFileDataMap.remove(fileName);
+            T data = mScheduledFileDataMap.get(fileName);
             writeTo(fileName, data);
         }
+        mScheduledFileDataMap.clear();
         mScheduledFuture = null;
     }
 
diff --git a/services/people/java/com/android/server/people/data/ConversationInfo.java b/services/people/java/com/android/server/people/data/ConversationInfo.java
index 859cdf2..41bc361 100644
--- a/services/people/java/com/android/server/people/data/ConversationInfo.java
+++ b/services/people/java/com/android/server/people/data/ConversationInfo.java
@@ -274,6 +274,10 @@
         }
         protoOutputStream.write(ConversationInfoProto.SHORTCUT_FLAGS, mShortcutFlags);
         protoOutputStream.write(ConversationInfoProto.CONVERSATION_FLAGS, mConversationFlags);
+        if (mContactPhoneNumber != null) {
+            protoOutputStream.write(ConversationInfoProto.CONTACT_PHONE_NUMBER,
+                    mContactPhoneNumber);
+        }
     }
 
     /** Reads from {@link ProtoInputStream} and constructs a {@link ConversationInfo}. */
@@ -315,6 +319,10 @@
                     builder.setConversationFlags(protoInputStream.readInt(
                             ConversationInfoProto.CONVERSATION_FLAGS));
                     break;
+                case (int) ConversationInfoProto.CONTACT_PHONE_NUMBER:
+                    builder.setContactPhoneNumber(protoInputStream.readString(
+                            ConversationInfoProto.CONTACT_PHONE_NUMBER));
+                    break;
                 default:
                     Slog.w(TAG, "Could not read undefined field: "
                             + protoInputStream.getFieldNumber());
diff --git a/services/people/java/com/android/server/people/data/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
index 3afb209..89c4972 100644
--- a/services/people/java/com/android/server/people/data/ConversationStore.java
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -22,8 +22,6 @@
 import android.annotation.WorkerThread;
 import android.content.LocusId;
 import android.net.Uri;
-import android.text.TextUtils;
-import android.text.format.DateUtils;
 import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.proto.ProtoInputStream;
@@ -50,8 +48,6 @@
 
     private static final String CONVERSATIONS_FILE_NAME = "conversations";
 
-    private static final long DISK_WRITE_DELAY = 2L * DateUtils.MINUTE_IN_MILLIS;
-
     // Shortcut ID -> Conversation Info
     @GuardedBy("this")
     private final Map<String, ConversationInfo> mConversationInfoMap = new ArrayMap<>();
@@ -74,16 +70,13 @@
 
     private final ScheduledExecutorService mScheduledExecutorService;
     private final File mPackageDir;
-    private final ContactsQueryHelper mHelper;
 
     private ConversationInfosProtoDiskReadWriter mConversationInfosProtoDiskReadWriter;
 
     ConversationStore(@NonNull File packageDir,
-            @NonNull ScheduledExecutorService scheduledExecutorService,
-            @NonNull ContactsQueryHelper helper) {
+            @NonNull ScheduledExecutorService scheduledExecutorService) {
         mScheduledExecutorService = scheduledExecutorService;
         mPackageDir = packageDir;
-        mHelper = helper;
     }
 
     /**
@@ -92,7 +85,7 @@
      */
     @MainThread
     void loadConversationsFromDisk() {
-        mScheduledExecutorService.submit(() -> {
+        mScheduledExecutorService.execute(() -> {
             synchronized (this) {
                 ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
                         getConversationInfosProtoDiskReadWriter();
@@ -105,7 +98,6 @@
                     return;
                 }
                 for (ConversationInfo conversationInfo : conversationsOnDisk) {
-                    conversationInfo = restoreConversationPhoneNumber(conversationInfo);
                     updateConversationsInMemory(conversationInfo);
                 }
             }
@@ -194,6 +186,15 @@
         return getConversation(mNotifChannelIdToShortcutIdMap.get(notifChannelId));
     }
 
+    synchronized void onDestroy() {
+        mConversationInfoMap.clear();
+        mContactUriToShortcutIdMap.clear();
+        mLocusIdToShortcutIdMap.clear();
+        mNotifChannelIdToShortcutIdMap.clear();
+        mPhoneNumberToShortcutIdMap.clear();
+        mConversationInfosProtoDiskReadWriter.deleteConversationsFile();
+    }
+
     @MainThread
     private synchronized void updateConversationsInMemory(
             @NonNull ConversationInfo conversationInfo) {
@@ -239,41 +240,21 @@
         }
         if (mConversationInfosProtoDiskReadWriter == null) {
             mConversationInfosProtoDiskReadWriter = new ConversationInfosProtoDiskReadWriter(
-                    mPackageDir, CONVERSATIONS_FILE_NAME, DISK_WRITE_DELAY,
-                    mScheduledExecutorService);
+                    mPackageDir, CONVERSATIONS_FILE_NAME, mScheduledExecutorService);
         }
         return mConversationInfosProtoDiskReadWriter;
     }
 
-    /**
-     * Conversation's phone number is not saved on disk, so it has to be fetched.
-     */
-    @WorkerThread
-    private ConversationInfo restoreConversationPhoneNumber(
-            @NonNull ConversationInfo conversationInfo) {
-        if (conversationInfo.getContactUri() != null) {
-            if (mHelper.query(conversationInfo.getContactUri().toString())) {
-                String phoneNumber = mHelper.getPhoneNumber();
-                if (!TextUtils.isEmpty(phoneNumber)) {
-                    conversationInfo = new ConversationInfo.Builder(
-                            conversationInfo).setContactPhoneNumber(
-                            phoneNumber).build();
-                }
-            }
-        }
-        return conversationInfo;
-    }
-
-    /** Reads and writes {@link ConversationInfo} on disk. */
-    static class ConversationInfosProtoDiskReadWriter extends
+    /** Reads and writes {@link ConversationInfo}s on disk. */
+    private static class ConversationInfosProtoDiskReadWriter extends
             AbstractProtoDiskReadWriter<List<ConversationInfo>> {
 
         private final String mConversationInfoFileName;
 
-        ConversationInfosProtoDiskReadWriter(@NonNull File baseDir,
+        ConversationInfosProtoDiskReadWriter(@NonNull File rootDir,
                 @NonNull String conversationInfoFileName,
-                long writeDelayMs, @NonNull ScheduledExecutorService scheduledExecutorService) {
-            super(baseDir, writeDelayMs, scheduledExecutorService);
+                @NonNull ScheduledExecutorService scheduledExecutorService) {
+            super(rootDir, scheduledExecutorService);
             mConversationInfoFileName = conversationInfoFileName;
         }
 
@@ -328,5 +309,10 @@
         void saveConversationsImmediately(@NonNull List<ConversationInfo> conversationInfos) {
             saveImmediately(mConversationInfoFileName, conversationInfos);
         }
+
+        @WorkerThread
+        void deleteConversationsFile() {
+            delete(mConversationInfoFileName);
+        }
     }
 }
diff --git a/services/people/java/com/android/server/people/data/DataManager.java b/services/people/java/com/android/server/people/data/DataManager.java
index dd9cbd0..3a34c6a 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -31,16 +31,16 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.LauncherApps;
 import android.content.pm.LauncherApps.ShortcutQuery;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutManager.ShareShortcutInfo;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
 import android.database.ContentObserver;
 import android.net.Uri;
-import android.os.Binder;
 import android.os.CancellationSignal;
 import android.os.Handler;
 import android.os.Process;
@@ -53,9 +53,9 @@
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
 import android.telecom.TelecomManager;
-import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.ArraySet;
+import android.util.Slog;
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -64,11 +64,13 @@
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.telephony.SmsApplication;
 import com.android.server.LocalServices;
+import com.android.server.notification.NotificationManagerInternal;
 
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
@@ -83,9 +85,8 @@
  */
 public class DataManager {
 
-    private static final String PLATFORM_PACKAGE_NAME = "android";
-    private static final int MY_UID = Process.myUid();
-    private static final int MY_PID = Process.myPid();
+    private static final String TAG = "DataManager";
+
     private static final long QUERY_EVENTS_MAX_AGE_MS = DateUtils.DAY_IN_MILLIS;
     private static final long USAGE_STATS_QUERY_INTERVAL_SEC = 120L;
 
@@ -106,7 +107,7 @@
 
     private ShortcutServiceInternal mShortcutServiceInternal;
     private PackageManagerInternal mPackageManagerInternal;
-    private ShortcutManager mShortcutManager;
+    private NotificationManagerInternal mNotificationManagerInternal;
     private UserManager mUserManager;
 
     public DataManager(Context context) {
@@ -125,10 +126,10 @@
     public void initialize() {
         mShortcutServiceInternal = LocalServices.getService(ShortcutServiceInternal.class);
         mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
-        mShortcutManager = mContext.getSystemService(ShortcutManager.class);
+        mNotificationManagerInternal = LocalServices.getService(NotificationManagerInternal.class);
         mUserManager = mContext.getSystemService(UserManager.class);
 
-        mShortcutServiceInternal.addListener(new ShortcutServiceListener());
+        mShortcutServiceInternal.addShortcutChangeCallback(new ShortcutServiceCallback());
 
         IntentFilter shutdownIntentFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
         BroadcastReceiver shutdownBroadcastReceiver = new ShutdownBroadcastReceiver();
@@ -139,8 +140,7 @@
     public void onUserUnlocked(int userId) {
         UserData userData = mUserDataArray.get(userId);
         if (userData == null) {
-            userData = new UserData(userId, mDiskReadWriterExecutor,
-                    mInjector.createContactsQueryHelper(mContext));
+            userData = new UserData(userId, mDiskReadWriterExecutor);
             mUserDataArray.put(userId, userData);
         }
         userData.setUserUnlocked();
@@ -171,8 +171,7 @@
         mNotificationListeners.put(userId, notificationListener);
         try {
             notificationListener.registerAsSystemService(mContext,
-                    new ComponentName(PLATFORM_PACKAGE_NAME, getClass().getCanonicalName()),
-                    userId);
+                    new ComponentName(mContext, getClass()), userId);
         } catch (RemoteException e) {
             // Should never occur for local calls.
         }
@@ -242,8 +241,8 @@
      * Iterates through all the {@link PackageData}s owned by the unlocked users who are in the
      * same profile group as the calling user.
      */
-    public void forAllPackages(Consumer<PackageData> consumer) {
-        List<UserInfo> users = mUserManager.getEnabledProfiles(mInjector.getCallingUserId());
+    void forPackagesInProfile(@UserIdInt int callingUserId, Consumer<PackageData> consumer) {
+        List<UserInfo> users = mUserManager.getEnabledProfiles(callingUserId);
         for (UserInfo userInfo : users) {
             UserData userData = getUnlockedUserData(userInfo.id);
             if (userData != null) {
@@ -275,44 +274,41 @@
      * Gets the {@link ShareShortcutInfo}s from all packages owned by the calling user that match
      * the specified {@link IntentFilter}.
      */
-    public List<ShareShortcutInfo> getShareShortcuts(@NonNull IntentFilter intentFilter) {
-        return mShortcutManager.getShareTargets(intentFilter);
+    public List<ShareShortcutInfo> getShareShortcuts(@NonNull IntentFilter intentFilter,
+            @UserIdInt int callingUserId) {
+        return mShortcutServiceInternal.getShareTargets(
+                mContext.getPackageName(), intentFilter, callingUserId);
     }
 
-    /** Reports the {@link AppTargetEvent} from App Prediction Manager. */
-    public void reportAppTargetEvent(@NonNull AppTargetEvent event,
+    /** Reports the sharing related {@link AppTargetEvent} from App Prediction Manager. */
+    public void reportShareTargetEvent(@NonNull AppTargetEvent event,
             @Nullable IntentFilter intentFilter) {
         AppTarget appTarget = event.getTarget();
-        ShortcutInfo shortcutInfo = appTarget != null ? appTarget.getShortcutInfo() : null;
-        if (shortcutInfo == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
+        if (appTarget == null || event.getAction() != AppTargetEvent.ACTION_LAUNCH) {
             return;
         }
-        PackageData packageData = getPackage(appTarget.getPackageName(),
-                appTarget.getUser().getIdentifier());
-        if (packageData == null) {
-            return;
-        }
+        UserData userData = getUnlockedUserData(appTarget.getUser().getIdentifier());
+        PackageData packageData = userData.getOrCreatePackageData(appTarget.getPackageName());
+        String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
+        @Event.EventType int eventType = mimeTypeToShareEventType(mimeType);
+        EventHistoryImpl eventHistory;
         if (ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE.equals(event.getLaunchLocation())) {
-            String mimeType = intentFilter != null ? intentFilter.getDataType(0) : null;
-            String shortcutId = shortcutInfo.getId();
-            if (packageData.getConversationStore().getConversation(shortcutId) == null
-                    || TextUtils.isEmpty(mimeType)) {
+            // Direct share event
+            if (appTarget.getShortcutInfo() == null) {
                 return;
             }
-            EventHistoryImpl eventHistory = packageData.getEventStore().getOrCreateEventHistory(
-                    EventStore.CATEGORY_SHORTCUT_BASED, shortcutInfo.getId());
-            @Event.EventType int eventType;
-            if (mimeType.startsWith("text/")) {
-                eventType = Event.TYPE_SHARE_TEXT;
-            } else if (mimeType.startsWith("image/")) {
-                eventType = Event.TYPE_SHARE_IMAGE;
-            } else if (mimeType.startsWith("video/")) {
-                eventType = Event.TYPE_SHARE_VIDEO;
-            } else {
-                eventType = Event.TYPE_SHARE_OTHER;
+            String shortcutId = appTarget.getShortcutInfo().getId();
+            if (packageData.getConversationStore().getConversation(shortcutId) == null) {
+                addOrUpdateConversationInfo(appTarget.getShortcutInfo());
             }
-            eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
+            eventHistory = packageData.getEventStore().getOrCreateEventHistory(
+                    EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
+        } else {
+            // App share event
+            eventHistory = packageData.getEventStore().getOrCreateEventHistory(
+                    EventStore.CATEGORY_CLASS_BASED, appTarget.getClassName());
         }
+        eventHistory.addEvent(new Event(System.currentTimeMillis(), eventType));
     }
 
     /** Prunes the data for the specified user. */
@@ -323,12 +319,11 @@
         }
         pruneUninstalledPackageData(userData);
 
-        long currentTimeMillis = System.currentTimeMillis();
         userData.forAllPackages(packageData -> {
             if (signal.isCanceled()) {
                 return;
             }
-            packageData.getEventStore().pruneOldEvents(currentTimeMillis);
+            packageData.getEventStore().pruneOldEvents();
             if (!packageData.isDefaultDialer()) {
                 packageData.getEventStore().deleteEventHistories(EventStore.CATEGORY_CALL);
             }
@@ -339,6 +334,17 @@
         });
     }
 
+    private int mimeTypeToShareEventType(String mimeType) {
+        if (mimeType.startsWith("text/")) {
+            return Event.TYPE_SHARE_TEXT;
+        } else if (mimeType.startsWith("image/")) {
+            return Event.TYPE_SHARE_IMAGE;
+        } else if (mimeType.startsWith("video/")) {
+            return Event.TYPE_SHARE_VIDEO;
+        }
+        return Event.TYPE_SHARE_OTHER;
+    }
+
     private void pruneUninstalledPackageData(@NonNull UserData userData) {
         Set<String> installApps = new ArraySet<>();
         mPackageManagerInternal.forEachInstalledPackage(
@@ -361,9 +367,9 @@
         @ShortcutQuery.QueryFlags int queryFlags = ShortcutQuery.FLAG_MATCH_DYNAMIC
                 | ShortcutQuery.FLAG_MATCH_PINNED | ShortcutQuery.FLAG_MATCH_PINNED_BY_ANY_LAUNCHER;
         return mShortcutServiceInternal.getShortcuts(
-                mInjector.getCallingUserId(), /*callingPackage=*/ PLATFORM_PACKAGE_NAME,
+                UserHandle.USER_SYSTEM, mContext.getPackageName(),
                 /*changedSince=*/ 0, packageName, shortcutIds, /*locusIds=*/ null,
-                /*componentName=*/ null, queryFlags, userId, MY_PID, MY_UID);
+                /*componentName=*/ null, queryFlags, userId, Process.myPid(), Process.myUid());
     }
 
     private void forAllUnlockedUsers(Consumer<UserData> consumer) {
@@ -414,12 +420,13 @@
                 EventStore.CATEGORY_SHORTCUT_BASED, shortcutId);
     }
 
+    private boolean isPersonShortcut(@NonNull ShortcutInfo shortcutInfo) {
+        return shortcutInfo.getPersons() != null && shortcutInfo.getPersons().length != 0;
+    }
+
     @VisibleForTesting
     @WorkerThread
-    void onShortcutAddedOrUpdated(@NonNull ShortcutInfo shortcutInfo) {
-        if (shortcutInfo.getPersons() == null || shortcutInfo.getPersons().length == 0) {
-            return;
-        }
+    void addOrUpdateConversationInfo(@NonNull ShortcutInfo shortcutInfo) {
         UserData userData = getUnlockedUserData(shortcutInfo.getUserId());
         if (userData == null) {
             return;
@@ -435,24 +442,24 @@
         builder.setShortcutId(shortcutInfo.getId());
         builder.setLocusId(shortcutInfo.getLocusId());
         builder.setShortcutFlags(shortcutInfo.getFlags());
+        builder.setContactUri(null);
+        builder.setContactPhoneNumber(null);
+        builder.setContactStarred(false);
 
-        Person person = shortcutInfo.getPersons()[0];
-        builder.setPersonImportant(person.isImportant());
-        builder.setPersonBot(person.isBot());
-        String contactUri = person.getUri();
-        if (contactUri != null) {
-            ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
-            if (helper.query(contactUri)) {
-                builder.setContactUri(helper.getContactUri());
-                builder.setContactStarred(helper.isStarred());
-                builder.setContactPhoneNumber(helper.getPhoneNumber());
+        if (shortcutInfo.getPersons() != null && shortcutInfo.getPersons().length != 0) {
+            Person person = shortcutInfo.getPersons()[0];
+            builder.setPersonImportant(person.isImportant());
+            builder.setPersonBot(person.isBot());
+            String contactUri = person.getUri();
+            if (contactUri != null) {
+                ContactsQueryHelper helper = mInjector.createContactsQueryHelper(mContext);
+                if (helper.query(contactUri)) {
+                    builder.setContactUri(helper.getContactUri());
+                    builder.setContactStarred(helper.isStarred());
+                    builder.setContactPhoneNumber(helper.getPhoneNumber());
+                }
             }
-        } else {
-            builder.setContactUri(null);
-            builder.setContactPhoneNumber(null);
-            builder.setContactStarred(false);
         }
-
         conversationStore.addOrUpdate(builder.build());
     }
 
@@ -621,16 +628,40 @@
     }
 
     /** Listener for the shortcut data changes. */
-    private class ShortcutServiceListener implements
-            ShortcutServiceInternal.ShortcutChangeListener {
+    private class ShortcutServiceCallback implements LauncherApps.ShortcutChangeCallback {
 
         @Override
-        public void onShortcutChanged(@NonNull String packageName, int userId) {
-            BackgroundThread.getExecutor().execute(() -> {
-                List<ShortcutInfo> shortcuts = getShortcuts(packageName, userId,
-                        /*shortcutIds=*/ null);
+        public void onShortcutsAddedOrUpdated(@NonNull String packageName,
+                @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
+            mInjector.getBackgroundExecutor().execute(() -> {
                 for (ShortcutInfo shortcut : shortcuts) {
-                    onShortcutAddedOrUpdated(shortcut);
+                    if (isPersonShortcut(shortcut)) {
+                        addOrUpdateConversationInfo(shortcut);
+                    }
+                }
+            });
+        }
+
+        @Override
+        public void onShortcutsRemoved(@NonNull String packageName,
+                @NonNull List<ShortcutInfo> shortcuts, @NonNull UserHandle user) {
+            mInjector.getBackgroundExecutor().execute(() -> {
+                int uid = Process.INVALID_UID;
+                try {
+                    uid = mContext.getPackageManager().getPackageUidAsUser(
+                            packageName, user.getIdentifier());
+                } catch (PackageManager.NameNotFoundException e) {
+                    Slog.e(TAG, "Package not found: " + packageName, e);
+                }
+                PackageData packageData = getPackage(packageName, user.getIdentifier());
+                for (ShortcutInfo shortcutInfo : shortcuts) {
+                    if (packageData != null) {
+                        packageData.deleteDataForConversation(shortcutInfo.getId());
+                    }
+                    if (uid != Process.INVALID_UID) {
+                        mNotificationManagerInternal.onConversationRemoved(
+                                shortcutInfo.getPackage(), uid, shortcutInfo.getId());
+                    }
                 }
             });
         }
@@ -775,7 +806,7 @@
 
         @Override
         public void onReceive(Context context, Intent intent) {
-            forAllPackages(PackageData::saveToDisk);
+            forAllUnlockedUsers(userData -> userData.forAllPackages(PackageData::saveToDisk));
         }
     }
 
@@ -786,6 +817,10 @@
             return Executors.newSingleThreadScheduledExecutor();
         }
 
+        Executor getBackgroundExecutor() {
+            return BackgroundThread.getExecutor();
+        }
+
         ContactsQueryHelper createContactsQueryHelper(Context context) {
             return new ContactsQueryHelper(context);
         }
@@ -809,9 +844,5 @@
                 Function<String, PackageData> packageDataGetter) {
             return new UsageStatsQueryHelper(userId, packageDataGetter);
         }
-
-        int getCallingUserId() {
-            return Binder.getCallingUserHandle().getIdentifier();
-        }
     }
 }
diff --git a/services/people/java/com/android/server/people/data/Event.java b/services/people/java/com/android/server/people/data/Event.java
index 81411c0..a929f6f 100644
--- a/services/people/java/com/android/server/people/data/Event.java
+++ b/services/people/java/com/android/server/people/data/Event.java
@@ -20,7 +20,13 @@
 import android.annotation.NonNull;
 import android.text.format.DateFormat;
 import android.util.ArraySet;
+import android.util.Slog;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
 
+import com.android.server.people.PeopleEventProto;
+
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.Objects;
@@ -29,6 +35,8 @@
 /** An event representing the interaction with a specific conversation or app. */
 public class Event {
 
+    private static final String TAG = Event.class.getSimpleName();
+
     public static final int TYPE_SHORTCUT_INVOCATION = 1;
 
     public static final int TYPE_NOTIFICATION_POSTED = 2;
@@ -142,6 +150,36 @@
         return mDurationSeconds;
     }
 
+    /** Writes field members to {@link ProtoOutputStream}. */
+    void writeToProto(@NonNull ProtoOutputStream protoOutputStream) {
+        protoOutputStream.write(PeopleEventProto.EVENT_TYPE, mType);
+        protoOutputStream.write(PeopleEventProto.TIME, mTimestamp);
+        protoOutputStream.write(PeopleEventProto.DURATION, mDurationSeconds);
+    }
+
+    /** Reads from {@link ProtoInputStream} and constructs {@link Event}. */
+    @NonNull
+    static Event readFromProto(@NonNull ProtoInputStream protoInputStream) throws IOException {
+        Event.Builder builder = new Event.Builder();
+        while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (protoInputStream.getFieldNumber()) {
+                case (int) PeopleEventProto.EVENT_TYPE:
+                    builder.setType(protoInputStream.readInt(PeopleEventProto.EVENT_TYPE));
+                    break;
+                case (int) PeopleEventProto.TIME:
+                    builder.setTimestamp(protoInputStream.readLong(PeopleEventProto.TIME));
+                    break;
+                case (int) PeopleEventProto.DURATION:
+                    builder.setDurationSeconds(protoInputStream.readInt(PeopleEventProto.DURATION));
+                    break;
+                default:
+                    Slog.w(TAG, "Could not read undefined field: "
+                            + protoInputStream.getFieldNumber());
+            }
+        }
+        return builder.build();
+    }
+
     @Override
     public boolean equals(Object obj) {
         if (this == obj) {
@@ -177,12 +215,14 @@
     /** Builder class for {@link Event} objects. */
     static class Builder {
 
-        private final long mTimestamp;
+        private long mTimestamp;
 
-        private final int mType;
+        private int mType;
 
         private int mDurationSeconds;
 
+        private Builder() {}
+
         Builder(long timestamp, @EventType int type) {
             mTimestamp = timestamp;
             mType = type;
@@ -193,6 +233,16 @@
             return this;
         }
 
+        private Builder setTimestamp(long timestamp) {
+            mTimestamp = timestamp;
+            return this;
+        }
+
+        private Builder setType(int type) {
+            mType = type;
+            return this;
+        }
+
         Event build() {
             return new Event(this);
         }
diff --git a/services/people/java/com/android/server/people/data/EventHistoryImpl.java b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
index 6bef1db..85661c6 100644
--- a/services/people/java/com/android/server/people/data/EventHistoryImpl.java
+++ b/services/people/java/com/android/server/people/data/EventHistoryImpl.java
@@ -16,42 +16,149 @@
 
 package com.android.server.people.data;
 
+import android.annotation.MainThread;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.WorkerThread;
+import android.net.Uri;
+import android.text.format.DateUtils;
+import android.util.ArrayMap;
+import android.util.Slog;
 import android.util.SparseArray;
+import android.util.proto.ProtoInputStream;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.people.PeopleEventIndexesProto;
+import com.android.server.people.PeopleEventsProto;
+import com.android.server.people.TypedPeopleEventIndexProto;
 
+import com.google.android.collect.Lists;
+
+import java.io.File;
+import java.io.IOException;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
+
 
 class EventHistoryImpl implements EventHistory {
 
+    private static final long MAX_EVENTS_AGE = 4L * DateUtils.HOUR_IN_MILLIS;
+    private static final long PRUNE_OLD_EVENTS_DELAY = 15L * DateUtils.MINUTE_IN_MILLIS;
+
+    private static final String EVENTS_DIR = "events";
+    private static final String INDEXES_DIR = "indexes";
+
     private final Injector mInjector;
+    private final ScheduledExecutorService mScheduledExecutorService;
+    private final EventsProtoDiskReadWriter mEventsProtoDiskReadWriter;
+    private final EventIndexesProtoDiskReadWriter mEventIndexesProtoDiskReadWriter;
 
     // Event Type -> Event Index
+    @GuardedBy("this")
     private final SparseArray<EventIndex> mEventIndexArray = new SparseArray<>();
 
+    @GuardedBy("this")
     private final EventList mRecentEvents = new EventList();
 
-    EventHistoryImpl() {
-        mInjector = new Injector();
+    private long mLastPruneTime;
+
+    EventHistoryImpl(@NonNull File rootDir,
+            @NonNull ScheduledExecutorService scheduledExecutorService) {
+        this(new Injector(), rootDir, scheduledExecutorService);
     }
 
     @VisibleForTesting
-    EventHistoryImpl(Injector injector) {
+    EventHistoryImpl(@NonNull Injector injector, @NonNull File rootDir,
+            @NonNull ScheduledExecutorService scheduledExecutorService) {
         mInjector = injector;
+        mScheduledExecutorService = scheduledExecutorService;
+        mLastPruneTime = injector.currentTimeMillis();
+
+        File eventsDir = new File(rootDir, EVENTS_DIR);
+        mEventsProtoDiskReadWriter = new EventsProtoDiskReadWriter(eventsDir,
+                mScheduledExecutorService);
+        File indexesDir = new File(rootDir, INDEXES_DIR);
+        mEventIndexesProtoDiskReadWriter = new EventIndexesProtoDiskReadWriter(indexesDir,
+                scheduledExecutorService);
+    }
+
+    @WorkerThread
+    @NonNull
+    static Map<String, EventHistoryImpl> eventHistoriesImplFromDisk(File categoryDir,
+            ScheduledExecutorService scheduledExecutorService) {
+        return eventHistoriesImplFromDisk(new Injector(), categoryDir, scheduledExecutorService);
+    }
+
+    @VisibleForTesting
+    @NonNull
+    static Map<String, EventHistoryImpl> eventHistoriesImplFromDisk(Injector injector,
+            File categoryDir, ScheduledExecutorService scheduledExecutorService) {
+        Map<String, EventHistoryImpl> results = new ArrayMap<>();
+        File[] keyDirs = categoryDir.listFiles(File::isDirectory);
+        if (keyDirs == null) {
+            return results;
+        }
+        for (File keyDir : keyDirs) {
+            File[] dirContents = keyDir.listFiles(
+                    (dir, name) -> EVENTS_DIR.equals(name) || INDEXES_DIR.equals(name));
+            if (dirContents != null && dirContents.length == 2) {
+                EventHistoryImpl eventHistory = new EventHistoryImpl(injector, keyDir,
+                        scheduledExecutorService);
+                eventHistory.loadFromDisk();
+                results.put(Uri.decode(keyDir.getName()), eventHistory);
+            }
+        }
+        return results;
+    }
+
+    /**
+     * Loads recent events and indexes from disk to memory in a background thread. This should be
+     * called after the device powers on and the user has been unlocked.
+     */
+    @VisibleForTesting
+    @MainThread
+    synchronized void loadFromDisk() {
+        mScheduledExecutorService.execute(() -> {
+            synchronized (this) {
+                EventList diskEvents = mEventsProtoDiskReadWriter.loadRecentEventsFromDisk();
+                if (diskEvents != null) {
+                    diskEvents.removeOldEvents(mInjector.currentTimeMillis() - MAX_EVENTS_AGE);
+                    mRecentEvents.addAll(diskEvents.getAllEvents());
+                }
+
+                SparseArray<EventIndex> diskIndexes =
+                        mEventIndexesProtoDiskReadWriter.loadIndexesFromDisk();
+                if (diskIndexes != null) {
+                    for (int i = 0; i < diskIndexes.size(); i++) {
+                        mEventIndexArray.put(diskIndexes.keyAt(i), diskIndexes.valueAt(i));
+                    }
+                }
+            }
+        });
+    }
+
+    /**
+     * Flushes events and indexes immediately. This should be called when device is powering off.
+     */
+    @MainThread
+    synchronized void saveToDisk() {
+        mEventsProtoDiskReadWriter.saveEventsImmediately(mRecentEvents);
+        mEventIndexesProtoDiskReadWriter.saveIndexesImmediately(mEventIndexArray);
     }
 
     @Override
     @NonNull
-    public EventIndex getEventIndex(@Event.EventType int eventType) {
+    public synchronized EventIndex getEventIndex(@Event.EventType int eventType) {
         EventIndex eventIndex = mEventIndexArray.get(eventType);
         return eventIndex != null ? new EventIndex(eventIndex) : mInjector.createEventIndex();
     }
 
     @Override
     @NonNull
-    public EventIndex getEventIndex(Set<Integer> eventTypes) {
+    public synchronized EventIndex getEventIndex(Set<Integer> eventTypes) {
         EventIndex combined = mInjector.createEventIndex();
         for (@Event.EventType int eventType : eventTypes) {
             EventIndex eventIndex = mEventIndexArray.get(eventType);
@@ -64,11 +171,35 @@
 
     @Override
     @NonNull
-    public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
+    public synchronized List<Event> queryEvents(Set<Integer> eventTypes, long startTime,
+            long endTime) {
         return mRecentEvents.queryEvents(eventTypes, startTime, endTime);
     }
 
-    void addEvent(Event event) {
+    synchronized void addEvent(Event event) {
+        pruneOldEvents();
+        addEventInMemory(event);
+        mEventsProtoDiskReadWriter.scheduleEventsSave(mRecentEvents);
+        mEventIndexesProtoDiskReadWriter.scheduleIndexesSave(mEventIndexArray);
+    }
+
+    synchronized void onDestroy() {
+        mEventIndexArray.clear();
+        mRecentEvents.clear();
+        mEventsProtoDiskReadWriter.deleteRecentEventsFile();
+        mEventIndexesProtoDiskReadWriter.deleteIndexesFile();
+    }
+
+    /** Deletes the events data that exceeds the retention period. */
+    synchronized void pruneOldEvents() {
+        long currentTime = mInjector.currentTimeMillis();
+        if (currentTime - mLastPruneTime > PRUNE_OLD_EVENTS_DELAY) {
+            mRecentEvents.removeOldEvents(currentTime - MAX_EVENTS_AGE);
+            mLastPruneTime = currentTime;
+        }
+    }
+
+    private synchronized void addEventInMemory(Event event) {
         EventIndex eventIndex = mEventIndexArray.get(event.getType());
         if (eventIndex == null) {
             eventIndex = mInjector.createEventIndex();
@@ -78,22 +209,180 @@
         mRecentEvents.add(event);
     }
 
-    void onDestroy() {
-        mEventIndexArray.clear();
-        mRecentEvents.clear();
-        // TODO: STOPSHIP: Delete the data files.
-    }
-
-    /** Deletes the events data that exceeds the retention period. */
-    void pruneOldEvents(long currentTimeMillis) {
-        // TODO: STOPSHIP: Delete the old events data files.
-    }
-
     @VisibleForTesting
     static class Injector {
 
         EventIndex createEventIndex() {
             return new EventIndex();
         }
+
+        long currentTimeMillis() {
+            return System.currentTimeMillis();
+        }
+    }
+
+    /** Reads and writes {@link Event}s on disk. */
+    private static class EventsProtoDiskReadWriter extends AbstractProtoDiskReadWriter<EventList> {
+
+        private static final String TAG = EventsProtoDiskReadWriter.class.getSimpleName();
+
+        private static final String RECENT_FILE = "recent";
+
+
+        EventsProtoDiskReadWriter(@NonNull File rootDir,
+                @NonNull ScheduledExecutorService scheduledExecutorService) {
+            super(rootDir, scheduledExecutorService);
+            rootDir.mkdirs();
+        }
+
+        @Override
+        ProtoStreamWriter<EventList> protoStreamWriter() {
+            return (protoOutputStream, data) -> {
+                for (Event event : data.getAllEvents()) {
+                    long token = protoOutputStream.start(PeopleEventsProto.EVENTS);
+                    event.writeToProto(protoOutputStream);
+                    protoOutputStream.end(token);
+                }
+            };
+        }
+
+        @Override
+        ProtoStreamReader<EventList> protoStreamReader() {
+            return protoInputStream -> {
+                List<Event> results = Lists.newArrayList();
+                try {
+                    while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                        if (protoInputStream.getFieldNumber() != (int) PeopleEventsProto.EVENTS) {
+                            continue;
+                        }
+                        long token = protoInputStream.start(PeopleEventsProto.EVENTS);
+                        Event event = Event.readFromProto(protoInputStream);
+                        protoInputStream.end(token);
+                        results.add(event);
+                    }
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to read protobuf input stream.", e);
+                }
+                EventList eventList = new EventList();
+                eventList.addAll(results);
+                return eventList;
+            };
+        }
+
+        @MainThread
+        void scheduleEventsSave(EventList recentEvents) {
+            scheduleSave(RECENT_FILE, recentEvents);
+        }
+
+        @MainThread
+        void saveEventsImmediately(EventList recentEvents) {
+            saveImmediately(RECENT_FILE, recentEvents);
+        }
+
+        /**
+         * Loads recent events from disk. This should be called when device is powered on.
+         */
+        @WorkerThread
+        @Nullable
+        EventList loadRecentEventsFromDisk() {
+            return read(RECENT_FILE);
+        }
+
+        @WorkerThread
+        void deleteRecentEventsFile() {
+            delete(RECENT_FILE);
+        }
+    }
+
+    /** Reads and writes {@link EventIndex}s on disk. */
+    private static class EventIndexesProtoDiskReadWriter extends
+            AbstractProtoDiskReadWriter<SparseArray<EventIndex>> {
+
+        private static final String TAG = EventIndexesProtoDiskReadWriter.class.getSimpleName();
+
+        private static final String INDEXES_FILE = "index";
+
+        EventIndexesProtoDiskReadWriter(@NonNull File rootDir,
+                @NonNull ScheduledExecutorService scheduledExecutorService) {
+            super(rootDir, scheduledExecutorService);
+            rootDir.mkdirs();
+        }
+
+        @Override
+        ProtoStreamWriter<SparseArray<EventIndex>> protoStreamWriter() {
+            return (protoOutputStream, data) -> {
+                for (int i = 0; i < data.size(); i++) {
+                    @Event.EventType int eventType = data.keyAt(i);
+                    EventIndex index = data.valueAt(i);
+                    long token = protoOutputStream.start(PeopleEventIndexesProto.TYPED_INDEXES);
+                    protoOutputStream.write(TypedPeopleEventIndexProto.EVENT_TYPE, eventType);
+                    long indexToken = protoOutputStream.start(TypedPeopleEventIndexProto.INDEX);
+                    index.writeToProto(protoOutputStream);
+                    protoOutputStream.end(indexToken);
+                    protoOutputStream.end(token);
+                }
+            };
+        }
+
+        @Override
+        ProtoStreamReader<SparseArray<EventIndex>> protoStreamReader() {
+            return protoInputStream -> {
+                SparseArray<EventIndex> results = new SparseArray<>();
+                try {
+                    while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                        if (protoInputStream.getFieldNumber()
+                                != (int) PeopleEventIndexesProto.TYPED_INDEXES) {
+                            continue;
+                        }
+                        long token = protoInputStream.start(PeopleEventIndexesProto.TYPED_INDEXES);
+                        @Event.EventType int eventType = 0;
+                        EventIndex index = EventIndex.EMPTY;
+                        while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+                            switch (protoInputStream.getFieldNumber()) {
+                                case (int) TypedPeopleEventIndexProto.EVENT_TYPE:
+                                    eventType = protoInputStream.readInt(
+                                            TypedPeopleEventIndexProto.EVENT_TYPE);
+                                    break;
+                                case (int) TypedPeopleEventIndexProto.INDEX:
+                                    long indexToken = protoInputStream.start(
+                                            TypedPeopleEventIndexProto.INDEX);
+                                    index = EventIndex.readFromProto(protoInputStream);
+                                    protoInputStream.end(indexToken);
+                                    break;
+                                default:
+                                    Slog.w(TAG, "Could not read undefined field: "
+                                            + protoInputStream.getFieldNumber());
+                            }
+                        }
+                        results.append(eventType, index);
+                        protoInputStream.end(token);
+                    }
+                } catch (IOException e) {
+                    Slog.e(TAG, "Failed to read protobuf input stream.", e);
+                }
+                return results;
+            };
+        }
+
+        @MainThread
+        void scheduleIndexesSave(SparseArray<EventIndex> indexes) {
+            scheduleSave(INDEXES_FILE, indexes);
+        }
+
+        @MainThread
+        void saveIndexesImmediately(SparseArray<EventIndex> indexes) {
+            saveImmediately(INDEXES_FILE, indexes);
+        }
+
+        @WorkerThread
+        @Nullable
+        SparseArray<EventIndex> loadIndexesFromDisk() {
+            return read(INDEXES_FILE);
+        }
+
+        @WorkerThread
+        void deleteIndexesFile() {
+            delete(INDEXES_FILE);
+        }
     }
 }
diff --git a/services/people/java/com/android/server/people/data/EventIndex.java b/services/people/java/com/android/server/people/data/EventIndex.java
index b74a3fa..47b6207 100644
--- a/services/people/java/com/android/server/people/data/EventIndex.java
+++ b/services/people/java/com/android/server/people/data/EventIndex.java
@@ -21,9 +21,14 @@
 import android.annotation.Nullable;
 import android.text.format.DateFormat;
 import android.util.Range;
+import android.util.Slog;
+import android.util.proto.ProtoInputStream;
+import android.util.proto.ProtoOutputStream;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.server.people.PeopleEventIndexProto;
 
+import java.io.IOException;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.time.Instant;
@@ -34,6 +39,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Objects;
 import java.util.TimeZone;
 import java.util.function.Function;
 
@@ -60,8 +66,9 @@
  *  </pre>
  */
 public class EventIndex {
+    private static final String TAG = EventIndex.class.getSimpleName();
 
-    private static final int LONG_SIZE_BITS = 64;
+    private static final int RETENTION_DAYS = 63;
 
     private static final int TIME_SLOT_ONE_DAY = 0;
 
@@ -118,22 +125,23 @@
     private final Injector mInjector;
 
     EventIndex() {
-        mInjector = new Injector();
-        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
-        mLastUpdatedTime = mInjector.currentTimeMillis();
+        this(new Injector());
     }
 
-    EventIndex(EventIndex from) {
-        mInjector = new Injector();
-        mEventBitmaps = Arrays.copyOf(from.mEventBitmaps, TIME_SLOT_TYPES_COUNT);
-        mLastUpdatedTime = from.mLastUpdatedTime;
+    EventIndex(@NonNull EventIndex from) {
+        this(from.mInjector, Arrays.copyOf(from.mEventBitmaps, TIME_SLOT_TYPES_COUNT),
+                from.mLastUpdatedTime);
     }
 
     @VisibleForTesting
-    EventIndex(Injector injector) {
+    EventIndex(@NonNull Injector injector) {
+        this(injector, new long[]{0L, 0L, 0L, 0L}, injector.currentTimeMillis());
+    }
+
+    private EventIndex(@NonNull Injector injector, long[] eventBitmaps, long lastUpdatedTime) {
         mInjector = injector;
-        mEventBitmaps = new long[]{0L, 0L, 0L, 0L};
-        mLastUpdatedTime = mInjector.currentTimeMillis();
+        mEventBitmaps = eventBitmaps;
+        mLastUpdatedTime = lastUpdatedTime;
     }
 
     /**
@@ -202,7 +210,7 @@
             updateEventBitmaps(currentTime);
             for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
                 int offset = diffTimeSlots(slotType, eventTime, currentTime);
-                if (offset < LONG_SIZE_BITS) {
+                if (offset < Long.SIZE) {
                     mEventBitmaps[slotType] |= (1L << offset);
                 }
             }
@@ -232,19 +240,70 @@
         return sb.toString();
     }
 
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof EventIndex)) {
+            return false;
+        }
+        EventIndex other = (EventIndex) obj;
+        return mLastUpdatedTime == other.mLastUpdatedTime
+                && Arrays.equals(mEventBitmaps, other.mEventBitmaps);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mLastUpdatedTime, mEventBitmaps);
+    }
+
+    synchronized void writeToProto(@NonNull ProtoOutputStream protoOutputStream) {
+        for (long bitmap : mEventBitmaps) {
+            protoOutputStream.write(PeopleEventIndexProto.EVENT_BITMAPS, bitmap);
+        }
+        protoOutputStream.write(PeopleEventIndexProto.LAST_UPDATED_TIME, mLastUpdatedTime);
+    }
+
     /** Shifts the event bitmaps to make them up-to-date. */
     private void updateEventBitmaps(long currentTimeMillis) {
         for (int slotType = 0; slotType < TIME_SLOT_TYPES_COUNT; slotType++) {
             int offset = diffTimeSlots(slotType, mLastUpdatedTime, currentTimeMillis);
-            if (offset < LONG_SIZE_BITS) {
+            if (offset < Long.SIZE) {
                 mEventBitmaps[slotType] <<= offset;
             } else {
                 mEventBitmaps[slotType] = 0L;
             }
         }
+
+        int bitsToClear = Long.SIZE - RETENTION_DAYS;
+        mEventBitmaps[TIME_SLOT_ONE_DAY] <<= bitsToClear;
+        mEventBitmaps[TIME_SLOT_ONE_DAY] >>>= bitsToClear;
         mLastUpdatedTime = currentTimeMillis;
     }
 
+    static EventIndex readFromProto(@NonNull ProtoInputStream protoInputStream) throws IOException {
+        int bitmapIndex = 0;
+        long[] eventBitmaps = new long[TIME_SLOT_TYPES_COUNT];
+        long lastUpdated = 0L;
+        while (protoInputStream.nextField() != ProtoInputStream.NO_MORE_FIELDS) {
+            switch (protoInputStream.getFieldNumber()) {
+                case (int) PeopleEventIndexProto.EVENT_BITMAPS:
+                    eventBitmaps[bitmapIndex++] = protoInputStream.readLong(
+                            PeopleEventIndexProto.EVENT_BITMAPS);
+                    break;
+                case (int) PeopleEventIndexProto.LAST_UPDATED_TIME:
+                    lastUpdated = protoInputStream.readLong(
+                            PeopleEventIndexProto.LAST_UPDATED_TIME);
+                    break;
+                default:
+                    Slog.e(TAG, "Could not read undefined field: "
+                            + protoInputStream.getFieldNumber());
+            }
+        }
+        return new EventIndex(new Injector(), eventBitmaps, lastUpdated);
+    }
+
     private static LocalDateTime toLocalDateTime(long epochMilli) {
         return LocalDateTime.ofInstant(
                 Instant.ofEpochMilli(epochMilli), TimeZone.getDefault().toZoneId());
diff --git a/services/people/java/com/android/server/people/data/EventList.java b/services/people/java/com/android/server/people/data/EventList.java
index d770f91..3788d6c 100644
--- a/services/people/java/com/android/server/people/data/EventList.java
+++ b/services/people/java/com/android/server/people/data/EventList.java
@@ -18,6 +18,8 @@
 
 import android.annotation.NonNull;
 
+import com.android.internal.util.CollectionUtils;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Set;
@@ -41,6 +43,16 @@
         mEvents.add(index, event);
     }
 
+
+    /**
+     * Call #add on each event to keep the order.
+     */
+    void addAll(@NonNull List<Event> events) {
+        for (Event event : events) {
+            add(event);
+        }
+    }
+
     /**
      * Returns a {@link List} of {@link Event}s whose timestamps are between the specified {@code
      * fromTimestamp}, inclusive, and {@code toTimestamp} exclusive, and match the specified event
@@ -73,6 +85,44 @@
         mEvents.clear();
     }
 
+    /**
+     * Returns a copy of events.
+     */
+    @NonNull
+    List<Event> getAllEvents() {
+        return CollectionUtils.copyOf(mEvents);
+    }
+
+    /**
+     * Remove events that are older than the specified cut off threshold timestamp.
+     */
+    void removeOldEvents(long cutOffThreshold) {
+
+        // Everything before the cut off is considered old, and should be removed.
+        int cutOffIndex = firstIndexOnOrAfter(cutOffThreshold);
+        if (cutOffIndex == 0) {
+            return;
+        }
+
+        // Clear entire list if the cut off is greater than the last element.
+        int eventsSize = mEvents.size();
+        if (cutOffIndex == eventsSize) {
+            mEvents.clear();
+            return;
+        }
+
+        // Reorder the list starting from the cut off index.
+        int i = 0;
+        for (; cutOffIndex < eventsSize; i++, cutOffIndex++) {
+            mEvents.set(i, mEvents.get(cutOffIndex));
+        }
+
+        // Clear the list after reordering.
+        if (eventsSize > i) {
+            mEvents.subList(i, eventsSize).clear();
+        }
+    }
+
     /** Returns the first index whose timestamp is greater or equal to the provided timestamp. */
     private int firstIndexOnOrAfter(long timestamp) {
         int result = mEvents.size();
diff --git a/services/people/java/com/android/server/people/data/EventStore.java b/services/people/java/com/android/server/people/data/EventStore.java
index c8d44ac..00d4241 100644
--- a/services/people/java/com/android/server/people/data/EventStore.java
+++ b/services/people/java/com/android/server/people/data/EventStore.java
@@ -17,16 +17,22 @@
 package com.android.server.people.data;
 
 import android.annotation.IntDef;
+import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.net.Uri;
 import android.util.ArrayMap;
 
+import com.android.internal.annotations.GuardedBy;
+
+import java.io.File;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ScheduledExecutorService;
 import java.util.function.Predicate;
 
 /** The store that stores and accesses the events data for a package. */
@@ -57,14 +63,58 @@
     @Retention(RetentionPolicy.SOURCE)
     @interface EventCategory {}
 
+    @GuardedBy("this")
     private final List<Map<String, EventHistoryImpl>> mEventHistoryMaps = new ArrayList<>();
+    private final List<File> mEventsCategoryDirs = new ArrayList<>();
+    private final ScheduledExecutorService mScheduledExecutorService;
 
-    EventStore() {
+    EventStore(@NonNull File packageDir,
+            @NonNull ScheduledExecutorService scheduledExecutorService) {
         mEventHistoryMaps.add(CATEGORY_SHORTCUT_BASED, new ArrayMap<>());
         mEventHistoryMaps.add(CATEGORY_LOCUS_ID_BASED, new ArrayMap<>());
         mEventHistoryMaps.add(CATEGORY_CALL, new ArrayMap<>());
         mEventHistoryMaps.add(CATEGORY_SMS, new ArrayMap<>());
         mEventHistoryMaps.add(CATEGORY_CLASS_BASED, new ArrayMap<>());
+
+        File eventDir = new File(packageDir, "event");
+        mEventsCategoryDirs.add(CATEGORY_SHORTCUT_BASED, new File(eventDir, "shortcut"));
+        mEventsCategoryDirs.add(CATEGORY_LOCUS_ID_BASED, new File(eventDir, "locus"));
+        mEventsCategoryDirs.add(CATEGORY_CALL, new File(eventDir, "call"));
+        mEventsCategoryDirs.add(CATEGORY_SMS, new File(eventDir, "sms"));
+        mEventsCategoryDirs.add(CATEGORY_CLASS_BASED, new File(eventDir, "class"));
+
+        mScheduledExecutorService = scheduledExecutorService;
+    }
+
+    /**
+     * Loads existing {@link EventHistoryImpl}s from disk. This should be called when device powers
+     * on and user is unlocked.
+     */
+    @MainThread
+    void loadFromDisk() {
+        mScheduledExecutorService.execute(() -> {
+            synchronized (this) {
+                for (@EventCategory int category = 0; category < mEventsCategoryDirs.size();
+                        category++) {
+                    File categoryDir = mEventsCategoryDirs.get(category);
+                    Map<String, EventHistoryImpl> existingEventHistoriesImpl =
+                            EventHistoryImpl.eventHistoriesImplFromDisk(categoryDir,
+                                    mScheduledExecutorService);
+                    mEventHistoryMaps.get(category).putAll(existingEventHistoriesImpl);
+                }
+            }
+        });
+    }
+
+    /**
+     * Flushes all {@link EventHistoryImpl}s to disk. Should be called when device is shutting down.
+     */
+    synchronized void saveToDisk() {
+        for (Map<String, EventHistoryImpl> map : mEventHistoryMaps) {
+            for (EventHistoryImpl eventHistory : map.values()) {
+                eventHistory.saveToDisk();
+            }
+        }
     }
 
     /**
@@ -74,7 +124,7 @@
      *            name.
      */
     @Nullable
-    EventHistory getEventHistory(@EventCategory int category, String key) {
+    synchronized EventHistory getEventHistory(@EventCategory int category, String key) {
         return mEventHistoryMaps.get(category).get(key);
     }
 
@@ -87,8 +137,11 @@
      *            name.
      */
     @NonNull
-    EventHistoryImpl getOrCreateEventHistory(@EventCategory int category, String key) {
-        return mEventHistoryMaps.get(category).computeIfAbsent(key, k -> new EventHistoryImpl());
+    synchronized EventHistoryImpl getOrCreateEventHistory(@EventCategory int category, String key) {
+        return mEventHistoryMaps.get(category).computeIfAbsent(key,
+                k -> new EventHistoryImpl(
+                        new File(mEventsCategoryDirs.get(category), Uri.encode(key)),
+                        mScheduledExecutorService));
     }
 
     /**
@@ -97,7 +150,7 @@
      * @param key Category-specific key, it can be shortcut ID, locus ID, phone number, or class
      *            name.
      */
-    void deleteEventHistory(@EventCategory int category, String key) {
+    synchronized void deleteEventHistory(@EventCategory int category, String key) {
         EventHistoryImpl eventHistory = mEventHistoryMaps.get(category).remove(key);
         if (eventHistory != null) {
             eventHistory.onDestroy();
@@ -105,16 +158,18 @@
     }
 
     /** Deletes all the events and index data for the specified category from disk. */
-    void deleteEventHistories(@EventCategory int category) {
+    synchronized void deleteEventHistories(@EventCategory int category) {
+        for (EventHistoryImpl eventHistory : mEventHistoryMaps.get(category).values()) {
+            eventHistory.onDestroy();
+        }
         mEventHistoryMaps.get(category).clear();
-        // TODO: Implement this method to delete the data from disk.
     }
 
     /** Deletes the events data that exceeds the retention period. */
-    void pruneOldEvents(long currentTimeMillis) {
+    synchronized void pruneOldEvents() {
         for (Map<String, EventHistoryImpl> map : mEventHistoryMaps) {
             for (EventHistoryImpl eventHistory : map.values()) {
-                eventHistory.pruneOldEvents(currentTimeMillis);
+                eventHistory.pruneOldEvents();
             }
         }
     }
@@ -125,7 +180,8 @@
      *
      * @param keyChecker Check whether there exists a conversation contains this key.
      */
-    void pruneOrphanEventHistories(@EventCategory int category, Predicate<String> keyChecker) {
+    synchronized void pruneOrphanEventHistories(@EventCategory int category,
+            Predicate<String> keyChecker) {
         Set<String> keys = mEventHistoryMaps.get(category).keySet();
         List<String> keysToDelete = new ArrayList<>();
         for (String key : keys) {
@@ -141,4 +197,12 @@
             }
         }
     }
+
+    synchronized void onDestroy() {
+        for (Map<String, EventHistoryImpl> map : mEventHistoryMaps) {
+            for (EventHistoryImpl eventHistory : map.values()) {
+                eventHistory.onDestroy();
+            }
+        }
+    }
 }
diff --git a/services/people/java/com/android/server/people/data/PackageData.java b/services/people/java/com/android/server/people/data/PackageData.java
index c55f972..35d245f 100644
--- a/services/people/java/com/android/server/people/data/PackageData.java
+++ b/services/people/java/com/android/server/people/data/PackageData.java
@@ -27,8 +27,10 @@
 import android.annotation.UserIdInt;
 import android.content.LocusId;
 import android.text.TextUtils;
+import android.util.ArrayMap;
 
 import java.io.File;
+import java.util.Map;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
@@ -57,28 +59,53 @@
             @NonNull Predicate<String> isDefaultDialerPredicate,
             @NonNull Predicate<String> isDefaultSmsAppPredicate,
             @NonNull ScheduledExecutorService scheduledExecutorService,
-            @NonNull File perUserPeopleDataDir,
-            @NonNull ContactsQueryHelper helper) {
+            @NonNull File perUserPeopleDataDir) {
         mPackageName = packageName;
         mUserId = userId;
 
         mPackageDataDir = new File(perUserPeopleDataDir, mPackageName);
-        mConversationStore = new ConversationStore(mPackageDataDir, scheduledExecutorService,
-                helper);
-        mEventStore = new EventStore();
+        mPackageDataDir.mkdirs();
+
+        mConversationStore = new ConversationStore(mPackageDataDir, scheduledExecutorService);
+        mEventStore = new EventStore(mPackageDataDir, scheduledExecutorService);
         mIsDefaultDialerPredicate = isDefaultDialerPredicate;
         mIsDefaultSmsAppPredicate = isDefaultSmsAppPredicate;
     }
 
-    /** Called when user is unlocked. */
-    void loadFromDisk() {
-        mPackageDataDir.mkdirs();
+    /**
+     * Returns a map of package directory names as keys and their associated {@link PackageData}.
+     * This should be called when device is powered on and unlocked.
+     */
+    @NonNull
+    static Map<String, PackageData> packagesDataFromDisk(@UserIdInt int userId,
+            @NonNull Predicate<String> isDefaultDialerPredicate,
+            @NonNull Predicate<String> isDefaultSmsAppPredicate,
+            @NonNull ScheduledExecutorService scheduledExecutorService,
+            @NonNull File perUserPeopleDataDir) {
+        Map<String, PackageData> results = new ArrayMap<>();
+        File[] packageDirs = perUserPeopleDataDir.listFiles(File::isDirectory);
+        if (packageDirs == null) {
+            return results;
+        }
+        for (File packageDir : packageDirs) {
+            PackageData packageData = new PackageData(packageDir.getName(), userId,
+                    isDefaultDialerPredicate, isDefaultSmsAppPredicate, scheduledExecutorService,
+                    perUserPeopleDataDir);
+            packageData.loadFromDisk();
+            results.put(packageDir.getName(), packageData);
+        }
+        return results;
+    }
+
+    private void loadFromDisk() {
         mConversationStore.loadConversationsFromDisk();
+        mEventStore.loadFromDisk();
     }
 
     /** Called when device is shutting down. */
     void saveToDisk() {
         mConversationStore.saveConversationsToDisk();
+        mEventStore.saveToDisk();
     }
 
     @NonNull
@@ -222,6 +249,7 @@
     }
 
     void onDestroy() {
-        // TODO: STOPSHIP: Implements this method for the case of package being uninstalled.
+        mEventStore.onDestroy();
+        mConversationStore.onDestroy();
     }
 }
diff --git a/services/people/java/com/android/server/people/data/UserData.java b/services/people/java/com/android/server/people/data/UserData.java
index 7ca4b6c..0f8b91b 100644
--- a/services/people/java/com/android/server/people/data/UserData.java
+++ b/services/people/java/com/android/server/people/data/UserData.java
@@ -37,8 +37,6 @@
 
     private final ScheduledExecutorService mScheduledExecutorService;
 
-    private final ContactsQueryHelper mHelper;
-
     private boolean mIsUnlocked;
 
     private Map<String, PackageData> mPackageDataMap = new ArrayMap<>();
@@ -49,12 +47,10 @@
     @Nullable
     private String mDefaultSmsApp;
 
-    UserData(@UserIdInt int userId, @NonNull ScheduledExecutorService scheduledExecutorService,
-            ContactsQueryHelper helper) {
+    UserData(@UserIdInt int userId, @NonNull ScheduledExecutorService scheduledExecutorService) {
         mUserId = userId;
         mPerUserPeopleDataDir = new File(Environment.getDataSystemCeDirectory(mUserId), "people");
         mScheduledExecutorService = scheduledExecutorService;
-        mHelper = helper;
     }
 
     @UserIdInt int getUserId() {
@@ -73,9 +69,8 @@
         // Ensures per user root directory for people data is present, and attempt to load
         // data from disk.
         mPerUserPeopleDataDir.mkdirs();
-        for (PackageData packageData : mPackageDataMap.values()) {
-            packageData.loadFromDisk();
-        }
+        mPackageDataMap.putAll(PackageData.packagesDataFromDisk(mUserId, this::isDefaultDialer,
+                this::isDefaultSmsApp, mScheduledExecutorService, mPerUserPeopleDataDir));
     }
 
     void setUserStopped() {
@@ -132,7 +127,7 @@
 
     private PackageData createPackageData(String packageName) {
         return new PackageData(packageName, mUserId, this::isDefaultDialer, this::isDefaultSmsApp,
-                mScheduledExecutorService, mPerUserPeopleDataDir, mHelper);
+                mScheduledExecutorService, mPerUserPeopleDataDir);
     }
 
     private boolean isDefaultDialer(String packageName) {
diff --git a/services/people/java/com/android/server/people/prediction/AppTargetPredictor.java b/services/people/java/com/android/server/people/prediction/AppTargetPredictor.java
index 44f3e35..c89dadc 100644
--- a/services/people/java/com/android/server/people/prediction/AppTargetPredictor.java
+++ b/services/people/java/com/android/server/people/prediction/AppTargetPredictor.java
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread;
 import android.annotation.NonNull;
+import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppTarget;
@@ -42,25 +43,28 @@
     /** Creates a {@link AppTargetPredictor} instance based on the prediction context. */
     public static AppTargetPredictor create(@NonNull AppPredictionContext predictionContext,
             @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
-            @NonNull DataManager dataManager) {
+            @NonNull DataManager dataManager, @UserIdInt int callingUserId) {
         if (UI_SURFACE_SHARE.equals(predictionContext.getUiSurface())) {
             return new ShareTargetPredictor(
-                    predictionContext, updatePredictionsMethod, dataManager);
+                    predictionContext, updatePredictionsMethod, dataManager, callingUserId);
         }
-        return new AppTargetPredictor(predictionContext, updatePredictionsMethod, dataManager);
+        return new AppTargetPredictor(
+                predictionContext, updatePredictionsMethod, dataManager, callingUserId);
     }
 
     private final AppPredictionContext mPredictionContext;
     private final Consumer<List<AppTarget>> mUpdatePredictionsMethod;
     private final DataManager mDataManager;
+    final int mCallingUserId;
     private final ExecutorService mCallbackExecutor;
 
     AppTargetPredictor(@NonNull AppPredictionContext predictionContext,
             @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
-            @NonNull DataManager dataManager) {
+            @NonNull DataManager dataManager, @UserIdInt int callingUserId) {
         mPredictionContext = predictionContext;
         mUpdatePredictionsMethod = updatePredictionsMethod;
         mDataManager = dataManager;
+        mCallingUserId = callingUserId;
         mCallbackExecutor = Executors.newSingleThreadExecutor();
     }
 
@@ -69,6 +73,7 @@
      */
     @MainThread
     public void onAppTargetEvent(AppTargetEvent event) {
+        mCallbackExecutor.execute(() -> reportAppTargetEvent(event));
     }
 
     /**
@@ -100,6 +105,11 @@
         return mUpdatePredictionsMethod;
     }
 
+    /** To be overridden by the subclass to report app target event. */
+    @WorkerThread
+    void reportAppTargetEvent(AppTargetEvent event) {
+    }
+
     /** To be overridden by the subclass to predict the targets. */
     @WorkerThread
     void predictTargets() {
diff --git a/services/people/java/com/android/server/people/prediction/ShareTargetPredictor.java b/services/people/java/com/android/server/people/prediction/ShareTargetPredictor.java
index 280ced3..8e5d75b 100644
--- a/services/people/java/com/android/server/people/prediction/ShareTargetPredictor.java
+++ b/services/people/java/com/android/server/people/prediction/ShareTargetPredictor.java
@@ -16,9 +16,9 @@
 
 package com.android.server.people.prediction;
 
-import android.annotation.MainThread;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppTarget;
@@ -27,15 +27,18 @@
 import android.content.IntentFilter;
 import android.content.pm.ShortcutInfo;
 import android.content.pm.ShortcutManager.ShareShortcutInfo;
+import android.util.Range;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.ChooserActivity;
 import com.android.server.people.data.ConversationInfo;
 import com.android.server.people.data.DataManager;
+import com.android.server.people.data.Event;
 import com.android.server.people.data.EventHistory;
 import com.android.server.people.data.PackageData;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.function.Consumer;
 
@@ -45,95 +48,145 @@
 
     ShareTargetPredictor(@NonNull AppPredictionContext predictionContext,
             @NonNull Consumer<List<AppTarget>> updatePredictionsMethod,
-            @NonNull DataManager dataManager) {
-        super(predictionContext, updatePredictionsMethod, dataManager);
+            @NonNull DataManager dataManager, @UserIdInt int callingUserId) {
+        super(predictionContext, updatePredictionsMethod, dataManager, callingUserId);
         mIntentFilter = predictionContext.getExtras().getParcelable(
                 ChooserActivity.APP_PREDICTION_INTENT_FILTER_KEY);
     }
 
-    @MainThread
-    @Override
-    public void onAppTargetEvent(AppTargetEvent event) {
-        getDataManager().reportAppTargetEvent(event, mIntentFilter);
-    }
-
+    /** Reports chosen history of direct/app share targets. */
     @WorkerThread
     @Override
-    protected void predictTargets() {
-        List<ShareTarget> shareTargets = getShareTargets();
-        // TODO: Rank the share targets with the data in ShareTarget.mConversationData.
-        List<AppTarget> appTargets = new ArrayList<>();
-        for (ShareTarget shareTarget : shareTargets) {
-
-            ShortcutInfo shortcutInfo = shareTarget.getShareShortcutInfo().getShortcutInfo();
-            AppTargetId appTargetId = new AppTargetId(shortcutInfo.getId());
-            String shareTargetClassName =
-                    shareTarget.getShareShortcutInfo().getTargetComponent().getClassName();
-            AppTarget appTarget = new AppTarget.Builder(appTargetId, shortcutInfo)
-                    .setClassName(shareTargetClassName)
-                    .build();
-            appTargets.add(appTarget);
-            if (appTargets.size() >= getPredictionContext().getPredictedTargetCount()) {
-                break;
-            }
-        }
-        updatePredictions(appTargets);
+    void reportAppTargetEvent(AppTargetEvent event) {
+        getDataManager().reportShareTargetEvent(event, mIntentFilter);
     }
 
-    @VisibleForTesting
-    List<ShareTarget> getShareTargets() {
+    /** Provides prediction on direct share targets */
+    @WorkerThread
+    @Override
+    void predictTargets() {
+        List<ShareTarget> shareTargets = getDirectShareTargets();
+        rankTargets(shareTargets);
+        List<AppTarget> res = new ArrayList<>();
+        for (int i = 0; i < Math.min(getPredictionContext().getPredictedTargetCount(),
+                shareTargets.size()); i++) {
+            res.add(shareTargets.get(i).getAppTarget());
+        }
+        updatePredictions(res);
+    }
+
+    /** Provides prediction on app share targets */
+    @WorkerThread
+    @Override
+    void sortTargets(List<AppTarget> targets, Consumer<List<AppTarget>> callback) {
+        List<ShareTarget> shareTargets = getAppShareTargets(targets);
+        rankTargets(shareTargets);
+        List<AppTarget> appTargetList = new ArrayList<>();
+        shareTargets.forEach(t -> appTargetList.add(t.getAppTarget()));
+        callback.accept(appTargetList);
+    }
+
+    private void rankTargets(List<ShareTarget> shareTargets) {
+        // Rank targets based on recency of sharing history only for the moment.
+        // TODO: Take more factors into ranking, e.g. frequency, mime type, foreground app.
+        Collections.sort(shareTargets, (t1, t2) -> {
+            if (t1.getEventHistory() == null) {
+                return 1;
+            }
+            if (t2.getEventHistory() == null) {
+                return -1;
+            }
+            Range<Long> timeSlot1 = t1.getEventHistory().getEventIndex(
+                    Event.SHARE_EVENT_TYPES).getMostRecentActiveTimeSlot();
+            Range<Long> timeSlot2 = t2.getEventHistory().getEventIndex(
+                    Event.SHARE_EVENT_TYPES).getMostRecentActiveTimeSlot();
+            if (timeSlot1 == null) {
+                return 1;
+            } else if (timeSlot2 == null) {
+                return -1;
+            } else {
+                return -Long.compare(timeSlot1.getUpper(), timeSlot2.getUpper());
+            }
+        });
+    }
+
+    private List<ShareTarget> getDirectShareTargets() {
         List<ShareTarget> shareTargets = new ArrayList<>();
         List<ShareShortcutInfo> shareShortcuts =
-                getDataManager().getShareShortcuts(mIntentFilter);
+                getDataManager().getShareShortcuts(mIntentFilter, mCallingUserId);
 
         for (ShareShortcutInfo shareShortcut : shareShortcuts) {
             ShortcutInfo shortcutInfo = shareShortcut.getShortcutInfo();
+            AppTarget appTarget = new AppTarget.Builder(
+                    new AppTargetId(shortcutInfo.getId()),
+                    shortcutInfo)
+                    .setClassName(shareShortcut.getTargetComponent().getClassName())
+                    .build();
             String packageName = shortcutInfo.getPackage();
             int userId = shortcutInfo.getUserId();
             PackageData packageData = getDataManager().getPackage(packageName, userId);
 
-            ConversationData conversationData = null;
+            ConversationInfo conversationInfo = null;
+            EventHistory eventHistory = null;
             if (packageData != null) {
                 String shortcutId = shortcutInfo.getId();
-                ConversationInfo conversationInfo =
-                        packageData.getConversationInfo(shortcutId);
-
+                conversationInfo = packageData.getConversationInfo(shortcutId);
                 if (conversationInfo != null) {
-                    EventHistory eventHistory = packageData.getEventHistory(shortcutId);
-                    conversationData = new ConversationData(
-                            packageName, userId, conversationInfo, eventHistory);
+                    eventHistory = packageData.getEventHistory(shortcutId);
                 }
             }
-            shareTargets.add(new ShareTarget(shareShortcut, conversationData));
+            shareTargets.add(new ShareTarget(appTarget, eventHistory, conversationInfo));
         }
 
         return shareTargets;
     }
 
+    private List<ShareTarget> getAppShareTargets(List<AppTarget> targets) {
+        List<ShareTarget> shareTargets = new ArrayList<>();
+        for (AppTarget target : targets) {
+            PackageData packageData = getDataManager().getPackage(target.getPackageName(),
+                    target.getUser().getIdentifier());
+            shareTargets.add(new ShareTarget(target,
+                    packageData == null ? null
+                            : packageData.getClassLevelEventHistory(target.getClassName()), null));
+        }
+        return shareTargets;
+    }
+
     @VisibleForTesting
     static class ShareTarget {
 
         @NonNull
-        private final ShareShortcutInfo mShareShortcutInfo;
+        private final AppTarget mAppTarget;
         @Nullable
-        private final ConversationData mConversationData;
+        private final EventHistory mEventHistory;
+        @Nullable
+        private final ConversationInfo mConversationInfo;
 
-        private ShareTarget(@NonNull ShareShortcutInfo shareShortcutInfo,
-                @Nullable ConversationData conversationData) {
-            mShareShortcutInfo = shareShortcutInfo;
-            mConversationData = conversationData;
+        private ShareTarget(@NonNull AppTarget appTarget,
+                @Nullable EventHistory eventHistory,
+                @Nullable ConversationInfo conversationInfo) {
+            mAppTarget = appTarget;
+            mEventHistory = eventHistory;
+            mConversationInfo = conversationInfo;
         }
 
         @NonNull
         @VisibleForTesting
-        ShareShortcutInfo getShareShortcutInfo() {
-            return mShareShortcutInfo;
+        AppTarget getAppTarget() {
+            return mAppTarget;
         }
 
         @Nullable
         @VisibleForTesting
-        ConversationData getConversationData() {
-            return mConversationData;
+        EventHistory getEventHistory() {
+            return mEventHistory;
+        }
+
+        @Nullable
+        @VisibleForTesting
+        ConversationInfo getConversationInfo() {
+            return mConversationInfo;
         }
     }
 }
diff --git a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
index 6190802..fa0febd 100644
--- a/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
+++ b/services/robotests/src/com/android/server/pm/CrossProfileAppsServiceImplRoboTest.java
@@ -46,8 +46,6 @@
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ResolveInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -58,6 +56,9 @@
 import com.android.internal.util.FunctionalUtils.ThrowingRunnable;
 import com.android.internal.util.FunctionalUtils.ThrowingSupplier;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 import com.android.server.testing.shadows.ShadowApplicationPackageManager;
 import com.android.server.testing.shadows.ShadowUserManager;
 import com.android.server.wm.ActivityTaskManagerInternal;
@@ -135,7 +136,8 @@
                         eq(userId)))
                 .thenReturn(packageInfo);
         when(mPackageManagerInternal.getPackage(uid))
-                .thenReturn(PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME));
+                .thenReturn(((ParsedPackage) PackageImpl.forTesting(CROSS_PROFILE_APP_PACKAGE_NAME)
+                        .hideAsParsed()).hideAsFinal());
     }
 
     private PackageInfo buildTestPackageInfo() {
@@ -497,7 +499,9 @@
 
     private void declareCrossProfileAttributeOnCrossProfileApp(boolean value) {
         mockCrossProfileAndroidPackage(
-                PackageImpl.forParsing(CROSS_PROFILE_APP_PACKAGE_NAME).setCrossProfile(value));
+                ((ParsedPackage) PackageImpl.forTesting(CROSS_PROFILE_APP_PACKAGE_NAME)
+                        .setCrossProfile(value)
+                        .hideAsParsed()).hideAsFinal());
     }
 
     private class TestInjector implements CrossProfileAppsServiceImpl.Injector {
diff --git a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
index 2d5fa23..959dc05 100644
--- a/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/appop/AppOpsServiceTest.java
@@ -50,7 +50,6 @@
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.pm.PackageManagerInternal;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
@@ -63,6 +62,7 @@
 
 import com.android.dx.mockito.inline.extended.StaticMockitoSession;
 import com.android.server.LocalServices;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import org.junit.After;
 import org.junit.Before;
diff --git a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
index 3778e17..e5450a9 100644
--- a/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/blob/BlobStoreManagerServiceTest.java
@@ -149,7 +149,7 @@
         final BlobMetadata blobMetadata2 = createBlobMetadataMock(blobId2, blobFile2, false);
         mUserBlobs.put(blobHandle2, blobMetadata2);
 
-        mService.addKnownIdsForTest(sessionId1, sessionId2, sessionId3, sessionId4,
+        mService.addActiveIdsForTest(sessionId1, sessionId2, sessionId3, sessionId4,
                 blobId1, blobId2);
 
         // Invoke test method
@@ -180,8 +180,10 @@
         assertThat(mUserBlobs.get(blobHandle1)).isNotNull();
         assertThat(mUserBlobs.get(blobHandle2)).isNull();
 
-        assertThat(mService.getKnownIdsForTest()).containsExactly(
+        assertThat(mService.getActiveIdsForTest()).containsExactly(
                 sessionId2, sessionId3, blobId1);
+        assertThat(mService.getKnownIdsForTest()).containsExactly(
+                sessionId1, sessionId2, sessionId3, sessionId4, blobId1, blobId2);
     }
 
     @Test
@@ -198,12 +200,12 @@
         doReturn(String.valueOf(testId3)).when(file3).getName();
 
         doReturn(new File[] {file1, file2, file3}).when(mBlobsDir).listFiles();
-        mService.addKnownIdsForTest(testId1, testId3);
+        mService.addActiveIdsForTest(testId1, testId3);
 
         // Invoke test method
         mService.handleIdleMaintenanceLocked();
 
-        // Verify unknown blobs are delete
+        // Verify unknown blobs are deleted
         verify(file1, never()).delete();
         verify(file2).delete();
         verify(file3, never()).delete();
@@ -242,7 +244,7 @@
                 sessionId3, sessionFile3, blobHandle3);
         mUserSessions.append(sessionId3, session3);
 
-        mService.addKnownIdsForTest(sessionId1, sessionId2, sessionId3);
+        mService.addActiveIdsForTest(sessionId1, sessionId2, sessionId3);
 
         // Invoke test method
         mService.handleIdleMaintenanceLocked();
@@ -255,7 +257,9 @@
         assertThat(mUserSessions.size()).isEqualTo(1);
         assertThat(mUserSessions.get(sessionId2)).isNotNull();
 
-        assertThat(mService.getKnownIdsForTest()).containsExactly(sessionId2);
+        assertThat(mService.getActiveIdsForTest()).containsExactly(sessionId2);
+        assertThat(mService.getKnownIdsForTest()).containsExactly(
+                sessionId1, sessionId2, sessionId3);
     }
 
     @Test
@@ -282,7 +286,7 @@
         final BlobMetadata blobMetadata3 = createBlobMetadataMock(blobId3, blobFile3, false);
         mUserBlobs.put(blobHandle3, blobMetadata3);
 
-        mService.addKnownIdsForTest(blobId1, blobId2, blobId3);
+        mService.addActiveIdsForTest(blobId1, blobId2, blobId3);
 
         // Invoke test method
         mService.handleIdleMaintenanceLocked();
@@ -295,7 +299,8 @@
         assertThat(mUserBlobs.size()).isEqualTo(1);
         assertThat(mUserBlobs.get(blobHandle2)).isNotNull();
 
-        assertThat(mService.getKnownIdsForTest()).containsExactly(blobId2);
+        assertThat(mService.getActiveIdsForTest()).containsExactly(blobId2);
+        assertThat(mService.getKnownIdsForTest()).containsExactly(blobId1, blobId2, blobId3);
     }
 
     private BlobStoreSession createBlobStoreSessionMock(String ownerPackageName, int ownerUid,
diff --git a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
index d7a3cfd..1bf9c2a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/job/controllers/JobStatusTest.java
@@ -73,7 +73,9 @@
     private static final double DELTA = 0.00001;
     private static final String TEST_PACKAGE = "job.test.package";
     private static final ComponentName TEST_JOB_COMPONENT = new ComponentName(TEST_PACKAGE, "test");
-    private static final Uri TEST_MEDIA_URI = Uri.parse("content://media/path/to/media");
+
+    private static final Uri IMAGES_MEDIA_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
+    private static final Uri VIDEO_MEDIA_URI = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
 
     @Mock
     private JobSchedulerInternal mJobSchedulerInternal;
@@ -127,7 +129,7 @@
     @Test
     public void testMediaBackupExemption_lateConstraint() {
         final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                 .setOverrideDeadline(12)
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
@@ -138,7 +140,7 @@
     @Test
     public void testMediaBackupExemption_noConnectivityConstraint() {
         final JobInfo triggerContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                 .build();
         when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
         assertEffectiveBucketForMediaExemption(createJobStatus(triggerContentJob), false);
@@ -156,7 +158,7 @@
     @Test
     public void testMediaBackupExemption_wrongSourcePackage() {
         final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
         when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn("not.test.package");
@@ -164,11 +166,12 @@
     }
 
     @Test
-    public void testMediaBackupExemption_nonMediaUri() {
-        final Uri nonMediaUri = Uri.parse("content://not-media/any/path");
+    public void testMediaBackupExemption_nonEligibleUri() {
+        final Uri nonEligibleUri = MediaStore.AUTHORITY_URI.buildUpon()
+                .appendPath("any_path").build();
         final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(nonMediaUri, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(nonEligibleUri, 0))
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
         when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
@@ -177,12 +180,25 @@
 
     @Test
     public void testMediaBackupExemptionGranted() {
-        final JobInfo networkContentJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
-                .addTriggerContentUri(new JobInfo.TriggerContentUri(TEST_MEDIA_URI, 0))
+        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
+        final JobInfo imageUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
                 .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
                 .build();
-        when(mJobSchedulerInternal.getMediaBackupPackage()).thenReturn(TEST_PACKAGE);
-        assertEffectiveBucketForMediaExemption(createJobStatus(networkContentJob), true);
+        assertEffectiveBucketForMediaExemption(createJobStatus(imageUriJob), true);
+
+        final JobInfo videoUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(VIDEO_MEDIA_URI, 0))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+                .build();
+        assertEffectiveBucketForMediaExemption(createJobStatus(videoUriJob), true);
+
+        final JobInfo bothUriJob = new JobInfo.Builder(42, TEST_JOB_COMPONENT)
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(IMAGES_MEDIA_URI, 0))
+                .addTriggerContentUri(new JobInfo.TriggerContentUri(VIDEO_MEDIA_URI, 0))
+                .setRequiredNetworkType(JobInfo.NETWORK_TYPE_ANY)
+                .build();
+        assertEffectiveBucketForMediaExemption(createJobStatus(bothUriJob), true);
     }
 
     @Test
diff --git a/services/tests/servicestests/Android.bp b/services/tests/servicestests/Android.bp
index bf2b9be..d148c21 100644
--- a/services/tests/servicestests/Android.bp
+++ b/services/tests/servicestests/Android.bp
@@ -93,6 +93,7 @@
     },
 
     data: [":JobTestApp"],
+    resource_zips: [":FrameworksServicesTests_apks_as_resources"],
 }
 
 java_library {
@@ -115,3 +116,28 @@
         "src/com/android/server/pm/SuspendPackagesTest.java",
     ],
 }
+
+// Rules to copy all the test apks to the intermediate raw resource directory
+java_genrule {
+    name: "FrameworksServicesTests_apks_as_resources",
+    srcs: [
+        ":FrameworksCoreTests_install_complete_package_info",
+        ":FrameworksServicesTests_install_intent_filters",
+        ":FrameworksServicesTests_install_split_base",
+        ":FrameworksServicesTests_install_split_feature_a",
+        ":FrameworksServicesTests_install_uses_sdk_0",
+        ":FrameworksServicesTests_install_uses_sdk_q0",
+        ":FrameworksServicesTests_install_uses_sdk_r",
+        ":FrameworksServicesTests_install_uses_sdk_r0",
+        ":FrameworksServicesTests_install_uses_sdk_r5",
+    ],
+    out: ["FrameworkServicesTests_apks_as_resources.res.zip"],
+    tools: ["soong_zip"],
+
+    cmd: "mkdir -p $(genDir)/res/raw && " +
+        "for i in $(in); do " +
+        "  x=$${i##*FrameworksCoreTests_}; cp $$i $(genDir)/res/raw/$${x%.apk};" +
+        "  x=$${i##*FrameworksServicesTests_}; cp $$i $(genDir)/res/raw/$${x%.apk};" +
+        "done && " +
+        "$(location soong_zip) -o $(out) -C $(genDir)/res -D $(genDir)/res",
+}
diff --git a/services/tests/servicestests/apks/Android.bp b/services/tests/servicestests/apks/Android.bp
new file mode 100644
index 0000000..3e11604
--- /dev/null
+++ b/services/tests/servicestests/apks/Android.bp
@@ -0,0 +1,7 @@
+java_defaults {
+    name: "FrameworksServicesTests_apks_defaults",
+    sdk_version: "current",
+
+    // Every package should have a native library
+    jni_libs: ["libframeworks_coretests_jni"],
+}
diff --git a/services/tests/servicestests/apks/install-split-base/Android.bp b/services/tests/servicestests/apks/install-split-base/Android.bp
new file mode 100644
index 0000000..1b62aa2
--- /dev/null
+++ b/services/tests/servicestests/apks/install-split-base/Android.bp
@@ -0,0 +1,6 @@
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_split_base",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+
+    srcs: ["**/*.java"],
+}
diff --git a/core/tests/coretests/apks/install-split-base/AndroidManifest.xml b/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
similarity index 93%
rename from core/tests/coretests/apks/install-split-base/AndroidManifest.xml
rename to services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
index c2bfedd..2979395 100644
--- a/core/tests/coretests/apks/install-split-base/AndroidManifest.xml
+++ b/services/tests/servicestests/apks/install-split-base/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_split"
+        package="com.android.frameworks.servicestests.install_split"
         android:isolatedSplits="true">
 
     <application android:label="ClassloaderSplitApp">
diff --git a/core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java b/services/tests/servicestests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
similarity index 100%
rename from core/tests/coretests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
rename to services/tests/servicestests/apks/install-split-base/src/com/google/android/dexapis/splitapp/BaseActivity.java
diff --git a/core/tests/coretests/apks/install-split-feature-a/Android.bp b/services/tests/servicestests/apks/install-split-feature-a/Android.bp
similarity index 60%
rename from core/tests/coretests/apks/install-split-feature-a/Android.bp
rename to services/tests/servicestests/apks/install-split-feature-a/Android.bp
index 9ec9893..45d8917 100644
--- a/core/tests/coretests/apks/install-split-feature-a/Android.bp
+++ b/services/tests/servicestests/apks/install-split-feature-a/Android.bp
@@ -1,6 +1,6 @@
 android_test_helper_app {
-    name: "FrameworksCoreTests_install_split_feature_a",
-    defaults: ["FrameworksCoreTests_apks_defaults"],
+    name: "FrameworksServicesTests_install_split_feature_a",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
 
     srcs: ["**/*.java"],
 
diff --git a/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml b/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
similarity index 93%
rename from core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml
rename to services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
index 3221c75..a3dd55f 100644
--- a/core/tests/coretests/apks/install-split-feature-a/AndroidManifest.xml
+++ b/services/tests/servicestests/apks/install-split-feature-a/AndroidManifest.xml
@@ -15,7 +15,7 @@
 -->
 
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_split"
+        package="com.android.frameworks.servicestests.install_split"
         featureSplit="feature_a">
 
     <application>
diff --git a/core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java b/services/tests/servicestests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
similarity index 100%
rename from core/tests/coretests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
rename to services/tests/servicestests/apks/install-split-feature-a/src/com/google/android/dexapis/splitapp/feature_a/FeatureAActivity.java
diff --git a/services/tests/servicestests/apks/install_intent_filters/Android.bp b/services/tests/servicestests/apks/install_intent_filters/Android.bp
new file mode 100644
index 0000000..59c8524
--- /dev/null
+++ b/services/tests/servicestests/apks/install_intent_filters/Android.bp
@@ -0,0 +1,7 @@
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_intent_filters",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+
+    srcs: ["**/*.java"],
+}
+
diff --git a/services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml b/services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml
new file mode 100644
index 0000000..fc7134d2
--- /dev/null
+++ b/services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+<manifest
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.frameworks.servicestests.install_intent_filters">
+
+<!--
+     This manifest declares an activity for testing intent filters.
+     The implementing class is an empty implementation.
+-->
+
+    <uses-feature
+        android:name="com.android.frameworks.servicestests.nonexistent" />
+    <uses-configuration
+        android:reqFiveWayNav="false" />
+
+    <instrumentation
+        android:name="android.test.InstrumentationTestRunner"
+        android:targetPackage="com.android.frameworks.coretests"
+        android:label="Frameworks Core Tests" />
+
+    <permission
+        android:label="test permission"
+        android:name="test_permission"
+        android:protectionLevel="normal" />
+
+    <application
+        android:hasCode="true">
+        <activity
+            android:name="com.android.frameworks.servicestests.TestActivity">
+            <intent-filter>
+                <action android:name="action1"/>
+                <data android:mimeGroup="mime_group_1"/>
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/core/java/android/service/controls/IControlsLoadCallback.aidl b/services/tests/servicestests/apks/install_intent_filters/src/com/android/frameworks/servicestests/TestActivity.java
similarity index 62%
rename from core/java/android/service/controls/IControlsLoadCallback.aidl
rename to services/tests/servicestests/apks/install_intent_filters/src/com/android/frameworks/servicestests/TestActivity.java
index bfc61cd..08a19aa 100644
--- a/core/java/android/service/controls/IControlsLoadCallback.aidl
+++ b/services/tests/servicestests/apks/install_intent_filters/src/com/android/frameworks/servicestests/TestActivity.java
@@ -1,11 +1,11 @@
 /*
- * Copyright (c) 2020, The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -14,13 +14,10 @@
  * limitations under the License.
  */
 
-package android.service.controls;
+package com.android.frameworks.coretests;
 
-import android.service.controls.Control;
+import android.app.Activity;
 
-/**
- * @hide
- */
-oneway interface IControlsLoadCallback {
-    void accept(in IBinder token, in List<Control> controls);
-}
\ No newline at end of file
+public class TestActivity extends Activity {
+
+}
diff --git a/services/tests/servicestests/apks/install_uses_sdk/Android.bp b/services/tests/servicestests/apks/install_uses_sdk/Android.bp
new file mode 100644
index 0000000..c24aa2b
--- /dev/null
+++ b/services/tests/servicestests/apks/install_uses_sdk/Android.bp
@@ -0,0 +1,39 @@
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r0",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r0.xml",
+
+    srcs: ["**/*.java"],
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r5",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r5.xml",
+
+    srcs: ["**/*.java"],
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_q0",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-q0.xml",
+
+    srcs: ["**/*.java"],
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_r",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-r.xml",
+
+    srcs: ["**/*.java"],
+}
+
+android_test_helper_app {
+    name: "FrameworksServicesTests_install_uses_sdk_0",
+    defaults: ["FrameworksServicesTests_apks_defaults"],
+    manifest: "AndroidManifest-0.xml",
+
+    srcs: ["**/*.java"],
+}
diff --git a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-0.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
similarity index 92%
rename from core/tests/coretests/apks/install_uses_sdk/AndroidManifest-0.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
index 634228b..215384b 100644
--- a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-0.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-0.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_uses_sdk">
+        package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This is invalid, because there is no sdk version specified -->
diff --git a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-q0.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0.xml
similarity index 93%
rename from core/tests/coretests/apks/install_uses_sdk/AndroidManifest-q0.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0.xml
index 8994966..c0e5867 100644
--- a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-q0.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-q0.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_uses_sdk">
+        package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This fails because 29 doesn't have an extension sdk -->
diff --git a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
similarity index 93%
rename from core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
index 0d0d8b9..5d22577 100644
--- a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_uses_sdk">
+        package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This is invalid, because there is no minimum extension version specified -->
diff --git a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r0.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
similarity index 92%
rename from core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r0.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
index a987afa..c1244f2 100644
--- a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r0.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r0.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_uses_sdk">
+        package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <extension-sdk android:sdkVersion="10000" android:minExtensionVersion="0" />
diff --git a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r5.xml b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
similarity index 93%
rename from core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r5.xml
rename to services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
index 9860096..3410938 100644
--- a/core/tests/coretests/apks/install_uses_sdk/AndroidManifest-r5.xml
+++ b/services/tests/servicestests/apks/install_uses_sdk/AndroidManifest-r5.xml
@@ -14,7 +14,7 @@
      limitations under the License.
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-        package="com.android.frameworks.coretests.install_uses_sdk">
+        package="com.android.frameworks.servicestests.install_uses_sdk">
 
     <uses-sdk android:minSdkVersion="4" android:targetSdkVersion="29">
         <!-- This will fail to install, because minExtensionVersion is not met -->
diff --git a/core/tests/coretests/apks/install_uses_sdk/res/values/strings.xml b/services/tests/servicestests/apks/install_uses_sdk/res/values/strings.xml
similarity index 100%
rename from core/tests/coretests/apks/install_uses_sdk/res/values/strings.xml
rename to services/tests/servicestests/apks/install_uses_sdk/res/values/strings.xml
diff --git a/core/tests/coretests/res/raw/com_android_tzdata.apex b/services/tests/servicestests/res/raw/com_android_tzdata.apex
similarity index 100%
rename from core/tests/coretests/res/raw/com_android_tzdata.apex
rename to services/tests/servicestests/res/raw/com_android_tzdata.apex
Binary files differ
diff --git a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
index 2a78b6f..2c84f26 100644
--- a/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/CachedDeviceStateServiceTest.java
@@ -26,6 +26,7 @@
 import android.os.BatteryManager;
 import android.os.BatteryManagerInternal;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.OsProtoEnums;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -52,13 +53,14 @@
 public class CachedDeviceStateServiceTest {
     @Mock private BatteryManagerInternal mBatteryManager;
     @Mock private IPowerManager mPowerManager;
+    @Mock private IThermalService mThermalService;
     private BroadcastInterceptingContext mContext;
 
     @Before
     public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
         Context context = InstrumentationRegistry.getContext();
-        PowerManager powerManager = new PowerManager(context, mPowerManager, null);
+        PowerManager powerManager = new PowerManager(context, mPowerManager, mThermalService, null);
         mContext = new BroadcastInterceptingContext(context) {
             @Override
             public Object getSystemService(String name) {
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
index dfe950e..ae8d554 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AbstractAccessibilityServiceConnectionTest.java
@@ -74,11 +74,11 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.PowerManager;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
-import android.testing.DexmakerShareClassLoaderRule;
 import android.view.Display;
 import android.view.KeyEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -91,7 +91,6 @@
 import com.android.server.wm.WindowManagerInternal;
 
 import org.junit.Before;
-import org.junit.Rule;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
 import org.mockito.Mock;
@@ -147,12 +146,9 @@
     private ArrayList<Integer> mDisplayList = new ArrayList<>(Arrays.asList(
             Display.DEFAULT_DISPLAY, SECONDARY_DISPLAY_ID));
 
-    // To mock package-private class.
-    @Rule public final DexmakerShareClassLoaderRule mDexmakerShareClassLoaderRule =
-            new DexmakerShareClassLoaderRule();
-
     @Mock private Context mMockContext;
     @Mock private IPowerManager mMockIPowerManager;
+    @Mock private IThermalService mMockIThermalService;
     @Mock private PackageManager mMockPackageManager;
     @Spy  private AccessibilityServiceInfo mSpyServiceInfo = new AccessibilityServiceInfo();
     @Mock private AccessibilitySecurityPolicy mMockSecurityPolicy;
@@ -180,7 +176,7 @@
                 .thenReturn(mMockMagnificationController);
 
         PowerManager powerManager =
-                new PowerManager(mMockContext, mMockIPowerManager, mHandler);
+                new PowerManager(mMockContext, mMockIPowerManager, mMockIThermalService, mHandler);
         when(mMockContext.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
         when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
         when(mMockPackageManager.hasSystemFeature(FEATURE_FINGERPRINT)).thenReturn(true);
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
index 4123556..85b8fcb 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/KeyEventDispatcherTest.java
@@ -34,6 +34,7 @@
 import android.content.Context;
 import android.os.Handler;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
@@ -73,6 +74,7 @@
     private KeyEventFilter mKeyEventFilter1;
     private KeyEventFilter mKeyEventFilter2;
     private IPowerManager mMockPowerManagerService;
+    private IThermalService mMockThermalService;
     private MessageCapturingHandler mMessageCapturingHandler;
     private ArgumentCaptor<Integer> mFilter1SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
     private ArgumentCaptor<Integer> mFilter2SequenceCaptor = ArgumentCaptor.forClass(Integer.class);
@@ -82,10 +84,12 @@
         Looper looper = InstrumentationRegistry.getContext().getMainLooper();
         mInputEventsHandler = new MessageCapturingHandler(looper, null);
         mMockPowerManagerService = mock(IPowerManager.class);
+        mMockThermalService = mock(IThermalService.class);
         // TODO: It would be better to mock PowerManager rather than its binder, but the class is
         // final.
         PowerManager powerManager =
-                new PowerManager(mock(Context.class), mMockPowerManagerService, new Handler(looper));
+                new PowerManager(mock(Context.class), mMockPowerManagerService, mMockThermalService,
+                        new Handler(looper));
         mMessageCapturingHandler = new MessageCapturingHandler(looper, null);
         mKeyEventDispatcher = new KeyEventDispatcher(mInputEventsHandler, SEND_FRAMEWORK_KEY_EVENT,
                 mLock, powerManager, mMessageCapturingHandler);
diff --git a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
index e90cb46..ac0cac1 100644
--- a/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/attention/AttentionManagerServiceTest.java
@@ -37,6 +37,7 @@
 import android.content.Context;
 import android.os.IBinder;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.provider.DeviceConfig;
@@ -74,6 +75,8 @@
     @Mock
     private IPowerManager mMockIPowerManager;
     @Mock
+    private IThermalService mMockIThermalService;
+    @Mock
     Context mContext;
 
     @Before
@@ -84,7 +87,7 @@
         // setup power manager mock
         PowerManager mPowerManager;
         doReturn(true).when(mMockIPowerManager).isInteractive();
-        mPowerManager = new PowerManager(mContext, mMockIPowerManager, null);
+        mPowerManager = new PowerManager(mContext, mMockIPowerManager, mMockIThermalService, null);
 
         Object mLock = new Object();
         // setup a spy on attention manager
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
index 1c8b00f..30bb38a 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/AuthServiceTest.java
@@ -111,6 +111,29 @@
                 any());
     }
 
+    @Test
+    public void testRegisterAuthenticator_callsInitConfiguredStrength() throws Exception {
+
+        final String[] config = {
+                "0:2:15", // ID0:Fingerprint:Strong
+                "1:4:255", // ID1:Iris:Weak
+                "2:8:4095", // ID2:Face:Convenience
+        };
+
+        when(mInjector.getConfiguration(any())).thenReturn(config);
+
+        mAuthService = new AuthService(mContext, mInjector);
+        mAuthService.onStart();
+
+        final int fingerprintStrength = 15;
+        final int irisStrength = 255;
+        final int faceStrength = 4095;
+
+        verify(mFingerprintService).initConfiguredStrength(eq(fingerprintStrength));
+        verify(mIrisService).initConfiguredStrength(eq(irisStrength));
+        verify(mFaceService).initConfiguredStrength(eq(faceStrength));
+    }
+
 
     // TODO(b/141025588): Check that an exception is thrown when the userId != callingUserId
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
index 407f67e..44f4ccf 100644
--- a/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/CompatConfigTest.java
@@ -24,6 +24,7 @@
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertThrows;
 
+import android.app.compat.ChangeIdStateCache;
 import android.content.Context;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
@@ -74,6 +75,7 @@
         // Assume userdebug/eng non-final build
         when(mBuildClassifier.isDebuggableBuild()).thenReturn(true);
         when(mBuildClassifier.isFinalBuild()).thenReturn(false);
+        ChangeIdStateCache.disable();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
index 4a686ee..53b90f2 100644
--- a/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
+++ b/services/tests/servicestests/src/com/android/server/compat/PlatformCompatTest.java
@@ -62,6 +62,7 @@
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
+        android.app.compat.ChangeIdStateCache.disable();
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         when(mPackageManager.getPackageUid(eq(PACKAGE_NAME), eq(0))).thenThrow(
                 new PackageManager.NameNotFoundException());
diff --git a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
index e37ed79..2cbc3f3 100644
--- a/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
+++ b/services/tests/servicestests/src/com/android/server/content/SyncOperationTest.java
@@ -124,8 +124,9 @@
         SyncOperation op2 = SyncOperation.maybeCreateFromJobExtras(pb);
 
         assertTrue("Account fields in extras not persisted.",
-                account1.equals(op2.extras.get("acc")));
-        assertTrue("Fields in extras not persisted", "String".equals(op2.extras.getString("str")));
+                account1.equals(op2.getClonedExtras().get("acc")));
+        assertTrue("Fields in extras not persisted", "String".equals(
+                op2.getClonedExtras().getString("str")));
     }
 
     @SmallTest
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
index 9574a08..40b0e71 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceMigrationTest.java
@@ -31,8 +31,11 @@
 import android.os.Bundle;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.platform.test.annotations.Presubmit;
 import android.provider.Settings;
 
+import androidx.test.filters.SmallTest;
+
 import com.android.frameworks.servicestests.R;
 import com.android.server.LocalServices;
 import com.android.server.SystemService;
@@ -43,7 +46,7 @@
 import java.util.Map;
 import java.util.Set;
 
-// TODO (b/143516163): Fix old test cases and put into presubmit.
+// TODO (b/149818286): Fix old test cases and put the whole test into presubmit.
 public class DevicePolicyManagerServiceMigrationTest extends DpmTestBase {
 
     private static final String USER_TYPE_EMPTY = "";
@@ -343,6 +346,8 @@
         assertTrue(alreadySet.contains(UserManager.DISALLOW_BLUETOOTH_SHARING));
     }
 
+    @Presubmit
+    @SmallTest
     public void testCompMigrationUnAffiliated_skipped() throws Exception {
         prepareAdmin1AsDo();
         prepareAdminAnotherPackageAsPo(COPE_PROFILE_USER_ID);
@@ -354,6 +359,8 @@
         assertTrue(dpms.mOwners.hasDeviceOwner());
     }
 
+    @Presubmit
+    @SmallTest
     public void testCompMigrationAffiliated() throws Exception {
         prepareAdmin1AsDo();
         prepareAdmin1AsPo(COPE_PROFILE_USER_ID);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 3a8258b..853151f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -369,6 +369,12 @@
         }
 
         @Override
+        PendingIntent pendingIntentGetBroadcast(Context context, int requestCode,
+                Intent intent, int flags) {
+            return null;
+        }
+
+        @Override
         void registerContentObserver(Uri uri, boolean notifyForDescendents,
                 ContentObserver observer, int userHandle) {
             mContentObservers.put(new Pair<Uri, Integer>(uri, userHandle), observer);
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 37ce510..ac818ea 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -26,6 +26,7 @@
 import static android.app.admin.DevicePolicyManager.PASSWORD_COMPLEXITY_NONE;
 import static android.app.admin.DevicePolicyManager.WIPE_EUICC;
 import static android.app.admin.PasswordMetrics.computeForPassword;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_DIRECT_BOOT_AWARE;
 
 import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_NONE;
 import static com.android.internal.widget.LockPatternUtils.EscrowTokenStateChangeCallback;
@@ -2097,7 +2098,8 @@
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED),
-                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+                eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
     }
 
     public void testSetFactoryResetProtectionPolicyFailWithPO() throws Exception {
@@ -2144,7 +2146,8 @@
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED),
-                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+                eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
     }
 
     public void testGetFactoryResetProtectionPolicyWithFrpManagementAgent()
@@ -2171,7 +2174,8 @@
         verify(mContext.spiedContext).sendBroadcastAsUser(
                 MockUtils.checkIntentAction(
                         DevicePolicyManager.ACTION_RESET_PROTECTION_POLICY_CHANGED),
-                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE));
+                MockUtils.checkUserHandle(DpmMockContext.CALLER_USER_HANDLE),
+                eq(android.Manifest.permission.MANAGE_FACTORY_RESET_PROTECTION));
     }
 
     private void assertPoliciesAreEqual(FactoryResetProtectionPolicy expectedPolicy,
@@ -3948,13 +3952,8 @@
     }
 
     public void testIsOrganizationOwnedDevice() throws Exception {
-        setupProfileOwner();
         // Set up the user manager to return correct user info
-        UserInfo managedProfileUserInfo = new UserInfo(DpmMockContext.CALLER_USER_HANDLE,
-                "managed profile",
-                UserInfo.FLAG_MANAGED_PROFILE);
-        when(getServices().userManager.getUsers())
-                .thenReturn(Arrays.asList(managedProfileUserInfo));
+        addManagedProfile(admin1, DpmMockContext.CALLER_UID, admin1);
 
         // Any caller should be able to call this method.
         assertFalse(dpm.isOrganizationOwnedDeviceWithManagedProfile());
@@ -5905,8 +5904,6 @@
     }
 
     private void configureProfileOwnerOfOrgOwnedDevice(ComponentName who, int userId) {
-        when(getServices().userManager.getProfileParent(eq(UserHandle.of(userId))))
-                .thenReturn(UserHandle.SYSTEM);
         final long ident = mServiceContext.binder.clearCallingIdentity();
         mServiceContext.binder.callingUid = UserHandle.getUid(userId, DpmMockContext.SYSTEM_UID);
 
@@ -6045,6 +6042,86 @@
         assertTrue(dpm.isCommonCriteriaModeEnabled(admin1));
     }
 
+    public void testCanProfileOwnerResetPasswordWhenLocked_nonDirectBootAwarePo()
+            throws Exception {
+        setDeviceEncryptionPerUser();
+        setupProfileOwner();
+        setupPasswordResetToken();
+
+        mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+        assertFalse("po is not direct boot aware",
+                dpm.canProfileOwnerResetPasswordWhenLocked(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    public void testCanProfileOwnerResetPasswordWhenLocked_noActiveToken() throws Exception {
+        setDeviceEncryptionPerUser();
+        setupProfileOwner();
+        makeAdmin1DirectBootAware();
+
+        mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+        assertFalse("po doesn't have an active password reset token",
+                dpm.canProfileOwnerResetPasswordWhenLocked(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    public void testCanProfileOwnerResetPasswordWhenLocked_nonFbeDevice() throws Exception {
+        setupProfileOwner();
+        makeAdmin1DirectBootAware();
+        setupPasswordResetToken();
+
+        mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+        assertFalse("device is not FBE",
+                dpm.canProfileOwnerResetPasswordWhenLocked(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    public void testCanProfileOwnerResetPasswordWhenLocked() throws Exception {
+        setDeviceEncryptionPerUser();
+        setupProfileOwner();
+        makeAdmin1DirectBootAware();
+        setupPasswordResetToken();
+
+        mContext.binder.callingUid = DpmMockContext.SYSTEM_UID;
+        assertTrue("direct boot aware po with active password reset token",
+                dpm.canProfileOwnerResetPasswordWhenLocked(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    private void setupPasswordResetToken() {
+        final byte[] token = new byte[32];
+        final long handle = 123456;
+
+        when(getServices().lockPatternUtils
+                .addEscrowToken(eq(token), eq(DpmMockContext.CALLER_USER_HANDLE),
+                        nullable(EscrowTokenStateChangeCallback.class)))
+                .thenReturn(handle);
+
+        dpm.setResetPasswordToken(admin1, token);
+
+        when(getServices().lockPatternUtils
+                .isEscrowTokenActive(eq(handle), eq(DpmMockContext.CALLER_USER_HANDLE)))
+                .thenReturn(true);
+
+        assertTrue("failed to activate token", dpm.isResetPasswordTokenActive(admin1));
+    }
+
+    private void makeAdmin1DirectBootAware()
+            throws PackageManager.NameNotFoundException, android.os.RemoteException {
+        Mockito.reset(getServices().ipackageManager);
+
+        final ApplicationInfo ai = DpmTestUtils.cloneParcelable(
+                mRealTestContext.getPackageManager().getApplicationInfo(
+                        admin1.getPackageName(),
+                        PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS));
+        ai.privateFlags = PRIVATE_FLAG_DIRECT_BOOT_AWARE;
+
+        doReturn(ai).when(getServices().ipackageManager).getApplicationInfo(
+                eq(admin1.getPackageName()),
+                anyInt(),
+                eq(DpmMockContext.CALLER_USER_HANDLE));
+    }
+
+    private void setDeviceEncryptionPerUser() {
+        when(getServices().storageManager.isFileBasedEncryptionEnabled()).thenReturn(true);
+    }
+
     private void setCrossProfileAppsList(String... packages) {
         when(mContext.getResources()
                 .getStringArray(eq(R.array.cross_profile_apps)))
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
index 37d4081..01f1a3e 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockSystemServices.java
@@ -265,6 +265,9 @@
                             .toArray();
                 }
         );
+        when(userManagerInternal.getUserInfos()).thenReturn(
+                mUserInfos.toArray(new UserInfo[mUserInfos.size()]));
+
         when(accountManager.getAccountsAsUser(anyInt())).thenReturn(new Account[0]);
 
         // Create a data directory.
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
index 0f05212..8dcf21f 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/SecurityEventTest.java
@@ -1,31 +1,43 @@
 package com.android.server.devicepolicy;
 
 import static android.app.admin.SecurityLog.TAG_ADB_SHELL_CMD;
+import static android.app.admin.SecurityLog.TAG_APP_PROCESS_START;
+import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_INSTALLED;
+import static android.app.admin.SecurityLog.TAG_CERT_AUTHORITY_REMOVED;
+import static android.app.admin.SecurityLog.TAG_KEY_DESTRUCTION;
+import static android.app.admin.SecurityLog.TAG_KEY_GENERATED;
+import static android.app.admin.SecurityLog.TAG_KEY_IMPORT;
+import static android.app.admin.SecurityLog.TAG_KEY_INTEGRITY_VIOLATION;
+import static android.app.admin.SecurityLog.TAG_MEDIA_MOUNT;
+import static android.app.admin.SecurityLog.TAG_MEDIA_UNMOUNT;
 
 import android.app.admin.SecurityLog.SecurityEvent;
 import android.os.Parcel;
-import android.test.suitebuilder.annotation.SmallTest;
+import android.os.UserHandle;
+import android.text.TextUtils;
 import android.util.EventLog;
+import android.util.EventLog.Event;
 
-import java.io.IOException;
+import junit.framework.AssertionFailedError;
+
 import java.util.ArrayList;
 import java.util.List;
 
-@SmallTest
 public class SecurityEventTest extends DpmTestBase {
-    private static long ID = 549;
-    private static String DATA = "adb shell some_command";
 
-    public void testSecurityEventId() {
-        SecurityEvent event = buildSecurityEvents(1 /* generate a single event */, ID).get(0);
-        assertEquals(ID, event.getId());
+    public void testSecurityEventId() throws Exception {
+        SecurityEvent event = createEvent(() -> {
+            EventLog.writeEvent(TAG_ADB_SHELL_CMD, 0);
+        }, TAG_ADB_SHELL_CMD);
         event.setId(20);
         assertEquals(20, event.getId());
     }
 
-    public void testSecurityEventParceling() {
+    public void testSecurityEventParceling() throws Exception {
         // GIVEN an event.
-        SecurityEvent event = buildSecurityEvents(1 /* generate a single event */, ID).get(0);
+        SecurityEvent event = createEvent(() -> {
+            EventLog.writeEvent(TAG_ADB_SHELL_CMD, "test");
+        }, TAG_ADB_SHELL_CMD);
         // WHEN parceling the event.
         Parcel p = Parcel.obtain();
         p.writeParcelable(event, 0);
@@ -39,23 +51,104 @@
         assertEquals(event.getId(), unparceledEvent.getId());
     }
 
-    private List<SecurityEvent> buildSecurityEvents(int numEvents, long id) {
-        // Write an event to the EventLog.
-        for (int i = 0; i < numEvents; i++) {
-            EventLog.writeEvent(TAG_ADB_SHELL_CMD, DATA + "_" + i);
+    public void testSecurityEventRedaction() throws Exception {
+        SecurityEvent event;
+
+        // TAG_ADB_SHELL_CMD will has the command redacted
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_ADB_SHELL_CMD, "command");
+        }, TAG_ADB_SHELL_CMD);
+        assertFalse(TextUtils.isEmpty((String) event.getData()));
+
+        // TAG_MEDIA_MOUNT will have the volume label redacted (second data)
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_MEDIA_MOUNT, new Object[] {"path", "label"});
+        }, TAG_MEDIA_MOUNT);
+        assertFalse(TextUtils.isEmpty(event.getStringData(1)));
+        assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+
+        // TAG_MEDIA_UNMOUNT will have the volume label redacted (second data)
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_MEDIA_UNMOUNT, new Object[] {"path", "label"});
+        }, TAG_MEDIA_UNMOUNT);
+        assertFalse(TextUtils.isEmpty(event.getStringData(1)));
+        assertTrue(TextUtils.isEmpty(event.redact(0).getStringData(1)));
+
+        // TAG_APP_PROCESS_START will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_APP_PROCESS_START, new Object[] {"process", 12345L,
+                    UserHandle.getUid(10, 123), 456, "seinfo", "hash"});
+        }, TAG_APP_PROCESS_START);
+        assertNotNull(event.redact(10));
+        assertNull(event.redact(11));
+
+        // TAG_CERT_AUTHORITY_INSTALLED will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_CERT_AUTHORITY_INSTALLED, new Object[] {1, "subject", 10});
+        }, TAG_CERT_AUTHORITY_INSTALLED);
+        assertNotNull(event.redact(10));
+        assertNull(event.redact(11));
+
+        // TAG_CERT_AUTHORITY_REMOVED will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_CERT_AUTHORITY_REMOVED, new Object[] {1, "subject", 20});
+        }, TAG_CERT_AUTHORITY_REMOVED);
+        assertNotNull(event.redact(20));
+        assertNull(event.redact(0));
+
+        // TAG_KEY_GENERATED will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_KEY_GENERATED,
+                    new Object[] {1, "alias", UserHandle.getUid(0, 123)});
+        }, TAG_KEY_GENERATED);
+        assertNotNull(event.redact(0));
+        assertNull(event.redact(10));
+
+        // TAG_KEY_IMPORT will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_KEY_IMPORT,
+                    new Object[] {1, "alias", UserHandle.getUid(1, 123)});
+        }, TAG_KEY_IMPORT);
+        assertNotNull(event.redact(1));
+        assertNull(event.redact(10));
+
+        // TAG_KEY_DESTRUCTION will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_KEY_DESTRUCTION,
+                    new Object[] {1, "alias", UserHandle.getUid(2, 123)});
+        }, TAG_KEY_DESTRUCTION);
+        assertNotNull(event.redact(2));
+        assertNull(event.redact(10));
+
+        // TAG_KEY_INTEGRITY_VIOLATION will be fully redacted if user does not match
+        event = createEvent(() -> {
+            EventLog.writeEvent(TAG_KEY_INTEGRITY_VIOLATION,
+                    new Object[] {"alias", UserHandle.getUid(2, 123)});
+        }, TAG_KEY_INTEGRITY_VIOLATION);
+        assertNotNull(event.redact(2));
+        assertNull(event.redact(10));
+
+    }
+
+    /**
+     * Creates an Event object. Only the native code has the serialization and deserialization logic
+     * so need to actually emit a real log in order to generate the object.
+     */
+    private SecurityEvent createEvent(Runnable generator, int expectedTag) throws Exception {
+        Long markerData = System.currentTimeMillis();
+        EventLog.writeEvent(expectedTag, markerData);
+        generator.run();
+
+        List<Event> events = new ArrayList<>();
+        // Give the message some time to show up in the log
+        Thread.sleep(20);
+        EventLog.readEvents(new int[] {expectedTag}, events);
+
+        for (int i = 0; i < events.size() - 1; i++) {
+            if (markerData.equals(events.get(i).getData())) {
+                return new SecurityEvent(0, events.get(i + 1).getBytes());
+            }
         }
-        List<EventLog.Event> events = new ArrayList<>();
-        try {
-            EventLog.readEvents(new int[]{TAG_ADB_SHELL_CMD}, events);
-        } catch (IOException e) {
-            fail("Reading a test event from storage failed: " + e);
-        }
-        assertTrue("Unexpected number of events read from the log.", events.size() >= numEvents);
-        // Read events generated by test, from the end of the log.
-        List<SecurityEvent> securityEvents = new ArrayList<>();
-        for (int i = events.size() - numEvents; i < events.size(); i++) {
-          securityEvents.add(new SecurityEvent(id++, events.get(i).getBytes()));
-        }
-        return securityEvents;
+        throw new AssertionFailedError("Unable to locate marker event");
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 25d0778..feae1e1 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -29,6 +29,12 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
+import com.android.server.display.DisplayModeDirector.RefreshRateRange;
+import com.android.server.display.DisplayModeDirector.Vote;
+
+import com.google.common.truth.Truth;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -37,6 +43,9 @@
 @SmallTest
 @RunWith(AndroidJUnit4.class)
 public class DisplayModeDirectorTest {
+    // The tolerance within which we consider something approximately equals.
+    private static final float FLOAT_TOLERANCE = 0.01f;
+
     private Context mContext;
 
     @Before
@@ -56,30 +65,22 @@
             modes[i - minFps] = new Display.Mode(
                     /*modeId=*/i, /*width=*/1000, /*height=*/1000, /*refreshRate=*/i);
         }
-        SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<Display.Mode[]>();
+        SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
         supportedModesByDisplay.put(displayId, modes);
         director.injectSupportedModesByDisplay(supportedModesByDisplay);
-        SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<Display.Mode>();
+        SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>();
         defaultModesByDisplay.put(displayId, modes[0]);
         director.injectDefaultModeByDisplay(defaultModesByDisplay);
         return director;
     }
 
-    private int[] intRange(int min, int max) {
-        int[] range = new int[max - min + 1];
-        for (int i = min; i <= max; i++) {
-            range[i - min] = i;
-        }
-        return range;
-    }
-
     @Test
     public void testDisplayModeVoting() {
         int displayId = 0;
 
         // With no votes present, DisplayModeDirector should allow any refresh rate.
-        assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*baseModeId=*/60,
-                             new DisplayModeDirector.RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
+        assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/60,
+                             new RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
                 createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
                         displayId));
 
@@ -93,20 +94,16 @@
             int maxFps = 90;
             DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
             assertTrue(2 * numPriorities < maxFps - minFps + 1);
-            SparseArray<DisplayModeDirector.Vote> votes =
-                    new SparseArray<DisplayModeDirector.Vote>();
-            SparseArray<SparseArray<DisplayModeDirector.Vote>> votesByDisplay =
-                    new SparseArray<SparseArray<DisplayModeDirector.Vote>>();
+            SparseArray<Vote> votes = new SparseArray<>();
+            SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
             votesByDisplay.put(displayId, votes);
             for (int i = 0; i < numPriorities; i++) {
-                int priority = DisplayModeDirector.Vote.MIN_PRIORITY + i;
-                votes.put(
-                        priority, DisplayModeDirector.Vote.forRefreshRates(minFps + i, maxFps - i));
+                int priority = Vote.MIN_PRIORITY + i;
+                votes.put(priority, Vote.forRefreshRates(minFps + i, maxFps - i));
                 director.injectVotesByDisplay(votesByDisplay);
-                assertEquals(
-                        new DisplayModeDirector.DesiredDisplayModeSpecs(
+                assertEquals(new DesiredDisplayModeSpecs(
                                 /*baseModeId=*/minFps + i,
-                                new DisplayModeDirector.RefreshRateRange(minFps + i, maxFps - i)),
+                                new RefreshRateRange(minFps + i, maxFps - i)),
                         director.getDesiredDisplayModeSpecs(displayId));
             }
         }
@@ -116,19 +113,35 @@
         {
             assertTrue(numPriorities >= 2);
             DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
-            SparseArray<DisplayModeDirector.Vote> votes =
-                    new SparseArray<DisplayModeDirector.Vote>();
-            SparseArray<SparseArray<DisplayModeDirector.Vote>> votesByDisplay =
-                    new SparseArray<SparseArray<DisplayModeDirector.Vote>>();
+            SparseArray<Vote> votes = new SparseArray<>();
+            SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
             votesByDisplay.put(displayId, votes);
-            votes.put(DisplayModeDirector.Vote.MAX_PRIORITY,
-                    DisplayModeDirector.Vote.forRefreshRates(65, 85));
-            votes.put(DisplayModeDirector.Vote.MIN_PRIORITY,
-                    DisplayModeDirector.Vote.forRefreshRates(70, 80));
+            votes.put(Vote.MAX_PRIORITY, Vote.forRefreshRates(65, 85));
+            votes.put(Vote.MIN_PRIORITY, Vote.forRefreshRates(70, 80));
             director.injectVotesByDisplay(votesByDisplay);
-            assertEquals(new DisplayModeDirector.DesiredDisplayModeSpecs(/*baseModeId=*/70,
-                                 new DisplayModeDirector.RefreshRateRange(70, 80)),
+            assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/70,
+                                 new RefreshRateRange(70, 80)),
                     director.getDesiredDisplayModeSpecs(displayId));
         }
     }
+
+    @Test
+    public void testVotingWithFloatingPointErrors() {
+        int displayId = 0;
+        DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(50, 90);
+        SparseArray<Vote> votes = new SparseArray<>();
+        SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+        votesByDisplay.put(displayId, votes);
+        float error = FLOAT_TOLERANCE / 4;
+        votes.put(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, Vote.forRefreshRates(0, 60));
+        votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forRefreshRates(60 + error, 60 + error));
+        votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE,
+                Vote.forRefreshRates(60 - error, 60 - error));
+        director.injectVotesByDisplay(votesByDisplay);
+        DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
+
+        Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
+        Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+        Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60);
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
index 50ed975..0551f2e 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystemTest.java
@@ -76,6 +76,7 @@
     private boolean mMutingEnabled;
     private boolean mArcSupport;
     private HdmiPortInfo[] mHdmiPortInfo;
+    private boolean mWokenUp;
 
     @Before
     public void setUp() {
@@ -138,7 +139,9 @@
                 }
 
                 @Override
-                void wakeUp() {}
+                void wakeUp() {
+                    mWokenUp = true;
+                }
 
                 @Override
                 void invokeDeviceEventListeners(HdmiDeviceInfo device, int status) {
@@ -698,4 +701,18 @@
             .getCecDeviceInfo(differentDevice.getLogicalAddress())).isEqualTo(differentDevice);
         assertThat(mInvokeDeviceEventState).isEqualTo(DEVICE_EVENT_ADD_DEVICE);
     }
+
+    @Test
+    public void doNotWakeUpOnHotPlug_PlugIn() {
+        mWokenUp = false;
+        mHdmiCecLocalDeviceAudioSystem.onHotplug(0, true);
+        assertThat(mWokenUp).isFalse();
+    }
+
+    @Test
+    public void doNotWakeUpOnHotPlug_PlugOut() {
+        mWokenUp = false;
+        mHdmiCecLocalDeviceAudioSystem.onHotplug(0, false);
+        assertThat(mWokenUp).isFalse();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
index 0062a17..4a1af51 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiCecLocalDevicePlaybackTest.java
@@ -47,6 +47,7 @@
     private TestLooper mTestLooper = new TestLooper();
     private ArrayList<HdmiCecLocalDevice> mLocalDevices = new ArrayList<>();
     private int mPlaybackPhysicalAddress;
+    private boolean mWokenUp;
 
     @Before
     public void setUp() {
@@ -54,6 +55,7 @@
             new HdmiControlService(InstrumentationRegistry.getTargetContext()) {
                 @Override
                 void wakeUp() {
+                    mWokenUp = true;
                 }
 
                 @Override
@@ -135,4 +137,18 @@
         assertThat(mHdmiCecLocalDevicePlayback.handleSystemAudioModeStatus(message)).isTrue();
         assertThat(mHdmiCecLocalDevicePlayback.mService.isSystemAudioActivated()).isTrue();
     }
+
+    @Test
+    public void doNotWakeUpOnHotPlug_PlugIn() {
+        mWokenUp = false;
+        mHdmiCecLocalDevicePlayback.onHotplug(0, true);
+        assertThat(mWokenUp).isFalse();
+    }
+
+    @Test
+    public void doNotWakeUpOnHotPlug_PlugOut() {
+        mWokenUp = false;
+        mHdmiCecLocalDevicePlayback.onHotplug(0, false);
+        assertThat(mWokenUp).isFalse();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
index 9e98427..fa19814 100644
--- a/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/hdmi/HdmiControlServiceTest.java
@@ -34,6 +34,7 @@
 import android.hardware.hdmi.HdmiControlManager;
 import android.hardware.hdmi.HdmiPortInfo;
 import android.os.IPowerManager;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -123,6 +124,7 @@
     private HdmiPortInfo[] mHdmiPortInfo;
 
     @Mock private IPowerManager mIPowerManagerMock;
+    @Mock private IThermalService mIThermalServiceMock;
 
     @Before
     public void setUp() throws Exception {
@@ -130,7 +132,8 @@
 
         mContextSpy = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
 
-        PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock, null);
+        PowerManager powerManager = new PowerManager(mContextSpy, mIPowerManagerMock,
+                mIThermalServiceMock, null);
         when(mContextSpy.getSystemService(Context.POWER_SERVICE)).thenReturn(powerManager);
         when(mIPowerManagerMock.isInteractive()).thenReturn(true);
 
diff --git a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
index 3dc26af..ab21ab0 100644
--- a/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/integrity/parser/RuleBinaryParserTest.java
@@ -73,7 +73,7 @@
     private static final String APP_CERTIFICATE = getBits(AtomicFormula.APP_CERTIFICATE, KEY_BITS);
     private static final String VERSION_CODE = getBits(AtomicFormula.VERSION_CODE, KEY_BITS);
     private static final String PRE_INSTALLED = getBits(AtomicFormula.PRE_INSTALLED, KEY_BITS);
-    private static final int INVALID_KEY_VALUE = 6;
+    private static final int INVALID_KEY_VALUE = 8;
     private static final String INVALID_KEY = getBits(INVALID_KEY_VALUE, KEY_BITS);
 
     private static final String EQ = getBits(AtomicFormula.EQ, OPERATOR_BITS);
diff --git a/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java b/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java
index 6fafe11..9b076e8 100644
--- a/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/MockableLocationProviderTest.java
@@ -118,16 +118,6 @@
     }
 
     @Test
-    public void testRequestSetAllowed() {
-        mProvider.requestSetAllowed(true);
-        verify(mRealProvider, times(1)).onRequestSetAllowed(true);
-
-        mProvider.setMockProvider(mMockProvider);
-        mProvider.requestSetAllowed(true);
-        verify(mMockProvider, times(1)).onRequestSetAllowed(true);
-    }
-
-    @Test
     public void testSendExtraCommand() {
         mProvider.sendExtraCommand(0, 0, "command", null);
         verify(mRealProvider, times(1)).onExtraCommand(0, 0, "command", null);
diff --git a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
index 19cbb0e..a99c982 100644
--- a/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/location/gnss/GnssManagerServiceTest.java
@@ -38,6 +38,7 @@
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.location.GnssAntennaInfo;
+import android.location.GnssAntennaInfo.SphericalCorrections;
 import android.location.GnssClock;
 import android.location.GnssMeasurementCorrections;
 import android.location.GnssMeasurementsEvent;
@@ -245,8 +246,8 @@
     private static List<GnssAntennaInfo> createDummyGnssAntennaInfos() {
         double carrierFrequencyMHz = 13758.0;
 
-        GnssAntennaInfo.PhaseCenterOffsetCoordinates phaseCenterOffsetCoordinates = new
-                GnssAntennaInfo.PhaseCenterOffsetCoordinates(
+        GnssAntennaInfo.PhaseCenterOffset phaseCenterOffset = new
+                GnssAntennaInfo.PhaseCenterOffset(
                 4.3d,
                 1.4d,
                 2.10d,
@@ -256,22 +257,26 @@
 
         double[][] phaseCenterVariationCorrectionsMillimeters = new double[10][10];
         double[][] phaseCenterVariationCorrectionsUncertaintyMillimeters = new double[10][10];
-        GnssAntennaInfo.PhaseCenterVariationCorrections
+        SphericalCorrections
                 phaseCenterVariationCorrections =
-                new GnssAntennaInfo.PhaseCenterVariationCorrections(
+                new SphericalCorrections(
                         phaseCenterVariationCorrectionsMillimeters,
                         phaseCenterVariationCorrectionsUncertaintyMillimeters);
 
         double[][] signalGainCorrectionsDbi = new double[10][10];
         double[][] signalGainCorrectionsUncertaintyDbi = new double[10][10];
-        GnssAntennaInfo.SignalGainCorrections signalGainCorrections = new
-                GnssAntennaInfo.SignalGainCorrections(
+        SphericalCorrections signalGainCorrections = new
+                SphericalCorrections(
                 signalGainCorrectionsDbi,
                 signalGainCorrectionsUncertaintyDbi);
 
         List<GnssAntennaInfo> gnssAntennaInfos = new ArrayList();
-        gnssAntennaInfos.add(new GnssAntennaInfo(carrierFrequencyMHz, phaseCenterOffsetCoordinates,
-                phaseCenterVariationCorrections, signalGainCorrections));
+        gnssAntennaInfos.add(new GnssAntennaInfo.Builder()
+                .setCarrierFrequencyMHz(carrierFrequencyMHz)
+                .setPhaseCenterOffset(phaseCenterOffset)
+                .setPhaseCenterVariationCorrections(phaseCenterVariationCorrections)
+                .setSignalGainCorrections(signalGainCorrections)
+                .build());
         return gnssAntennaInfos;
     }
 
@@ -388,14 +393,6 @@
     }
 
     @Test
-    public void getGnssCapabilitiesWithoutPermissionsTest() {
-        disableLocationPermissions();
-
-        assertThrows(SecurityException.class,
-                () -> mGnssManagerService.getGnssCapabilities("com.android.server"));
-    }
-
-    @Test
     public void getGnssCapabilitiesWithPermissionsTest() {
         final long mGnssCapabilities = 23132L;
         when(mMockGnssCapabilitiesProvider.getGnssCapabilities()).thenReturn(mGnssCapabilities);
diff --git a/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java b/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java
index 762080f..5943f67 100644
--- a/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java
+++ b/services/tests/servicestests/src/com/android/server/location/test/FakeProvider.java
@@ -38,8 +38,5 @@
     protected void onExtraCommand(int uid, int pid, String command, Bundle extras) {}
 
     @Override
-    protected void onRequestSetAllowed(boolean allowed) {}
-
-    @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {}
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
new file mode 100644
index 0000000..c4fea77
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplRebootTests.java
@@ -0,0 +1,188 @@
+/*
+ * 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.om;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import android.content.om.OverlayInfo;
+
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(AndroidJUnit4.class)
+public class OverlayManagerServiceImplRebootTests extends OverlayManagerServiceImplTestsBase {
+
+    private static final String OVERLAY = "com.dummy.overlay";
+    private static final String TARGET = "com.dummy.target";
+    private static final int USER = 0;
+
+    private static final String OVERLAY2 = OVERLAY + "2";
+
+    @Test
+    public void testUpdateOverlaysForUser() {
+        final OverlayManagerServiceImpl impl = getImpl();
+        installTargetPackage(TARGET, USER);
+        installTargetPackage("some.other.target", USER);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+
+        // do nothing, expect no change
+        final List<String> a = impl.updateOverlaysForUser(USER);
+        assertEquals(1, a.size());
+        assertTrue(a.contains(TARGET));
+
+        // upgrade overlay, keep target
+        beginUpgradeOverlayPackage(OVERLAY, USER);
+        endUpgradeOverlayPackage(OVERLAY, TARGET, USER);
+
+        final List<String> b = impl.updateOverlaysForUser(USER);
+        assertEquals(1, b.size());
+        assertTrue(b.contains(TARGET));
+
+        // do nothing, expect no change
+        final List<String> c = impl.updateOverlaysForUser(USER);
+        assertEquals(1, c.size());
+        assertTrue(c.contains(TARGET));
+
+        // upgrade overlay, switch to new target
+        addOverlayPackage(OVERLAY, "some.other.target", USER, true, false, 0);
+        final List<String> d = impl.updateOverlaysForUser(USER);
+        assertEquals(2, d.size());
+        assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
+
+        // do nothing, expect no change
+        final List<String> f = impl.updateOverlaysForUser(USER);
+        assertEquals(1, f.size());
+        assertTrue(f.contains("some.other.target"));
+    }
+
+    @Test
+    public void testImmutableEnabledChange() {
+        final OverlayManagerServiceImpl impl = getImpl();
+        installTargetPackage(TARGET, USER);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o1);
+        assertFalse(o1.isEnabled());
+        assertFalse(o1.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o2);
+        assertTrue(o2.isEnabled());
+        assertFalse(o2.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o3);
+        assertFalse(o3.isEnabled());
+        assertFalse(o3.isMutable);
+    }
+
+    @Test
+    public void testMutableEnabledChangeHasNoEffect() {
+        final OverlayManagerServiceImpl impl = getImpl();
+        installTargetPackage(TARGET, USER);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o1);
+        assertFalse(o1.isEnabled());
+        assertTrue(o1.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, true, true, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o2);
+        assertFalse(o2.isEnabled());
+        assertTrue(o2.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o3);
+        assertFalse(o3.isEnabled());
+        assertTrue(o3.isMutable);
+    }
+
+    @Test
+    public void testMutabilityChange() {
+        final OverlayManagerServiceImpl impl = getImpl();
+        installTargetPackage(TARGET, USER);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o1);
+        assertTrue(o1.isEnabled());
+        assertFalse(o1.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, true, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o2);
+        assertFalse(o2.isEnabled());
+        assertTrue(o2.isMutable);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, false, 0);
+        impl.updateOverlaysForUser(USER);
+        final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+        assertNotNull(o3);
+        assertFalse(o3.isEnabled());
+        assertFalse(o3.isMutable);
+    }
+
+    @Test
+    public void testPriorityChange() {
+        final OverlayManagerServiceImpl impl = getImpl();
+        installTargetPackage(TARGET, USER);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 0);
+        addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 1);
+        impl.updateOverlaysForUser(USER);
+
+        final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+        final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
+        assertNotNull(o1);
+        assertNotNull(o2);
+        assertEquals(0, o1.priority);
+        assertEquals(1, o2.priority);
+
+        addOverlayPackage(OVERLAY, TARGET, USER, false, true, 1);
+        addOverlayPackage(OVERLAY2, TARGET, USER, false, true, 0);
+        impl.updateOverlaysForUser(USER);
+
+        final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY, USER);
+        final OverlayInfo o4 = impl.getOverlayInfo(OVERLAY2, USER);
+        assertNotNull(o3);
+        assertNotNull(o4);
+        assertEquals(1, o3.priority);
+        assertEquals(0, o4.priority);
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
index c566dfc..a428a97 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTests.java
@@ -24,6 +24,9 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.content.om.OverlayInfo;
@@ -33,6 +36,8 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.internal.content.om.OverlayConfig;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -45,10 +50,7 @@
 import java.util.Set;
 
 @RunWith(AndroidJUnit4.class)
-public class OverlayManagerServiceImplTests {
-    private OverlayManagerServiceImpl mImpl;
-    private DummyDeviceState mState;
-    private DummyListener mListener;
+public class OverlayManagerServiceImplTests extends OverlayManagerServiceImplTestsBase {
 
     private static final String OVERLAY = "com.dummy.overlay";
     private static final String TARGET = "com.dummy.target";
@@ -61,25 +63,14 @@
     private static final String OVERLAY3 = OVERLAY + "3";
     private static final int USER3 = USER2 + 1;
 
-
-    @Before
-    public void setUp() throws Exception {
-        mState = new DummyDeviceState();
-        mListener = new DummyListener();
-        DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
-        mImpl = new OverlayManagerServiceImpl(pmh,
-                new DummyIdmapManager(mState, pmh),
-                new OverlayManagerSettings(),
-                new String[0],
-                mListener);
-    }
-
     // tests: basics
 
     @Test
     public void testGetOverlayInfo() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER, false);
-        final OverlayInfo oi = mImpl.getOverlayInfo(OVERLAY, USER);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+
+        final OverlayManagerServiceImpl impl = getImpl();
+        final OverlayInfo oi = impl.getOverlayInfo(OVERLAY, USER);
         assertNotNull(oi);
         assertEquals(oi.packageName, OVERLAY);
         assertEquals(oi.targetPackageName, TARGET);
@@ -88,87 +79,91 @@
 
     @Test
     public void testGetOverlayInfosForTarget() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER, false);
-        installOverlayPackage(OVERLAY2, TARGET, USER, false);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+        installOverlayPackage(OVERLAY2, TARGET, USER);
+        installOverlayPackage(OVERLAY3, TARGET, USER2);
 
-        installOverlayPackage(OVERLAY3, TARGET, USER2, false);
-
-        final List<OverlayInfo> ois = mImpl.getOverlayInfosForTarget(TARGET, USER);
+        final OverlayManagerServiceImpl impl = getImpl();
+        final List<OverlayInfo> ois = impl.getOverlayInfosForTarget(TARGET, USER);
         assertEquals(ois.size(), 2);
-        assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
-        assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+        assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY, USER)));
+        assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY2, USER)));
 
-        final List<OverlayInfo> ois2 = mImpl.getOverlayInfosForTarget(TARGET, USER2);
+        final List<OverlayInfo> ois2 = impl.getOverlayInfosForTarget(TARGET, USER2);
         assertEquals(ois2.size(), 1);
-        assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER2)));
+        assertTrue(ois2.contains(impl.getOverlayInfo(OVERLAY3, USER2)));
 
-        final List<OverlayInfo> ois3 = mImpl.getOverlayInfosForTarget(TARGET, USER3);
+        final List<OverlayInfo> ois3 = impl.getOverlayInfosForTarget(TARGET, USER3);
         assertNotNull(ois3);
         assertEquals(ois3.size(), 0);
 
-        final List<OverlayInfo> ois4 = mImpl.getOverlayInfosForTarget("no.such.overlay", USER);
+        final List<OverlayInfo> ois4 = impl.getOverlayInfosForTarget("no.such.overlay", USER);
         assertNotNull(ois4);
         assertEquals(ois4.size(), 0);
     }
 
     @Test
     public void testGetOverlayInfosForUser() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER, false);
-        installOverlayPackage(OVERLAY2, TARGET, USER, false);
-        installOverlayPackage(OVERLAY3, TARGET2, USER, false);
+        installTargetPackage(TARGET, USER);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+        installOverlayPackage(OVERLAY2, TARGET, USER);
+        installOverlayPackage(OVERLAY3, TARGET2, USER);
 
-        final Map<String, List<OverlayInfo>> everything = mImpl.getOverlaysForUser(USER);
+        final OverlayManagerServiceImpl impl = getImpl();
+        final Map<String, List<OverlayInfo>> everything = impl.getOverlaysForUser(USER);
         assertEquals(everything.size(), 2);
 
         final List<OverlayInfo> ois = everything.get(TARGET);
         assertNotNull(ois);
         assertEquals(ois.size(), 2);
-        assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY, USER)));
-        assertTrue(ois.contains(mImpl.getOverlayInfo(OVERLAY2, USER)));
+        assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY, USER)));
+        assertTrue(ois.contains(impl.getOverlayInfo(OVERLAY2, USER)));
 
         final List<OverlayInfo> ois2 = everything.get(TARGET2);
         assertNotNull(ois2);
         assertEquals(ois2.size(), 1);
-        assertTrue(ois2.contains(mImpl.getOverlayInfo(OVERLAY3, USER)));
+        assertTrue(ois2.contains(impl.getOverlayInfo(OVERLAY3, USER)));
 
-        final Map<String, List<OverlayInfo>> everything2 = mImpl.getOverlaysForUser(USER2);
+        final Map<String, List<OverlayInfo>> everything2 = impl.getOverlaysForUser(USER2);
         assertNotNull(everything2);
         assertEquals(everything2.size(), 0);
     }
 
     @Test
     public void testPriority() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER, false);
-        installOverlayPackage(OVERLAY2, TARGET, USER, false);
-        installOverlayPackage(OVERLAY3, TARGET, USER, false);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+        installOverlayPackage(OVERLAY2, TARGET, USER);
+        installOverlayPackage(OVERLAY3, TARGET, USER);
 
-        final OverlayInfo o1 = mImpl.getOverlayInfo(OVERLAY, USER);
-        final OverlayInfo o2 = mImpl.getOverlayInfo(OVERLAY2, USER);
-        final OverlayInfo o3 = mImpl.getOverlayInfo(OVERLAY3, USER);
+        final OverlayManagerServiceImpl impl = getImpl();
+        final OverlayInfo o1 = impl.getOverlayInfo(OVERLAY, USER);
+        final OverlayInfo o2 = impl.getOverlayInfo(OVERLAY2, USER);
+        final OverlayInfo o3 = impl.getOverlayInfo(OVERLAY3, USER);
 
         assertOverlayInfoList(TARGET, USER, o1, o2, o3);
 
-        assertTrue(mImpl.setLowestPriority(OVERLAY3, USER));
+        assertTrue(impl.setLowestPriority(OVERLAY3, USER));
         assertOverlayInfoList(TARGET, USER, o3, o1, o2);
 
-        assertTrue(mImpl.setHighestPriority(OVERLAY3, USER));
+        assertTrue(impl.setHighestPriority(OVERLAY3, USER));
         assertOverlayInfoList(TARGET, USER, o1, o2, o3);
 
-        assertTrue(mImpl.setPriority(OVERLAY, OVERLAY2, USER));
+        assertTrue(impl.setPriority(OVERLAY, OVERLAY2, USER));
         assertOverlayInfoList(TARGET, USER, o2, o1, o3);
     }
 
     @Test
     public void testOverlayInfoStateTransitions() throws Exception {
-        assertNull(mImpl.getOverlayInfo(OVERLAY, USER));
+        final OverlayManagerServiceImpl impl = getImpl();
+        assertNull(impl.getOverlayInfo(OVERLAY, USER));
 
-        installOverlayPackage(OVERLAY, TARGET, USER, true);
+        installOverlayPackage(OVERLAY, TARGET, USER);
         assertState(STATE_MISSING_TARGET, OVERLAY, USER);
 
         installTargetPackage(TARGET, USER);
         assertState(STATE_DISABLED, OVERLAY, USER);
 
-        mImpl.setEnabled(OVERLAY, true, USER);
+        impl.setEnabled(OVERLAY, true, USER);
         assertState(STATE_ENABLED, OVERLAY, USER);
 
         // target upgrades do not change the state of the overlay
@@ -186,319 +181,48 @@
     }
 
     @Test
-    public void testUpdateOverlaysForUser() throws Exception {
-        installTargetPackage(TARGET, USER);
-        installTargetPackage("some.other.target", USER);
-        installOverlayPackage(OVERLAY, TARGET, USER, true);
-
-        // do nothing, expect no change
-        List<String> a = mImpl.updateOverlaysForUser(USER);
-        assertEquals(1, a.size());
-        assertTrue(a.contains(TARGET));
-
-        // upgrade overlay, keep target
-        upgradeOverlayPackage(OVERLAY, TARGET, USER, true);
-        List<String> b = mImpl.updateOverlaysForUser(USER);
-        assertEquals(1, b.size());
-        assertTrue(b.contains(TARGET));
-
-        // do nothing, expect no change
-        List<String> c = mImpl.updateOverlaysForUser(USER);
-        assertEquals(1, c.size());
-        assertTrue(c.contains(TARGET));
-
-        // upgrade overlay, switch to new target
-        upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
-        List<String> d = mImpl.updateOverlaysForUser(USER);
-        assertEquals(2, d.size());
-        assertTrue(d.containsAll(Arrays.asList(TARGET, "some.other.target")));
-
-        // do nothing, expect no change
-        List<String> e = mImpl.updateOverlaysForUser(USER);
-        assertEquals(1, e.size());
-        assertTrue(e.contains("some.other.target"));
-    }
-
-    @Test
     public void testOnOverlayPackageUpgraded() throws Exception {
+        final OverlayManagerServiceImpl impl = getImpl();
+        final DummyListener listener = getListener();
         installTargetPackage(TARGET, USER);
-        installOverlayPackage(OVERLAY, TARGET, USER, true);
-        mImpl.onOverlayPackageReplacing(OVERLAY, USER);
-        mListener.count = 0;
-        mImpl.onOverlayPackageReplaced(OVERLAY, USER);
-        assertEquals(1, mListener.count);
+        installOverlayPackage(OVERLAY, TARGET, USER);
+        impl.onOverlayPackageReplacing(OVERLAY, USER);
+        listener.count = 0;
+        impl.onOverlayPackageReplaced(OVERLAY, USER);
+        assertEquals(1, listener.count);
 
         // upgrade to a version where the overlay has changed its target
-        upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
-        mImpl.onOverlayPackageReplacing(OVERLAY, USER);
-        mListener.count = 0;
-        mImpl.onOverlayPackageReplaced(OVERLAY, USER);
+        beginUpgradeOverlayPackage(OVERLAY, USER);
+        listener.count = 0;
+        endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
         // expect once for the old target package, once for the new target package
-        assertEquals(2, mListener.count);
+        assertEquals(2, listener.count);
 
-        upgradeOverlayPackage(OVERLAY, "some.other.target", USER, true);
-        mImpl.onOverlayPackageReplacing(OVERLAY, USER);
-        mListener.count = 0;
-        mImpl.onOverlayPackageReplaced(OVERLAY, USER);
-        assertEquals(1, mListener.count);
+        beginUpgradeOverlayPackage(OVERLAY, USER);
+        listener.count = 0;
+        endUpgradeOverlayPackage(OVERLAY, "some.other.target", USER);
+        assertEquals(1, listener.count);
     }
 
     // tests: listener interface
 
     @Test
     public void testListener() throws Exception {
-        installOverlayPackage(OVERLAY, TARGET, USER, true);
-        assertEquals(1, mListener.count);
-        mListener.count = 0;
+        final OverlayManagerServiceImpl impl = getImpl();
+        final DummyListener listener = getListener();
+        installOverlayPackage(OVERLAY, TARGET, USER);
+        assertEquals(1, listener.count);
+        listener.count = 0;
 
         installTargetPackage(TARGET, USER);
-        assertEquals(1, mListener.count);
-        mListener.count = 0;
+        assertEquals(1, listener.count);
+        listener.count = 0;
 
-        mImpl.setEnabled(OVERLAY, true, USER);
-        assertEquals(1, mListener.count);
-        mListener.count = 0;
+        impl.setEnabled(OVERLAY, true, USER);
+        assertEquals(1, listener.count);
+        listener.count = 0;
 
-        mImpl.setEnabled(OVERLAY, true, USER);
-        assertEquals(0, mListener.count);
-    }
-
-    // helper methods
-
-    private void assertState(int expected, final String overlayPackageName, int userId) {
-        int actual = mImpl.getOverlayInfo(OVERLAY, USER).state;
-        String msg = String.format("expected %s but was %s:",
-                OverlayInfo.stateToString(expected), OverlayInfo.stateToString(actual));
-        assertEquals(msg, expected, actual);
-    }
-
-    private void assertOverlayInfoList(final String targetPackageName, int userId,
-            OverlayInfo... overlayInfos) {
-        final List<OverlayInfo> expected =
-                mImpl.getOverlayInfosForTarget(targetPackageName, userId);
-        final List<OverlayInfo> actual = Arrays.asList(overlayInfos);
-        assertEquals(expected, actual);
-    }
-
-    private void installTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) != null) {
-            throw new IllegalStateException("package already installed");
-        }
-        mState.add(packageName, null, userId, false);
-        mImpl.onTargetPackageAdded(packageName, userId);
-    }
-
-    private void beginUpgradeTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
-        }
-        mState.add(packageName, null, userId, false);
-        mImpl.onTargetPackageReplacing(packageName, userId);
-    }
-
-    private void endUpgradeTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
-        }
-        mState.add(packageName, null, userId, false);
-        mImpl.onTargetPackageReplaced(packageName, userId);
-    }
-
-    private void uninstallTargetPackage(String packageName, int userId) {
-        if (mState.select(packageName, userId) == null) {
-            throw new IllegalStateException("package not installed");
-        }
-        mState.remove(packageName, userId);
-        mImpl.onTargetPackageRemoved(packageName, userId);
-    }
-
-    private void installOverlayPackage(String packageName, String targetPackageName, int userId,
-            boolean canCreateIdmap) {
-        if (mState.select(packageName, userId) != null) {
-            throw new IllegalStateException("package already installed");
-        }
-        mState.add(packageName, targetPackageName, userId, canCreateIdmap);
-        mImpl.onOverlayPackageAdded(packageName, userId);
-    }
-
-    private void upgradeOverlayPackage(String packageName, String targetPackageName, int userId,
-            boolean canCreateIdmap) {
-        DummyDeviceState.Package pkg = mState.select(packageName, userId);
-        if (pkg == null) {
-            throw new IllegalStateException("package not installed, cannot upgrade");
-        }
-        pkg.targetPackageName = targetPackageName;
-        pkg.canCreateIdmap = canCreateIdmap;
-    }
-
-    private void uninstallOverlayPackage(String packageName, int userId) {
-        // implement this when adding support for downloadable overlays
-        throw new IllegalArgumentException("not implemented");
-    }
-
-    private static final class DummyDeviceState {
-        private List<Package> mPackages = new ArrayList<>();
-
-        public void add(String packageName, String targetPackageName, int userId,
-                boolean canCreateIdmap) {
-            remove(packageName, userId);
-            Package pkg = new Package();
-            pkg.packageName = packageName;
-            pkg.targetPackageName = targetPackageName;
-            pkg.userId = userId;
-            pkg.canCreateIdmap = canCreateIdmap;
-            mPackages.add(pkg);
-        }
-
-        public void remove(String packageName, int userId) {
-            final Iterator<Package> iter = mPackages.iterator();
-            while (iter.hasNext()) {
-                final Package pkg = iter.next();
-                if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
-                    iter.remove();
-                    return;
-                }
-            }
-        }
-
-        public List<Package> select(int userId) {
-            List<Package> out = new ArrayList<>();
-            final int packageCount = mPackages.size();
-            for (int i = 0; i < packageCount; i++) {
-                final Package pkg = mPackages.get(i);
-                if (pkg.userId == userId) {
-                    out.add(pkg);
-                }
-            }
-            return out;
-        }
-
-        public Package select(String packageName, int userId) {
-            final int packageCount = mPackages.size();
-            for (int i = 0; i < packageCount; i++) {
-                final Package pkg = mPackages.get(i);
-                if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
-                    return pkg;
-                }
-            }
-            return null;
-        }
-
-        private static final class Package {
-            public String packageName;
-            public int userId;
-            public String targetPackageName;
-            public boolean canCreateIdmap;
-        }
-    }
-
-    private static final class DummyPackageManagerHelper implements
-            OverlayManagerServiceImpl.PackageManagerHelper {
-        private final DummyDeviceState mState;
-
-        DummyPackageManagerHelper(DummyDeviceState state) {
-            mState = state;
-        }
-
-        @Override
-        public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
-            final DummyDeviceState.Package pkg = mState.select(packageName, userId);
-            if (pkg == null) {
-                return null;
-            }
-            ApplicationInfo ai = new ApplicationInfo();
-            ai.sourceDir = String.format("%s/%s/base.apk",
-                    pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
-                    pkg.packageName);
-            PackageInfo pi = new PackageInfo();
-            pi.applicationInfo = ai;
-            pi.packageName = pkg.packageName;
-            pi.overlayTarget = pkg.targetPackageName;
-            pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
-            return pi;
-        }
-
-        @Override
-        public boolean signaturesMatching(@NonNull String packageName1,
-                @NonNull String packageName2, int userId) {
-            return false;
-        }
-
-        @Override
-        public List<PackageInfo> getOverlayPackages(int userId) {
-            List<PackageInfo> out = new ArrayList<>();
-            final List<DummyDeviceState.Package> packages = mState.select(userId);
-            final int packageCount = packages.size();
-            for (int i = 0; i < packageCount; i++) {
-                final DummyDeviceState.Package pkg = packages.get(i);
-                if (pkg.targetPackageName != null) {
-                    out.add(getPackageInfo(pkg.packageName, pkg.userId));
-                }
-            }
-            return out;
-        }
-    }
-
-    private static class DummyIdmapManager extends IdmapManager {
-        private final DummyDeviceState mState;
-        private Set<String> mIdmapFiles = new ArraySet<>();
-
-        DummyIdmapManager(DummyDeviceState state, DummyPackageManagerHelper packageManagerHelper) {
-            super(packageManagerHelper);
-            mState = state;
-        }
-
-        @Override
-        boolean createIdmap(@NonNull final PackageInfo targetPackage,
-                @NonNull final PackageInfo overlayPackage, int userId) {
-            final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
-            if (t == null) {
-                return false;
-            }
-            final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
-            if (o == null) {
-                return false;
-            }
-            if (!o.canCreateIdmap) {
-                return false;
-            }
-            final String key = createKey(overlayPackage.packageName, userId);
-            mIdmapFiles.add(key);
-            return true;
-        }
-
-        @Override
-        boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
-            final String key = createKey(oi.packageName, oi.userId);
-            if (!mIdmapFiles.contains(key)) {
-                return false;
-            }
-            mIdmapFiles.remove(key);
-            return true;
-        }
-
-        @Override
-        boolean idmapExists(@NonNull final OverlayInfo oi) {
-            final String key = createKey(oi.packageName, oi.userId);
-            return mIdmapFiles.contains(key);
-        }
-
-        @Override
-        boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
-            final String key = createKey(overlayPackage.packageName, userId);
-            return mIdmapFiles.contains(key);
-        }
-
-        private String createKey(@NonNull final String packageName, final int userId) {
-            return String.format("%s:%d", packageName, userId);
-        }
-    }
-
-    private static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
-        public int count;
-
-        public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
-            count++;
-        }
+        impl.setEnabled(OVERLAY, true, USER);
+        assertEquals(0, listener.count);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
new file mode 100644
index 0000000..a753aac
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerServiceImplTestsBase.java
@@ -0,0 +1,385 @@
+/*
+ * 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.om;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
+import android.content.om.OverlayInfo;
+import android.content.om.OverlayInfo.State;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.util.ArraySet;
+
+import com.android.internal.content.om.OverlayConfig;
+
+import org.junit.Before;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/** Base class for creating {@link OverlayManagerServiceImplTests} tests. */
+class OverlayManagerServiceImplTestsBase {
+    private OverlayManagerServiceImpl mImpl;
+    private DummyDeviceState mState;
+    private DummyListener mListener;
+
+    @Before
+    public void setUp() {
+        mState = new DummyDeviceState();
+        mListener = new DummyListener();
+        final DummyPackageManagerHelper pmh = new DummyPackageManagerHelper(mState);
+
+        mImpl = new OverlayManagerServiceImpl(pmh,
+                new DummyIdmapManager(mState, pmh),
+                new OverlayManagerSettings(),
+                mState.mOverlayConfig,
+                new String[0],
+                mListener);
+    }
+
+    public OverlayManagerServiceImpl getImpl() {
+        return mImpl;
+    }
+
+    public DummyListener getListener() {
+        return mListener;
+    }
+
+    void assertState(@State int expected, final String overlayPackageName, int userId) {
+        final OverlayInfo info = mImpl.getOverlayInfo(overlayPackageName, userId);
+        if (info == null) {
+            throw new IllegalStateException("package not installed");
+        }
+
+        final String msg = String.format("expected %s but was %s:",
+                OverlayInfo.stateToString(expected), OverlayInfo.stateToString(info.state));
+        assertEquals(msg, expected, info.state);
+    }
+
+    void assertOverlayInfoList(final String targetPackageName, int userId,
+            OverlayInfo... overlayInfos) {
+        final List<OverlayInfo> expected =
+                mImpl.getOverlayInfosForTarget(targetPackageName, userId);
+        final List<OverlayInfo> actual = Arrays.asList(overlayInfos);
+        assertEquals(expected, actual);
+    }
+
+    /**
+     * Creates an overlay configured through {@link OverlayConfig}.
+     *
+     * @throws IllegalStateException if the package is already installed
+     */
+    void addOverlayPackage(String packageName, String targetPackageName, int userId,
+            boolean mutable, boolean enabled, int priority) {
+        mState.addOverlay(packageName, targetPackageName, userId, mutable, enabled, priority);
+    }
+
+    /**
+     * Adds the target package to the device.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void installTargetPackage(String packageName, int userId) {
+        if (mState.select(packageName, userId) != null) {
+            throw new IllegalStateException("package already installed");
+        }
+        mState.addTarget(packageName, userId);
+        mImpl.onTargetPackageAdded(packageName, userId);
+    }
+
+    /**
+     * Begins upgrading the target package.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
+     * {@link android.content.Intent#EXTRA_REPLACING} extra.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void beginUpgradeTargetPackage(String packageName, int userId) {
+        if (mState.select(packageName, userId) == null) {
+            throw new IllegalStateException("package not installed");
+        }
+        mImpl.onTargetPackageReplacing(packageName, userId);
+    }
+
+    /**
+     * Ends upgrading the target package.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
+     * {@link android.content.Intent#EXTRA_REPLACING} extra.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void endUpgradeTargetPackage(String packageName, int userId) {
+        if (mState.select(packageName, userId) == null) {
+            throw new IllegalStateException("package not installed");
+        }
+        mState.addTarget(packageName, userId);
+        mImpl.onTargetPackageReplaced(packageName, userId);
+    }
+
+    /**
+     * Removes the target package from the device.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void uninstallTargetPackage(String packageName, int userId) {
+        if (mState.select(packageName, userId) == null) {
+            throw new IllegalStateException("package not installed");
+        }
+        mState.remove(packageName, userId);
+        mImpl.onTargetPackageRemoved(packageName, userId);
+    }
+
+    /**
+     * Adds the overlay package to the device.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast.
+     *
+     * @throws IllegalStateException if the package is already installed
+     */
+    void installOverlayPackage(String packageName, String targetPackageName, int userId) {
+        if (mState.select(packageName, userId) != null) {
+            throw new IllegalStateException("package already installed");
+        }
+        mState.addOverlay(packageName, targetPackageName, userId);
+        mImpl.onOverlayPackageAdded(packageName, userId);
+    }
+
+    /**
+     * Begins upgrading the overlay package.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_REMOVED} broadcast with the
+     * {@link android.content.Intent#EXTRA_REPLACING} extra.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void beginUpgradeOverlayPackage(String packageName, int userId) {
+        if (mState.select(packageName, userId) == null) {
+            throw new IllegalStateException("package not installed, cannot upgrade");
+        }
+
+        mImpl.onOverlayPackageReplacing(packageName, userId);
+    }
+
+    /**
+     * Ends upgrading the overlay package, potentially changing its target package.
+     *
+     * This corresponds to when the OMS receives the
+     * {@link android.content.Intent#ACTION_PACKAGE_ADDED} broadcast with the
+     * {@link android.content.Intent#EXTRA_REPLACING} extra.
+     *
+     * @throws IllegalStateException if the package is not currently installed
+     */
+    void endUpgradeOverlayPackage(String packageName, String targetPackageName, int userId) {
+        if (mState.select(packageName, userId) == null) {
+            throw new IllegalStateException("package not installed, cannot upgrade");
+        }
+
+        mState.addOverlay(packageName, targetPackageName, userId);
+        mImpl.onOverlayPackageReplaced(packageName, userId);
+    }
+
+    private static final class DummyDeviceState {
+        private List<Package> mPackages = new ArrayList<>();
+        private OverlayConfig mOverlayConfig = mock(OverlayConfig.class);
+
+        /** Adds a non-overlay to the device. */
+        public void addTarget(String packageName, int userId) {
+            remove(packageName, userId);
+            mPackages.add(new Package(packageName, userId, null, false, false, 0));
+        }
+
+        /** Adds an overlay to the device. */
+        public void addOverlay(String packageName, String targetPackageName, int userId) {
+            addOverlay(packageName, targetPackageName, userId, true, false, OverlayConfig.DEFAULT_PRIORITY);
+        }
+
+        /** Adds a configured overlay to the device. */
+        public void addOverlay(String packageName, String targetPackageName, int userId,
+                boolean mutable, boolean enabled, int priority) {
+            remove(packageName, userId);
+            mPackages.add(new Package(packageName, userId, targetPackageName, mutable, enabled,
+                    priority));
+            when(mOverlayConfig.getPriority(packageName)).thenReturn(priority);
+            when(mOverlayConfig.isEnabled(packageName)).thenReturn(enabled);
+            when(mOverlayConfig.isMutable(packageName)).thenReturn(mutable);
+        }
+
+        /** Remove a package from the device. */
+        public void remove(String packageName, int userId) {
+            final Iterator<Package> iter = mPackages.iterator();
+            while (iter.hasNext()) {
+                final Package pkg = iter.next();
+                if (pkg.packageName.equals(packageName) && pkg.userId == userId) {
+                    iter.remove();
+                    return;
+                }
+            }
+        }
+
+        /** Retrieves all packages on device for a particular user. */
+        public List<Package> select(int userId) {
+            return mPackages.stream().filter(p -> p.userId == userId).collect(Collectors.toList());
+        }
+
+        /** Retrieves the package with the specified package name for a particular user. */
+        public Package select(String packageName, int userId) {
+            return mPackages.stream().filter(
+                    p -> p.packageName.equals(packageName) && p.userId == userId)
+                    .findFirst().orElse(null);
+        }
+
+        private static final class Package {
+            public final String packageName;
+            public final int userId;
+            public final String targetPackageName;
+            public final boolean mutable;
+            public final boolean enabled;
+            public final int priority;
+
+            private Package(String packageName, int userId, String targetPackageName,
+                    boolean mutable, boolean enabled, int priority) {
+                this.packageName = packageName;
+                this.userId = userId;
+                this.targetPackageName = targetPackageName;
+                this.mutable = mutable;
+                this.enabled = enabled;
+                this.priority = priority;
+            }
+        }
+    }
+
+    static final class DummyPackageManagerHelper implements
+            OverlayManagerServiceImpl.PackageManagerHelper {
+        private final DummyDeviceState mState;
+
+        private DummyPackageManagerHelper(DummyDeviceState state) {
+            mState = state;
+        }
+
+        @Override
+        public PackageInfo getPackageInfo(@NonNull String packageName, int userId) {
+            final DummyDeviceState.Package pkg = mState.select(packageName, userId);
+            if (pkg == null) {
+                return null;
+            }
+            final ApplicationInfo ai = new ApplicationInfo();
+            ai.sourceDir = String.format("%s/%s/base.apk",
+                    pkg.targetPackageName == null ? "/system/app/" : "/vendor/overlay/",
+                    pkg.packageName);
+            PackageInfo pi = new PackageInfo();
+            pi.applicationInfo = ai;
+            pi.packageName = pkg.packageName;
+            pi.overlayTarget = pkg.targetPackageName;
+            pi.overlayCategory = "dummy-category-" + pkg.targetPackageName;
+            return pi;
+        }
+
+        @Override
+        public boolean signaturesMatching(@NonNull String packageName1,
+                @NonNull String packageName2, int userId) {
+            return false;
+        }
+
+        @Override
+        public List<PackageInfo> getOverlayPackages(int userId) {
+            return mState.select(userId).stream()
+                    .filter(p -> p.targetPackageName != null)
+                    .map(p -> getPackageInfo(p.packageName, p.userId))
+                    .collect(Collectors.toList());
+        }
+    }
+
+    static class DummyIdmapManager extends IdmapManager {
+        private final DummyDeviceState mState;
+        private Set<String> mIdmapFiles = new ArraySet<>();
+
+        private DummyIdmapManager(DummyDeviceState state,
+                DummyPackageManagerHelper packageManagerHelper) {
+            super(packageManagerHelper);
+            mState = state;
+        }
+
+        @Override
+        boolean createIdmap(@NonNull final PackageInfo targetPackage,
+                @NonNull final PackageInfo overlayPackage, int userId) {
+            final DummyDeviceState.Package t = mState.select(targetPackage.packageName, userId);
+            if (t == null) {
+                return false;
+            }
+            final DummyDeviceState.Package o = mState.select(overlayPackage.packageName, userId);
+            if (o == null) {
+                return false;
+            }
+            final String key = createKey(overlayPackage.packageName, userId);
+            mIdmapFiles.add(key);
+            return true;
+        }
+
+        @Override
+        boolean removeIdmap(@NonNull final OverlayInfo oi, final int userId) {
+            final String key = createKey(oi.packageName, oi.userId);
+            if (!mIdmapFiles.contains(key)) {
+                return false;
+            }
+            mIdmapFiles.remove(key);
+            return true;
+        }
+
+        @Override
+        boolean idmapExists(@NonNull final OverlayInfo oi) {
+            final String key = createKey(oi.packageName, oi.userId);
+            return mIdmapFiles.contains(key);
+        }
+
+        @Override
+        boolean idmapExists(@NonNull final PackageInfo overlayPackage, final int userId) {
+            final String key = createKey(overlayPackage.packageName, userId);
+            return mIdmapFiles.contains(key);
+        }
+
+        private String createKey(@NonNull final String packageName, final int userId) {
+            return String.format("%s:%d", packageName, userId);
+        }
+    }
+
+    static class DummyListener implements OverlayManagerServiceImpl.OverlayChangeListener {
+        public int count;
+
+        public void onOverlaysChanged(@NonNull String targetPackage, int userId) {
+            count++;
+        }
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
index 8ff8b6e..146f60a 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayManagerSettingsTests.java
@@ -58,7 +58,7 @@
             STATE_DISABLED,
             0,
             0,
-            false);
+            true);
 
     private static final OverlayInfo OVERLAY_B0 = new OverlayInfo(
             "com.dummy.overlay_b",
@@ -69,7 +69,7 @@
             STATE_DISABLED,
             0,
             0,
-            false);
+            true);
 
     private static final OverlayInfo OVERLAY_C0 = new OverlayInfo(
             "com.dummy.overlay_c",
@@ -80,7 +80,7 @@
             STATE_DISABLED,
             0,
             0,
-            false);
+            true);
 
     private static final OverlayInfo OVERLAY_A1 = new OverlayInfo(
             "com.dummy.overlay_a",
@@ -91,7 +91,7 @@
             STATE_DISABLED,
             1,
             0,
-            false);
+            true);
 
     private static final OverlayInfo OVERLAY_B1 = new OverlayInfo(
             "com.dummy.overlay_b",
@@ -102,7 +102,7 @@
             STATE_DISABLED,
             1,
             0,
-            false);
+            true);
 
     @Before
     public void setUp() throws Exception {
@@ -238,7 +238,7 @@
                 STATE_DISABLED,
                 0,
                 0,
-                false);
+                true);
         insert(otherTarget);
         changed = mSettings.setPriority(OVERLAY_A0.packageName, otherTarget.packageName,
                 OVERLAY_A0.userId);
@@ -435,7 +435,7 @@
 
     private void insert(OverlayInfo oi) throws Exception {
         mSettings.init(oi.packageName, oi.userId, oi.targetPackageName, null, oi.baseCodePath,
-                false, 0, oi.category);
+                true, false,0, oi.category);
         mSettings.setState(oi.packageName, oi.userId, oi.state);
         mSettings.setEnabled(oi.packageName, oi.userId, false);
     }
diff --git a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
index ef12948..063cd5da 100644
--- a/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
+++ b/services/tests/servicestests/src/com/android/server/om/OverlayReferenceMapperTests.kt
@@ -16,8 +16,8 @@
 
 package com.android.server.om
 
-import android.content.pm.parsing.AndroidPackage
 import android.net.Uri
+import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
@@ -196,11 +196,13 @@
         whenever(packageName) { "$TARGET_PACKAGE_NAME$increment" }
         whenever(overlayables) { mapOf("overlayableName$increment" to ACTOR_NAME) }
         whenever(toString()) { "Package{$packageName}" }
+        whenever(isOverlay) { false }
     }
 
     private fun mockOverlay(increment: Int = 0) = mockThrowOnUnmocked<AndroidPackage> {
         whenever(packageName) { "$OVERLAY_PACKAGE_NAME$increment" }
         whenever(overlayables) { emptyMap<String, String>() }
         whenever(toString()) { "Package{$packageName}" }
+        whenever(isOverlay) { true }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
index b614a4f..443718d 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/AggregateEventHistoryImplTest.java
@@ -21,11 +21,16 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Context;
+
+import androidx.test.InstrumentationRegistry;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.io.File;
 import java.util.List;
 
 @RunWith(JUnit4.class)
@@ -60,11 +65,16 @@
 
         EventHistoryImpl.Injector injector = new EventHistoryImplInjector();
 
-        mEventHistory1 = new EventHistoryImpl(injector);
+        Context ctx = InstrumentationRegistry.getContext();
+        File testDir = new File(ctx.getCacheDir(), "testdir");
+        MockScheduledExecutorService mockScheduledExecutorService =
+                new MockScheduledExecutorService();
+
+        mEventHistory1 = new EventHistoryImpl(injector, testDir, mockScheduledExecutorService);
         mEventHistory1.addEvent(E1);
         mEventHistory1.addEvent(E2);
 
-        mEventHistory2 = new EventHistoryImpl(injector);
+        mEventHistory2 = new EventHistoryImpl(injector, testDir, mockScheduledExecutorService);
         mEventHistory2.addEvent(E3);
         mEventHistory2.addEvent(E4);
     }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
index 03b5e38..d138700 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/ConversationStoreTest.java
@@ -21,7 +21,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 
-import android.annotation.Nullable;
 import android.content.Context;
 import android.content.LocusId;
 import android.content.pm.ShortcutInfo;
@@ -63,7 +62,6 @@
     private static final String PHONE_NUMBER_3 = "+9234567890";
 
     private MockScheduledExecutorService mMockScheduledExecutorService;
-    private TestContactQueryHelper mTestContactQueryHelper;
     private ConversationStore mConversationStore;
     private File mFile;
 
@@ -71,7 +69,6 @@
     public void setUp() {
         Context ctx = InstrumentationRegistry.getContext();
         mFile = new File(ctx.getCacheDir(), "testdir");
-        mTestContactQueryHelper = new TestContactQueryHelper(ctx);
         resetConversationStore();
     }
 
@@ -207,9 +204,6 @@
         mConversationStore.deleteConversation(SHORTCUT_ID_3);
         mMockScheduledExecutorService.fastForwardTime(3L * DateUtils.MINUTE_IN_MILLIS);
 
-        mTestContactQueryHelper.setQueryResult(true, true);
-        mTestContactQueryHelper.setPhoneNumberResult(PHONE_NUMBER, PHONE_NUMBER_2);
-
         resetConversationStore();
         ConversationInfo out1 = mConversationStore.getConversation(SHORTCUT_ID);
         ConversationInfo out2 = mConversationStore.getConversation(SHORTCUT_ID_2);
@@ -240,9 +234,6 @@
         mConversationStore.addOrUpdate(in2);
         mMockScheduledExecutorService.fastForwardTime(DateUtils.MINUTE_IN_MILLIS);
 
-        mTestContactQueryHelper.setQueryResult(true);
-        mTestContactQueryHelper.setPhoneNumberResult(PHONE_NUMBER);
-
         resetConversationStore();
         ConversationInfo out1 = mConversationStore.getConversation(SHORTCUT_ID);
         ConversationInfo out2 = mConversationStore.getConversation(SHORTCUT_ID_2);
@@ -256,10 +247,6 @@
         mConversationStore.addOrUpdate(in3);
         mMockScheduledExecutorService.fastForwardTime(3L * DateUtils.MINUTE_IN_MILLIS);
 
-        mTestContactQueryHelper.reset();
-        mTestContactQueryHelper.setQueryResult(true, true, true);
-        mTestContactQueryHelper.setPhoneNumberResult(PHONE_NUMBER, PHONE_NUMBER_2, PHONE_NUMBER_3);
-
         resetConversationStore();
         out1 = mConversationStore.getConversation(SHORTCUT_ID);
         out2 = mConversationStore.getConversation(SHORTCUT_ID_2);
@@ -290,9 +277,6 @@
         // loadConversationFromDisk gets called each time we call #resetConversationStore().
         assertEquals(2, mMockScheduledExecutorService.getExecutes().size());
 
-        mTestContactQueryHelper.setQueryResult(true, true);
-        mTestContactQueryHelper.setPhoneNumberResult(PHONE_NUMBER, PHONE_NUMBER_2);
-
         resetConversationStore();
         ConversationInfo out1 = mConversationStore.getConversation(SHORTCUT_ID);
         ConversationInfo out2 = mConversationStore.getConversation(SHORTCUT_ID_2);
@@ -303,8 +287,7 @@
     private void resetConversationStore() {
         mFile.mkdir();
         mMockScheduledExecutorService = new MockScheduledExecutorService();
-        mConversationStore = new ConversationStore(mFile, mMockScheduledExecutorService,
-                mTestContactQueryHelper);
+        mConversationStore = new ConversationStore(mFile, mMockScheduledExecutorService);
         mConversationStore.loadConversationsFromDisk();
     }
 
@@ -326,54 +309,4 @@
                 .setBubbled(true)
                 .build();
     }
-
-    private static class TestContactQueryHelper extends ContactsQueryHelper {
-
-        private int mQueryCalls;
-        private boolean[] mQueryResult;
-
-        private int mPhoneNumberCalls;
-        private String[] mPhoneNumberResult;
-
-        TestContactQueryHelper(Context context) {
-            super(context);
-
-            mQueryCalls = 0;
-            mPhoneNumberCalls = 0;
-        }
-
-        private void setQueryResult(boolean... values) {
-            mQueryResult = values;
-        }
-
-        private void setPhoneNumberResult(String... values) {
-            mPhoneNumberResult = values;
-        }
-
-        private void reset() {
-            mQueryCalls = 0;
-            mQueryResult = null;
-            mPhoneNumberCalls = 0;
-            mPhoneNumberResult = null;
-        }
-
-        @Override
-        boolean query(String contactUri) {
-            if (mQueryResult != null && mQueryCalls < mQueryResult.length) {
-                return mQueryResult[mQueryCalls++];
-            }
-            mQueryCalls++;
-            return false;
-        }
-
-        @Override
-        @Nullable
-        String getPhoneNumber() {
-            if (mPhoneNumberResult != null && mPhoneNumberCalls < mPhoneNumberResult.length) {
-                return mPhoneNumberResult[mPhoneNumberCalls++];
-            }
-            mPhoneNumberCalls++;
-            return null;
-        }
-    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 3ecd319..f0b7d20 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
@@ -52,12 +52,12 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.LauncherApps.ShortcutChangeCallback;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.ShortcutInfo;
-import android.content.pm.ShortcutManager;
 import android.content.pm.ShortcutServiceInternal;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
 import android.database.ContentObserver;
 import android.net.Uri;
 import android.os.CancellationSignal;
@@ -74,12 +74,16 @@
 import com.android.internal.app.ChooserActivity;
 import com.android.internal.content.PackageMonitor;
 import com.android.server.LocalServices;
+import com.android.server.notification.NotificationManagerInternal;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
 
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
@@ -87,6 +91,8 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ScheduledFuture;
 import java.util.concurrent.TimeUnit;
@@ -100,7 +106,9 @@
     private static final int USER_ID_PRIMARY_MANAGED = 10;
     private static final int USER_ID_SECONDARY = 11;
     private static final String TEST_PKG_NAME = "pkg";
+    private static final String TEST_CLASS_NAME = "class";
     private static final String TEST_SHORTCUT_ID = "sc";
+    private static final int TEST_PKG_UID = 35;
     private static final String CONTACT_URI = "content://com.android.contacts/contacts/lookup/123";
     private static final String PHONE_NUMBER = "+1234567890";
     private static final String NOTIFICATION_CHANNEL_ID = "test : sc";
@@ -110,8 +118,9 @@
     @Mock private ShortcutServiceInternal mShortcutServiceInternal;
     @Mock private UsageStatsManagerInternal mUsageStatsManagerInternal;
     @Mock private PackageManagerInternal mPackageManagerInternal;
-    @Mock private ShortcutManager mShortcutManager;
+    @Mock private NotificationManagerInternal mNotificationManagerInternal;
     @Mock private UserManager mUserManager;
+    @Mock private PackageManager mPackageManager;
     @Mock private TelephonyManager mTelephonyManager;
     @Mock private TelecomManager mTelecomManager;
     @Mock private ContentResolver mContentResolver;
@@ -121,14 +130,16 @@
     @Mock private StatusBarNotification mStatusBarNotification;
     @Mock private Notification mNotification;
 
+    @Captor private ArgumentCaptor<ShortcutChangeCallback> mShortcutChangeCallbackCaptor;
+
     private NotificationChannel mNotificationChannel;
     private DataManager mDataManager;
-    private int mCallingUserId;
     private CancellationSignal mCancellationSignal;
+    private ShortcutChangeCallback mShortcutChangeCallback;
     private TestInjector mInjector;
 
     @Before
-    public void setUp() {
+    public void setUp() throws PackageManager.NameNotFoundException {
         MockitoAnnotations.initMocks(this);
 
         addLocalServiceMock(ShortcutServiceInternal.class, mShortcutServiceInternal);
@@ -144,15 +155,16 @@
             return null;
         }).when(mPackageManagerInternal).forEachInstalledPackage(any(Consumer.class), anyInt());
 
+        addLocalServiceMock(NotificationManagerInternal.class, mNotificationManagerInternal);
+
+        when(mContext.getContentResolver()).thenReturn(mContentResolver);
         when(mContext.getMainLooper()).thenReturn(Looper.getMainLooper());
+        when(mContext.getPackageName()).thenReturn("android");
+        when(mContext.getPackageManager()).thenReturn(mPackageManager);
 
         Context originalContext = getInstrumentation().getTargetContext();
         when(mContext.getApplicationInfo()).thenReturn(originalContext.getApplicationInfo());
 
-        when(mContext.getSystemService(Context.SHORTCUT_SERVICE)).thenReturn(mShortcutManager);
-        when(mContext.getSystemServiceName(ShortcutManager.class)).thenReturn(
-                Context.SHORTCUT_SERVICE);
-
         when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
         when(mContext.getSystemServiceName(UserManager.class)).thenReturn(
                 Context.USER_SERVICE);
@@ -179,7 +191,8 @@
         when(mUserManager.getEnabledProfiles(USER_ID_SECONDARY))
                 .thenReturn(Collections.singletonList(buildUserInfo(USER_ID_SECONDARY)));
 
-        when(mContext.getContentResolver()).thenReturn(mContentResolver);
+        when(mPackageManager.getPackageUidAsUser(TEST_PKG_NAME, USER_ID_PRIMARY))
+                .thenReturn(TEST_PKG_UID);
 
         when(mStatusBarNotification.getNotification()).thenReturn(mNotification);
         when(mStatusBarNotification.getPackageName()).thenReturn(TEST_PKG_NAME);
@@ -191,13 +204,15 @@
                 NOTIFICATION_CHANNEL_ID, "test channel", NotificationManager.IMPORTANCE_DEFAULT);
         mNotificationChannel.setConversationId("test", TEST_SHORTCUT_ID);
 
-        mCallingUserId = USER_ID_PRIMARY;
-
         mCancellationSignal = new CancellationSignal();
 
         mInjector = new TestInjector();
         mDataManager = new DataManager(mContext, mInjector);
         mDataManager.initialize();
+
+        verify(mShortcutServiceInternal).addShortcutChangeCallback(
+                mShortcutChangeCallbackCaptor.capture());
+        mShortcutChangeCallback = mShortcutChangeCallbackCaptor.getValue();
     }
 
     @After
@@ -213,18 +228,16 @@
         mDataManager.onUserUnlocked(USER_ID_PRIMARY_MANAGED);
         mDataManager.onUserUnlocked(USER_ID_SECONDARY);
 
-        mDataManager.onShortcutAddedOrUpdated(
+        mDataManager.addOrUpdateConversationInfo(
                 buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1",
                         buildPerson(true, false)));
-        mDataManager.onShortcutAddedOrUpdated(
+        mDataManager.addOrUpdateConversationInfo(
                 buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2",
                         buildPerson(false, true)));
-        mDataManager.onShortcutAddedOrUpdated(
+        mDataManager.addOrUpdateConversationInfo(
                 buildShortcutInfo("pkg_3", USER_ID_SECONDARY, "sc_3", buildPerson()));
 
-        List<ConversationInfo> conversations = new ArrayList<>();
-        mDataManager.forAllPackages(
-                packageData -> packageData.forAllConversations(conversations::add));
+        List<ConversationInfo> conversations = getConversationsInPrimary();
 
         // USER_ID_SECONDARY is not in the same profile group as USER_ID_PRIMARY.
         assertEquals(2, conversations.size());
@@ -245,23 +258,19 @@
     @Test
     public void testAccessConversationForUnlockedUsersOnly() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
-        mDataManager.onShortcutAddedOrUpdated(
+        mDataManager.addOrUpdateConversationInfo(
                 buildShortcutInfo("pkg_1", USER_ID_PRIMARY, "sc_1", buildPerson()));
-        mDataManager.onShortcutAddedOrUpdated(
+        mDataManager.addOrUpdateConversationInfo(
                 buildShortcutInfo("pkg_2", USER_ID_PRIMARY_MANAGED, "sc_2", buildPerson()));
 
-        List<ConversationInfo> conversations = new ArrayList<>();
-        mDataManager.forAllPackages(
-                packageData -> packageData.forAllConversations(conversations::add));
+        List<ConversationInfo> conversations = getConversationsInPrimary();
 
         // USER_ID_PRIMARY_MANAGED is not locked, so only USER_ID_PRIMARY's conversation is stored.
         assertEquals(1, conversations.size());
         assertEquals("sc_1", conversations.get(0).getShortcutId());
 
         mDataManager.onUserStopped(USER_ID_PRIMARY);
-        conversations.clear();
-        mDataManager.forAllPackages(
-                packageData -> packageData.forAllConversations(conversations::add));
+        conversations = getConversationsInPrimary();
         assertTrue(conversations.isEmpty());
     }
 
@@ -274,11 +283,12 @@
     }
 
     @Test
-    public void testReportAppTargetEvent() throws IntentFilter.MalformedMimeTypeException {
+    public void testReportAppTargetEvent_directSharing()
+            throws IntentFilter.MalformedMimeTypeException {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
                 .build();
@@ -287,14 +297,58 @@
                         .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
                         .build();
         IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
-        mDataManager.reportAppTargetEvent(appTargetEvent, intentFilter);
+        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
 
-        List<Range<Long>> activeShareTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeShareTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.TYPE_SHARE_IMAGE)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
+                Event.SHARE_EVENT_TYPES);
+        assertEquals(1, activeShareTimeSlots.size());
+    }
+
+    @Test
+    public void testReportAppTargetEvent_directSharing_createConversation()
+            throws IntentFilter.MalformedMimeTypeException {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                null);
+        AppTarget appTarget = new AppTarget.Builder(new AppTargetId(TEST_SHORTCUT_ID), shortcut)
+                .build();
+        AppTargetEvent appTargetEvent =
+                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
+                        .setLaunchLocation(ChooserActivity.LAUNCH_LOCATON_DIRECT_SHARE)
+                        .build();
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
+
+        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
+
+        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
+                Event.SHARE_EVENT_TYPES);
+        assertEquals(1, activeShareTimeSlots.size());
+        ConversationInfo conversationInfo = mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY)
+                .getConversationStore()
+                .getConversation(TEST_SHORTCUT_ID);
+        assertNotNull(conversationInfo);
+        assertEquals(conversationInfo.getShortcutId(), TEST_SHORTCUT_ID);
+    }
+
+    @Test
+    public void testReportAppTargetEvent_appSharing()
+            throws IntentFilter.MalformedMimeTypeException {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+        AppTarget appTarget = new AppTarget.Builder(
+                    new AppTargetId(TEST_SHORTCUT_ID),
+                    TEST_PKG_NAME,
+                    UserHandle.of(USER_ID_PRIMARY))
+                .setClassName(TEST_CLASS_NAME)
+                .build();
+        AppTargetEvent appTargetEvent =
+                new AppTargetEvent.Builder(appTarget, AppTargetEvent.ACTION_LAUNCH)
+                        .build();
+        IntentFilter intentFilter = new IntentFilter(Intent.ACTION_SEND, "image/jpg");
+
+        mDataManager.reportShareTargetEvent(appTargetEvent, intentFilter);
+
+        List<Range<Long>> activeShareTimeSlots = getActiveSlotsForTestShortcut(
+                Event.SHARE_EVENT_TYPES);
         assertEquals(1, activeShareTimeSlots.size());
     }
 
@@ -305,7 +359,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         final String newPhoneNumber = "+1000000000";
         mInjector.mContactsQueryHelper.mIsStarred = true;
@@ -315,9 +369,7 @@
                 USER_ID_PRIMARY);
         contentObserver.onChange(false, ContactsContract.Contacts.CONTENT_URI, USER_ID_PRIMARY);
 
-        List<ConversationInfo> conversations = new ArrayList<>();
-        mDataManager.forAllPackages(
-                packageData -> packageData.forAllConversations(conversations::add));
+        List<ConversationInfo> conversations = getConversationsInPrimary();
         assertEquals(1, conversations.size());
 
         assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
@@ -331,19 +383,15 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
 
         listenerService.onNotificationPosted(mStatusBarNotification);
 
-        List<Range<Long>> activeNotificationOpenTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeNotificationOpenTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.TYPE_NOTIFICATION_POSTED)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
+                Event.NOTIFICATION_EVENT_TYPES);
         assertEquals(1, activeNotificationOpenTimeSlots.size());
     }
 
@@ -353,7 +401,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
@@ -361,12 +409,8 @@
         listenerService.onNotificationRemoved(mStatusBarNotification, null,
                 NotificationListenerService.REASON_CLICK);
 
-        List<Range<Long>> activeNotificationOpenTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeNotificationOpenTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.TYPE_NOTIFICATION_OPENED)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeNotificationOpenTimeSlots = getActiveSlotsForTestShortcut(
+                Event.NOTIFICATION_EVENT_TYPES);
         assertEquals(1, activeNotificationOpenTimeSlots.size());
     }
 
@@ -377,7 +421,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
@@ -402,7 +446,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
@@ -428,7 +472,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         NotificationListenerService listenerService =
                 mDataManager.getNotificationListenerServiceForTesting(USER_ID_PRIMARY);
@@ -451,13 +495,50 @@
     }
 
     @Test
+    public void testShortcutAddedOrUpdated() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
+                buildPerson());
+        mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
+                Collections.singletonList(shortcut), UserHandle.of(USER_ID_PRIMARY));
+
+        List<ConversationInfo> conversations = getConversationsInPrimary();
+
+        assertEquals(1, conversations.size());
+        assertEquals(TEST_SHORTCUT_ID, conversations.get(0).getShortcutId());
+    }
+
+    @Test
+    public void testShortcutDeleted() {
+        mDataManager.onUserUnlocked(USER_ID_PRIMARY);
+
+        ShortcutInfo shortcut1 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc1",
+                buildPerson());
+        ShortcutInfo shortcut2 = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, "sc2",
+                buildPerson());
+        mShortcutChangeCallback.onShortcutsAddedOrUpdated(TEST_PKG_NAME,
+                Arrays.asList(shortcut1, shortcut2), UserHandle.of(USER_ID_PRIMARY));
+        mShortcutChangeCallback.onShortcutsRemoved(TEST_PKG_NAME,
+                Collections.singletonList(shortcut1), UserHandle.of(USER_ID_PRIMARY));
+
+        List<ConversationInfo> conversations = getConversationsInPrimary();
+
+        assertEquals(1, conversations.size());
+        assertEquals("sc2", conversations.get(0).getShortcutId());
+
+        verify(mNotificationManagerInternal)
+                .onConversationRemoved(TEST_PKG_NAME, TEST_PKG_UID, "sc1");
+    }
+
+    @Test
     public void testCallLogContentObserver() {
         mDataManager.onUserUnlocked(USER_ID_PRIMARY);
         mDataManager.onUserUnlocked(USER_ID_SECONDARY);
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         ContentObserver contentObserver = mDataManager.getCallLogContentObserverForTesting();
         contentObserver.onChange(false);
@@ -469,12 +550,7 @@
         mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                 new Event(currentTimestamp - MILLIS_PER_MINUTE * 5L, Event.TYPE_CALL_MISSED));
 
-        List<Range<Long>> activeTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.CALL_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
         assertEquals(3, activeTimeSlots.size());
     }
 
@@ -485,7 +561,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
         mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);
 
         ContentObserver contentObserver = mDataManager.getMmsSmsContentObserverForTesting();
@@ -498,12 +574,7 @@
         mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, outgoingSmsEvent);
         mInjector.mSmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER, incomingSmsEvent);
 
-        List<Range<Long>> activeTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.SMS_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
         assertEquals(2, activeTimeSlots.size());
     }
 
@@ -513,7 +584,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
         assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
 
         PackageMonitor packageMonitor = mDataManager.getPackageMonitorForTesting(USER_ID_PRIMARY);
@@ -530,7 +601,7 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
         assertNotNull(mDataManager.getPackage(TEST_PKG_NAME, USER_ID_PRIMARY));
 
         doAnswer(ans -> null).when(mPackageManagerInternal)
@@ -545,28 +616,18 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
 
         long currentTimestamp = System.currentTimeMillis();
         mInjector.mCallLogQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                 new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_CALL_OUTGOING));
 
-        List<Range<Long>> activeTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.CALL_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
         assertEquals(1, activeTimeSlots.size());
 
         mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultDialer(null);
         mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
-        activeTimeSlots.clear();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.CALL_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        activeTimeSlots = getActiveSlotsForTestShortcut(Event.CALL_EVENT_TYPES);
         assertTrue(activeTimeSlots.isEmpty());
     }
 
@@ -576,29 +637,19 @@
 
         ShortcutInfo shortcut = buildShortcutInfo(TEST_PKG_NAME, USER_ID_PRIMARY, TEST_SHORTCUT_ID,
                 buildPerson());
-        mDataManager.onShortcutAddedOrUpdated(shortcut);
+        mDataManager.addOrUpdateConversationInfo(shortcut);
         mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(TEST_PKG_NAME);
 
         long currentTimestamp = System.currentTimeMillis();
         mInjector.mMmsQueryHelper.mEventConsumer.accept(PHONE_NUMBER,
                 new Event(currentTimestamp - MILLIS_PER_MINUTE, Event.TYPE_SMS_OUTGOING));
 
-        List<Range<Long>> activeTimeSlots = new ArrayList<>();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.SMS_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        List<Range<Long>> activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
         assertEquals(1, activeTimeSlots.size());
 
         mDataManager.getUserDataForTesting(USER_ID_PRIMARY).setDefaultSmsApp(null);
         mDataManager.pruneDataForUser(USER_ID_PRIMARY, mCancellationSignal);
-        activeTimeSlots.clear();
-        mDataManager.forAllPackages(packageData ->
-                activeTimeSlots.addAll(
-                        packageData.getEventHistory(TEST_SHORTCUT_ID)
-                                .getEventIndex(Event.SMS_EVENT_TYPES)
-                                .getActiveTimeSlots()));
+        activeTimeSlots = getActiveSlotsForTestShortcut(Event.SMS_EVENT_TYPES);
         assertTrue(activeTimeSlots.isEmpty());
     }
 
@@ -607,6 +658,24 @@
         LocalServices.addService(clazz, mock);
     }
 
+    private List<ConversationInfo> getConversationsInPrimary() {
+        List<ConversationInfo> conversations = new ArrayList<>();
+        mDataManager.forPackagesInProfile(USER_ID_PRIMARY,
+                packageData -> packageData.forAllConversations(conversations::add));
+        return conversations;
+    }
+
+    private List<Range<Long>> getActiveSlotsForTestShortcut(
+            Set<Integer> eventTypes) {
+        List<Range<Long>> activeSlots = new ArrayList<>();
+        mDataManager.forPackagesInProfile(USER_ID_PRIMARY, packageData ->
+                activeSlots.addAll(
+                        packageData.getEventHistory(TEST_SHORTCUT_ID)
+                                .getEventIndex(eventTypes)
+                                .getActiveTimeSlots()));
+        return activeSlots;
+    }
+
     private ShortcutInfo buildShortcutInfo(String packageName, int userId, String id,
             @Nullable Person person) {
         Context mockContext = mock(Context.class);
@@ -754,6 +823,11 @@
         }
 
         @Override
+        Executor getBackgroundExecutor() {
+            return Runnable::run;
+        }
+
+        @Override
         ContactsQueryHelper createContactsQueryHelper(Context context) {
             return mContactsQueryHelper;
         }
@@ -778,10 +852,5 @@
             mSmsQueryHelper = new TestSmsQueryHelper(context, eventConsumer);
             return mSmsQueryHelper;
         }
-
-        @Override
-        int getCallingUserId() {
-            return mCallingUserId;
-        }
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
index 43e1001..825ca10 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/EventHistoryImplTest.java
@@ -21,18 +21,27 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
+import android.content.Context;
+import android.os.FileUtils;
+import android.text.format.DateUtils;
+
+import androidx.test.InstrumentationRegistry;
+
+import com.google.android.collect.Lists;
 import com.google.android.collect.Sets;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+import java.io.File;
 import java.util.List;
+import java.util.Map;
 
 @RunWith(JUnit4.class)
 public final class EventHistoryImplTest {
-
     private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
 
     private static final Event E1 = new Event(timestamp("01-06 05:26"),
@@ -41,26 +50,48 @@
             Event.TYPE_NOTIFICATION_OPENED);
     private static final Event E3 = new Event(timestamp("01-30 03:06"),
             Event.TYPE_SHARE_IMAGE);
-    private static final Event E4 = new Event(timestamp("01-30 18:14"),
+    private static final Event E4 = new Event(timestamp("01-30 16:14"),
+            Event.TYPE_SMS_INCOMING);
+    private static final Event E5 = new Event(timestamp("01-30 18:30"),
             Event.TYPE_SMS_INCOMING);
 
+    private static final EventIndex.Injector EVENT_INDEX_INJECTOR = new EventIndex.Injector() {
+        @Override
+        long currentTimeMillis() {
+            return CURRENT_TIMESTAMP;
+        }
+    };
+    private static final EventHistoryImpl.Injector EVENT_HISTORY_INJECTOR =
+            new EventHistoryImpl.Injector() {
+                @Override
+                EventIndex createEventIndex() {
+                    return new EventIndex(EVENT_INDEX_INJECTOR);
+                }
+
+                @Override
+                long currentTimeMillis() {
+                    return CURRENT_TIMESTAMP;
+                }
+            };
+
     private EventHistoryImpl mEventHistory;
+    private File mCacheDir;
+    private File mFile;
+    private MockScheduledExecutorService mMockScheduledExecutorService;
 
     @Before
     public void setUp() {
-        EventIndex.Injector eventIndexInjector = new EventIndex.Injector() {
-            @Override
-            long currentTimeMillis() {
-                return CURRENT_TIMESTAMP;
-            }
-        };
-        EventHistoryImpl.Injector eventHistoryInjector = new EventHistoryImpl.Injector() {
-            @Override
-            EventIndex createEventIndex() {
-                return new EventIndex(eventIndexInjector);
-            }
-        };
-        mEventHistory = new EventHistoryImpl(eventHistoryInjector);
+        Context ctx = InstrumentationRegistry.getContext();
+        mCacheDir = ctx.getCacheDir();
+        mFile = new File(mCacheDir, "testdir");
+        mMockScheduledExecutorService = new MockScheduledExecutorService();
+        mEventHistory = new EventHistoryImpl(EVENT_HISTORY_INJECTOR, mFile,
+                mMockScheduledExecutorService);
+    }
+
+    @After
+    public void tearDown() {
+        FileUtils.deleteContentsAndDir(mFile);
     }
 
     @Test
@@ -115,4 +146,105 @@
                 Sets.newArraySet(Event.TYPE_SHARE_IMAGE), 0L, Long.MAX_VALUE);
         assertEquals(1, events.size());
     }
+
+    @Test
+    public void testPersistenceAndRestoration() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+        mEventHistory.addEvent(E5);
+
+        // futures of events and event index flush.
+        long futuresExecuted = mMockScheduledExecutorService.fastForwardTime(
+                3L * DateUtils.MINUTE_IN_MILLIS);
+        assertEquals(2, futuresExecuted);
+
+        EventIndex indexBeforePowerOff = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+
+        resetAndLoadEventHistory();
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+        assertTrue(events.containsAll(Lists.newArrayList(E4, E5)));
+
+        EventIndex indexAfterPowerOff = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(indexBeforePowerOff, indexAfterPowerOff);
+    }
+
+    @Test
+    public void testMimicDevicePowerOff() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+        mEventHistory.addEvent(E5);
+        mEventHistory.saveToDisk();
+
+        EventIndex indexBeforePowerOff = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+
+        // Ensure that futures were cancelled and the immediate flush occurred.
+        assertEquals(0, mMockScheduledExecutorService.getFutures().size());
+
+        // Expect to see 2 executes from #saveToDisk, one for events and another for index.
+        assertEquals(2, mMockScheduledExecutorService.getExecutes().size());
+
+        resetAndLoadEventHistory();
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertEquals(2, events.size());
+        assertTrue(events.containsAll(Lists.newArrayList(E4, E5)));
+
+        EventIndex indexAfterPowerOff = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(indexBeforePowerOff, indexAfterPowerOff);
+    }
+
+    @Test
+    public void testOnDestroy() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+        mEventHistory.addEvent(E5);
+        mEventHistory.saveToDisk();
+
+        mEventHistory.onDestroy();
+
+        List<Event> events = mEventHistory.queryEvents(Event.ALL_EVENT_TYPES, 0L, Long.MAX_VALUE);
+        assertTrue(events.isEmpty());
+
+        EventIndex index = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+        assertTrue(index.isEmpty());
+    }
+
+    @Test
+    public void testEventHistoriesImplFromDisk() {
+        mEventHistory.addEvent(E1);
+        mEventHistory.addEvent(E2);
+        mEventHistory.addEvent(E3);
+        mEventHistory.addEvent(E4);
+        mEventHistory.addEvent(E5);
+        mEventHistory.saveToDisk();
+
+        EventIndex indexBefore = mEventHistory.getEventIndex(Event.ALL_EVENT_TYPES);
+
+        Map<String, EventHistoryImpl> map = EventHistoryImpl.eventHistoriesImplFromDisk(
+                EVENT_HISTORY_INJECTOR, mCacheDir, mMockScheduledExecutorService);
+        assertEquals(1, map.size());
+        assertTrue(map.containsKey("testdir"));
+
+        List<Event> events = map.get("testdir").queryEvents(Event.ALL_EVENT_TYPES, 0L,
+                Long.MAX_VALUE);
+        assertEquals(2, events.size());
+        assertTrue(events.containsAll(Lists.newArrayList(E4, E5)));
+
+        EventIndex indexAfter = map.get("testdir").getEventIndex(Event.ALL_EVENT_TYPES);
+        assertEquals(indexBefore, indexAfter);
+    }
+
+    private void resetAndLoadEventHistory() {
+        mEventHistory = new EventHistoryImpl(EVENT_HISTORY_INJECTOR, mFile,
+                mMockScheduledExecutorService);
+        mEventHistory.loadFromDisk();
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java b/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
index 8b8ba12..aecbc8d 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/MockScheduledExecutorService.java
@@ -54,8 +54,8 @@
         long totalExecuted = 0;
         for (MockScheduledFuture<?> future : futuresCopy) {
             if (future.getDelay() < mTimeElapsedMillis) {
-                future.getCommand().run();
-                mExecutes.add(future.getCommand());
+                future.getRunnable().run();
+                mExecutes.add(future.getRunnable());
                 totalExecuted += 1;
             } else {
                 mFutures.add(future);
@@ -96,7 +96,8 @@
     @Override
     public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period,
             TimeUnit unit) {
-        throw new UnsupportedOperationException();
+        Preconditions.checkState(unit == TimeUnit.MILLISECONDS);
+        return new MockScheduledFuture<>(command, period, unit);
     }
 
     @Override
@@ -132,7 +133,13 @@
 
     @Override
     public <T> Future<T> submit(Callable<T> task) {
-        throw new UnsupportedOperationException();
+        MockScheduledFuture<T> future = new MockScheduledFuture<>(task, 0, TimeUnit.MILLISECONDS);
+        try {
+            future.getCallable().call();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return future;
     }
 
     @Override
@@ -141,11 +148,11 @@
     }
 
     @Override
-    public Future<?> submit(Runnable command) {
-        mExecutes.add(command);
-        MockScheduledFuture<?> future = new MockScheduledFuture<>(command, 0,
+    public Future<?> submit(Runnable runnable) {
+        mExecutes.add(runnable);
+        MockScheduledFuture<?> future = new MockScheduledFuture<>(runnable, 0,
                 TimeUnit.MILLISECONDS);
-        future.getCommand().run();
+        future.getRunnable().run();
         return future;
     }
 
@@ -181,12 +188,22 @@
 
     class MockScheduledFuture<V> implements ScheduledFuture<V> {
 
-        private final Runnable mCommand;
+        private final Runnable mRunnable;
+        private final Callable<V> mCallable;
         private final long mDelay;
         private boolean mCancelled = false;
 
-        MockScheduledFuture(Runnable command, long delay, TimeUnit timeUnit) {
-            mCommand = command;
+        MockScheduledFuture(Runnable runnable, long delay, TimeUnit timeUnit) {
+            this(runnable, null, delay);
+        }
+
+        MockScheduledFuture(Callable<V> callable, long delay, TimeUnit timeUnit) {
+            this(null, callable, delay);
+        }
+
+        private MockScheduledFuture(Runnable runnable, Callable<V> callable, long delay) {
+            mCallable = callable;
+            mRunnable = runnable;
             mDelay = delay;
         }
 
@@ -194,8 +211,12 @@
             return mDelay;
         }
 
-        public Runnable getCommand() {
-            return mCommand;
+        public Runnable getRunnable() {
+            return mRunnable;
+        }
+
+        public Callable<V> getCallable() {
+            return mCallable;
         }
 
         @Override
diff --git a/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
index e52cdf5..8191d17 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/PackageDataTest.java
@@ -61,7 +61,7 @@
         testDir.mkdir();
         mPackageData = new PackageData(
                 PACKAGE_NAME, USER_ID, pkg -> mIsDefaultDialer, pkg -> mIsDefaultSmsApp,
-                new MockScheduledExecutorService(), testDir, new ContactsQueryHelper(ctx));
+                new MockScheduledExecutorService(), testDir);
         ConversationInfo conversationInfo = new ConversationInfo.Builder()
                 .setShortcutId(SHORTCUT_ID)
                 .setLocusId(LOCUS_ID)
diff --git a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
index d444466..7934d33 100644
--- a/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
@@ -16,6 +16,8 @@
 
 package com.android.server.people.data;
 
+import static com.android.server.people.data.TestUtils.timestamp;
+
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -62,7 +64,8 @@
     private static final LocusId LOCUS_ID_1 = new LocusId("locus_1");
     private static final LocusId LOCUS_ID_2 = new LocusId("locus_2");
 
-    @Mock private UsageStatsManagerInternal mUsageStatsManagerInternal;
+    @Mock
+    private UsageStatsManagerInternal mUsageStatsManagerInternal;
 
     private TestPackageData mPackageData;
     private UsageStatsQueryHelper mHelper;
@@ -76,10 +79,9 @@
         Context ctx = InstrumentationRegistry.getContext();
         File testDir = new File(ctx.getCacheDir(), "testdir");
         ScheduledExecutorService scheduledExecutorService = new MockScheduledExecutorService();
-        ContactsQueryHelper helper = new ContactsQueryHelper(ctx);
 
         mPackageData = new TestPackageData(PKG_NAME, USER_ID_PRIMARY, pkg -> false, pkg -> false,
-                scheduledExecutorService, testDir, helper);
+                scheduledExecutorService, testDir);
         mPackageData.mConversationStore.mConversationInfo = new ConversationInfo.Builder()
                 .setShortcutId(SHORTCUT_ID)
                 .setLocusId(LOCUS_ID_1)
@@ -218,9 +220,8 @@
         private ConversationInfo mConversationInfo;
 
         TestConversationStore(File packageDir,
-                ScheduledExecutorService scheduledExecutorService,
-                ContactsQueryHelper helper) {
-            super(packageDir, scheduledExecutorService, helper);
+                ScheduledExecutorService scheduledExecutorService) {
+            super(packageDir, scheduledExecutorService);
         }
 
         @Override
@@ -233,17 +234,16 @@
     private static class TestPackageData extends PackageData {
 
         private final TestConversationStore mConversationStore;
-        private final TestEventStore mEventStore = new TestEventStore();
+        private final TestEventStore mEventStore;
 
         TestPackageData(@NonNull String packageName, @UserIdInt int userId,
                 @NonNull Predicate<String> isDefaultDialerPredicate,
                 @NonNull Predicate<String> isDefaultSmsAppPredicate,
-                @NonNull ScheduledExecutorService scheduledExecutorService, @NonNull File rootDir,
-                @NonNull ContactsQueryHelper helper) {
+                @NonNull ScheduledExecutorService scheduledExecutorService, @NonNull File rootDir) {
             super(packageName, userId, isDefaultDialerPredicate, isDefaultSmsAppPredicate,
-                    scheduledExecutorService, rootDir, helper);
-            mConversationStore = new TestConversationStore(rootDir, scheduledExecutorService,
-                    helper);
+                    scheduledExecutorService, rootDir);
+            mConversationStore = new TestConversationStore(rootDir, scheduledExecutorService);
+            mEventStore = new TestEventStore(rootDir, scheduledExecutorService);
         }
 
         @Override
@@ -261,8 +261,31 @@
 
     private static class TestEventStore extends EventStore {
 
-        private final EventHistoryImpl mShortcutEventHistory = new TestEventHistoryImpl();
-        private final EventHistoryImpl mLocusEventHistory = new TestEventHistoryImpl();
+        private static final long CURRENT_TIMESTAMP = timestamp("01-30 18:50");
+        private static final EventIndex.Injector EVENT_INDEX_INJECTOR = new EventIndex.Injector() {
+            @Override
+            long currentTimeMillis() {
+                return CURRENT_TIMESTAMP;
+            }
+        };
+        private static final EventHistoryImpl.Injector EVENT_HISTORY_INJECTOR =
+                new EventHistoryImpl.Injector() {
+                    @Override
+                    EventIndex createEventIndex() {
+                        return new EventIndex(EVENT_INDEX_INJECTOR);
+                    }
+                };
+
+        private final EventHistoryImpl mShortcutEventHistory;
+        private final EventHistoryImpl mLocusEventHistory;
+
+        TestEventStore(File rootDir, ScheduledExecutorService scheduledExecutorService) {
+            super(rootDir, scheduledExecutorService);
+            mShortcutEventHistory = new TestEventHistoryImpl(EVENT_HISTORY_INJECTOR, rootDir,
+                    scheduledExecutorService);
+            mLocusEventHistory = new TestEventHistoryImpl(EVENT_HISTORY_INJECTOR, rootDir,
+                    scheduledExecutorService);
+        }
 
         @Override
         @NonNull
@@ -280,6 +303,11 @@
 
         private final List<Event> mEvents = new ArrayList<>();
 
+        TestEventHistoryImpl(Injector injector, File rootDir,
+                ScheduledExecutorService scheduledExecutorService) {
+            super(injector, rootDir, scheduledExecutorService);
+        }
+
         @Override
         @NonNull
         public List<Event> queryEvents(Set<Integer> eventTypes, long startTime, long endTime) {
diff --git a/services/tests/servicestests/src/com/android/server/people/prediction/ShareTargetPredictorTest.java b/services/tests/servicestests/src/com/android/server/people/prediction/ShareTargetPredictorTest.java
index 808906e..c6cd347 100644
--- a/services/tests/servicestests/src/com/android/server/people/prediction/ShareTargetPredictorTest.java
+++ b/services/tests/servicestests/src/com/android/server/people/prediction/ShareTargetPredictorTest.java
@@ -16,15 +16,19 @@
 
 package com.android.server.people.prediction;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anySet;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
 import android.app.prediction.AppPredictionContext;
+import android.app.prediction.AppTarget;
+import android.app.prediction.AppTargetId;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -32,22 +36,26 @@
 import android.content.pm.ShortcutManager.ShareShortcutInfo;
 import android.os.Bundle;
 import android.os.UserHandle;
+import android.util.Range;
 
 import com.android.server.people.data.ConversationInfo;
 import com.android.server.people.data.DataManager;
 import com.android.server.people.data.EventHistory;
+import com.android.server.people.data.EventIndex;
 import com.android.server.people.data.PackageData;
-import com.android.server.people.prediction.ShareTargetPredictor.ShareTarget;
 
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.function.Consumer;
 
 @RunWith(JUnit4.class)
 public final class ShareTargetPredictorTest {
@@ -56,24 +64,39 @@
     private static final int NUM_PREDICTED_TARGETS = 5;
     private static final int USER_ID = 0;
     private static final String PACKAGE_1 = "pkg1";
-    private static final String CLASS_1 = "cls1";
     private static final String PACKAGE_2 = "pkg2";
+    private static final String PACKAGE_3 = "pkg3";
+    private static final String CLASS_1 = "cls1";
     private static final String CLASS_2 = "cls2";
 
     @Mock private Context mContext;
     @Mock private DataManager mDataManager;
+    @Mock private Consumer<List<AppTarget>> mUpdatePredictionsMethod;
     @Mock private PackageData mPackageData1;
     @Mock private PackageData mPackageData2;
+    @Mock private EventHistory mEventHistory1;
+    @Mock private EventHistory mEventHistory2;
+    @Mock private EventHistory mEventHistory3;
+    @Mock private EventHistory mEventHistory4;
+    @Mock private EventHistory mEventHistory5;
+    @Mock private EventHistory mEventHistory6;
+
+    @Mock private EventIndex mEventIndex1;
+    @Mock private EventIndex mEventIndex2;
+    @Mock private EventIndex mEventIndex3;
+    @Mock private EventIndex mEventIndex4;
+    @Mock private EventIndex mEventIndex5;
+    @Mock private EventIndex mEventIndex6;
+    @Captor private ArgumentCaptor<List<AppTarget>> mAppTargetCaptor;
 
     private List<ShareShortcutInfo> mShareShortcuts = new ArrayList<>();
-
     private ShareTargetPredictor mPredictor;
 
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
 
-        when(mDataManager.getShareShortcuts(any())).thenReturn(mShareShortcuts);
+        when(mDataManager.getShareShortcuts(any(), anyInt())).thenReturn(mShareShortcuts);
         when(mDataManager.getPackage(PACKAGE_1, USER_ID)).thenReturn(mPackageData1);
         when(mDataManager.getPackage(PACKAGE_2, USER_ID)).thenReturn(mPackageData2);
 
@@ -82,11 +105,12 @@
                 .setPredictedTargetCount(NUM_PREDICTED_TARGETS)
                 .setExtras(new Bundle())
                 .build();
-        mPredictor = new ShareTargetPredictor(predictionContext, targets -> { }, mDataManager);
+        mPredictor = new ShareTargetPredictor(
+                predictionContext, mUpdatePredictionsMethod, mDataManager, USER_ID);
     }
 
     @Test
-    public void testGetShareTargets() {
+    public void testPredictTargets() {
         mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc1"));
         mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc2"));
         mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc3"));
@@ -97,24 +121,148 @@
         when(mPackageData2.getConversationInfo("sc3")).thenReturn(mock(ConversationInfo.class));
         // "sc4" does not have a ConversationInfo.
 
-        when(mPackageData1.getEventHistory(anyString())).thenReturn(mock(EventHistory.class));
-        when(mPackageData2.getEventHistory(anyString())).thenReturn(mock(EventHistory.class));
+        when(mPackageData1.getEventHistory("sc1")).thenReturn(mEventHistory1);
+        when(mPackageData1.getEventHistory("sc2")).thenReturn(mEventHistory2);
+        when(mPackageData2.getEventHistory("sc3")).thenReturn(mEventHistory3);
+        when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
+        when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
+        when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
+        when(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
+        when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
+        when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
 
-        List<ShareTarget> shareTargets = mPredictor.getShareTargets();
+        mPredictor.predictTargets();
 
-        assertEquals(4, shareTargets.size());
+        verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
+        List<AppTarget> res = mAppTargetCaptor.getValue();
+        assertEquals(4, res.size());
 
-        assertEquals("sc1", shareTargets.get(0).getShareShortcutInfo().getShortcutInfo().getId());
-        assertNotNull(shareTargets.get(0).getConversationData());
+        assertEquals("sc3", res.get(0).getId().getId());
+        assertEquals(CLASS_2, res.get(0).getClassName());
+        assertEquals(PACKAGE_2, res.get(0).getPackageName());
 
-        assertEquals("sc2", shareTargets.get(1).getShareShortcutInfo().getShortcutInfo().getId());
-        assertNotNull(shareTargets.get(1).getConversationData());
+        assertEquals("sc2", res.get(1).getId().getId());
+        assertEquals(CLASS_1, res.get(1).getClassName());
+        assertEquals(PACKAGE_1, res.get(1).getPackageName());
 
-        assertEquals("sc3", shareTargets.get(2).getShareShortcutInfo().getShortcutInfo().getId());
-        assertNotNull(shareTargets.get(2).getConversationData());
+        assertEquals("sc1", res.get(2).getId().getId());
+        assertEquals(CLASS_1, res.get(2).getClassName());
+        assertEquals(PACKAGE_1, res.get(2).getPackageName());
 
-        assertEquals("sc4", shareTargets.get(3).getShareShortcutInfo().getShortcutInfo().getId());
-        assertNull(shareTargets.get(3).getConversationData());
+        assertEquals("sc4", res.get(3).getId().getId());
+        assertEquals(CLASS_2, res.get(3).getClassName());
+        assertEquals(PACKAGE_2, res.get(3).getPackageName());
+    }
+
+    @Test
+    public void testPredictTargets_reachTargetsLimit() {
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc1"));
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc2"));
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc3"));
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc4"));
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_1, CLASS_1, "sc5"));
+        mShareShortcuts.add(buildShareShortcut(PACKAGE_2, CLASS_2, "sc6"));
+
+        when(mPackageData1.getConversationInfo("sc1")).thenReturn(mock(ConversationInfo.class));
+        when(mPackageData1.getConversationInfo("sc2")).thenReturn(mock(ConversationInfo.class));
+        when(mPackageData2.getConversationInfo("sc3")).thenReturn(mock(ConversationInfo.class));
+        when(mPackageData2.getConversationInfo("sc4")).thenReturn(mock(ConversationInfo.class));
+        when(mPackageData1.getConversationInfo("sc5")).thenReturn(mock(ConversationInfo.class));
+        when(mPackageData2.getConversationInfo("sc6")).thenReturn(mock(ConversationInfo.class));
+
+        when(mPackageData1.getEventHistory("sc1")).thenReturn(mEventHistory1);
+        when(mPackageData1.getEventHistory("sc2")).thenReturn(mEventHistory2);
+        when(mPackageData2.getEventHistory("sc3")).thenReturn(mEventHistory3);
+        when(mPackageData2.getEventHistory("sc4")).thenReturn(mEventHistory4);
+        when(mPackageData1.getEventHistory("sc5")).thenReturn(mEventHistory5);
+        when(mPackageData2.getEventHistory("sc6")).thenReturn(mEventHistory6);
+
+        when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
+        when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
+        when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
+        when(mEventHistory4.getEventIndex(anySet())).thenReturn(mEventIndex4);
+        when(mEventHistory5.getEventIndex(anySet())).thenReturn(mEventIndex5);
+        when(mEventHistory6.getEventIndex(anySet())).thenReturn(mEventIndex6);
+        when(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
+        when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
+        when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
+        when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(4L, 5L));
+        when(mEventIndex5.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(5L, 6L));
+        when(mEventIndex6.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(6L, 7L));
+
+        mPredictor.predictTargets();
+
+        verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
+        List<AppTarget> res = mAppTargetCaptor.getValue();
+        assertEquals(5, res.size());
+
+        assertEquals("sc6", res.get(0).getId().getId());
+        assertEquals(CLASS_2, res.get(0).getClassName());
+        assertEquals(PACKAGE_2, res.get(0).getPackageName());
+
+        assertEquals("sc5", res.get(1).getId().getId());
+        assertEquals(CLASS_1, res.get(1).getClassName());
+        assertEquals(PACKAGE_1, res.get(1).getPackageName());
+
+        assertEquals("sc4", res.get(2).getId().getId());
+        assertEquals(CLASS_2, res.get(2).getClassName());
+        assertEquals(PACKAGE_2, res.get(2).getPackageName());
+
+        assertEquals("sc3", res.get(3).getId().getId());
+        assertEquals(CLASS_2, res.get(3).getClassName());
+        assertEquals(PACKAGE_2, res.get(3).getPackageName());
+
+        assertEquals("sc2", res.get(4).getId().getId());
+        assertEquals(CLASS_1, res.get(4).getClassName());
+        assertEquals(PACKAGE_1, res.get(4).getPackageName());
+    }
+
+    @Test
+    public void testSortTargets() {
+        AppTarget appTarget1 = new AppTarget.Builder(
+                    new AppTargetId("cls1#pkg1"), PACKAGE_1, UserHandle.of(USER_ID))
+                .setClassName(CLASS_1)
+                .build();
+        AppTarget appTarget2 = new AppTarget.Builder(
+                    new AppTargetId("cls2#pkg1"), PACKAGE_1, UserHandle.of(USER_ID))
+                .setClassName(CLASS_2)
+                .build();
+        AppTarget appTarget3 = new AppTarget.Builder(
+                    new AppTargetId("cls1#pkg2"), PACKAGE_2, UserHandle.of(USER_ID))
+                .setClassName(CLASS_1)
+                .build();
+        AppTarget appTarget4 = new AppTarget.Builder(
+                    new AppTargetId("cls2#pkg2"), PACKAGE_2, UserHandle.of(USER_ID))
+                .setClassName(CLASS_2)
+                .build();
+        AppTarget appTarget5 = new AppTarget.Builder(
+                new AppTargetId("cls1#pkg3"), PACKAGE_3, UserHandle.of(USER_ID))
+                .setClassName(CLASS_1)
+                .build();
+
+        when(mPackageData1.getClassLevelEventHistory(CLASS_1)).thenReturn(mEventHistory1);
+        when(mPackageData1.getClassLevelEventHistory(CLASS_2)).thenReturn(mEventHistory2);
+        when(mPackageData2.getClassLevelEventHistory(CLASS_1)).thenReturn(mEventHistory3);
+        when(mPackageData2.getClassLevelEventHistory(CLASS_2)).thenReturn(mEventHistory4);
+        // PackageData of PACKAGE_3 is empty.
+        when(mDataManager.getPackage(PACKAGE_3, USER_ID)).thenReturn(null);
+
+        when(mEventHistory1.getEventIndex(anySet())).thenReturn(mEventIndex1);
+        when(mEventHistory2.getEventIndex(anySet())).thenReturn(mEventIndex2);
+        when(mEventHistory3.getEventIndex(anySet())).thenReturn(mEventIndex3);
+        when(mEventHistory4.getEventIndex(anySet())).thenReturn(mEventIndex4);
+        when(mEventIndex1.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(1L, 2L));
+        when(mEventIndex2.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(2L, 3L));
+        when(mEventIndex3.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(3L, 4L));
+        when(mEventIndex4.getMostRecentActiveTimeSlot()).thenReturn(new Range<>(4L, 5L));
+
+        mPredictor.sortTargets(
+                List.of(appTarget1, appTarget2, appTarget3, appTarget4, appTarget5),
+                mUpdatePredictionsMethod);
+
+        verify(mUpdatePredictionsMethod).accept(mAppTargetCaptor.capture());
+        assertThat(mAppTargetCaptor.getValue()).containsExactly(
+                appTarget4, appTarget3, appTarget2, appTarget1, appTarget5);
     }
 
     private ShareShortcutInfo buildShareShortcut(
diff --git a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
index 9670658..5d5c714 100644
--- a/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/AppsFilterTest.java
@@ -29,12 +29,10 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageParser;
 import android.content.pm.Signature;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
-import android.content.pm.parsing.PackageImpl;
 import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedProvider;
 import android.os.Build;
 import android.os.Process;
 import android.platform.test.annotations.Presubmit;
@@ -44,6 +42,9 @@
 import androidx.annotation.NonNull;
 
 import com.android.server.om.OverlayReferenceMapper;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -74,7 +75,7 @@
     private ArrayMap<String, PackageSetting> mExisting = new ArrayMap<>();
 
     private static ParsingPackage pkg(String packageName) {
-        return PackageImpl.forParsing(packageName)
+        return PackageImpl.forTesting(packageName)
                 .setTargetSdkVersion(Build.VERSION_CODES.R);
     }
 
@@ -113,7 +114,7 @@
         ParsedActivity activity = new ParsedActivity();
         activity.setPackageName(packageName);
         for (IntentFilter filter : filters) {
-            final ParsedActivityIntentInfo info = new ParsedActivityIntentInfo(packageName, null);
+            final ParsedIntentInfo info = new ParsedIntentInfo();
             if (filter.countActions() > 0) {
                 filter.actionsIterator().forEachRemaining(info::addAction);
             }
@@ -127,7 +128,7 @@
                 filter.schemesIterator().forEachRemaining(info::addDataScheme);
             }
             activity.addIntent(info);
-            activity.exported = true;
+            activity.setExported(true);
         }
 
         return pkg(packageName)
@@ -135,7 +136,7 @@
     }
 
     private static ParsingPackage pkgWithProvider(String packageName, String authority) {
-        ComponentParseUtils.ParsedProvider provider = new ComponentParseUtils.ParsedProvider();
+        ParsedProvider provider = new ParsedProvider();
         provider.setPackageName(packageName);
         provider.setExported(true);
         provider.setAuthority(authority);
@@ -437,7 +438,7 @@
         ParsingPackage target = pkg("com.some.package.target")
                 .addOverlayable("overlayableName", actorName);
         ParsingPackage overlay = pkg("com.some.package.overlay")
-                .setIsOverlay(true)
+                .setOverlay(true)
                 .setOverlayTarget(target.getPackageName())
                 .setOverlayTargetName("overlayableName");
         ParsingPackage actor = pkg("com.some.package.actor");
@@ -499,7 +500,7 @@
         ParsingPackage target = pkg("com.some.package.target")
                 .addOverlayable("overlayableName", actorName);
         ParsingPackage overlay = pkg("com.some.package.overlay")
-                .setIsOverlay(true)
+                .setOverlay(true)
                 .setOverlayTarget(target.getPackageName())
                 .setOverlayTargetName("overlayableName");
         ParsingPackage actorOne = pkg("com.some.package.actor.one");
@@ -618,7 +619,7 @@
 
     private PackageSetting simulateAddPackage(AppsFilter filter,
             ParsingPackage newPkgBuilder, int appId, @Nullable WithSettingBuilder action) {
-        AndroidPackage newPkg = newPkgBuilder.hideAsParsed().hideAsFinal();
+        AndroidPackage newPkg = ((ParsedPackage) newPkgBuilder.hideAsParsed()).hideAsFinal();
 
         final PackageSettingBuilder settingBuilder = new PackageSettingBuilder()
                 .setPackage(newPkg)
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index df2b3ef..6c769485 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -562,6 +562,11 @@
         boolean injectHasAccessShortcutsPermission(int callingPid, int callingUid) {
             return true;
         }
+
+        @Override
+        boolean injectHasInteractAcrossUsersFullPermission(int callingPid, int callingUid) {
+            return false;
+        }
     }
 
     protected class LauncherAppsTestable extends LauncherApps {
diff --git a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
index 0273a1c..164bd72 100644
--- a/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/KeySetManagerServiceTest.java
@@ -40,7 +40,7 @@
         return new PackageSetting(name, name, new File(mContext.getCacheDir(), "fakeCodePath"),
                 new File(mContext.getCacheDir(), "fakeResPath"), "", "", "",
                 "", 1, 0, 0, 0 /*sharedUserId*/, null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/, null /*mimeGroups*/);
     }
 
     @Override
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
index 85840e1..9cf6702 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java
@@ -88,7 +88,7 @@
                 new File("resourcePath"), "legacyNativeLibraryPathString",
                 "primaryCpuAbiString", "secondaryCpuAbiString",
                 "cpuAbiOverrideString", 0, 0, 0, 0,
-                null, null);
+                null, null, null);
         pri.populateUsers(new int[] {
                 1, 2, 3, 4, 5
         }, setting);
@@ -118,15 +118,15 @@
         String[] partitions = { "system", "vendor", "odm", "oem", "product", "system_ext" };
         String[] appdir = { "app", "priv-app" };
         for (int i = 0; i < partitions.length; i++) {
-            final PackageManagerService.SystemPartition systemPartition =
+            final PackageManagerService.ScanPartition scanPartition =
                     PackageManagerService.SYSTEM_PARTITIONS.get(i);
             for (int j = 0; j < appdir.length; j++) {
                 String canonical = new File("/" + partitions[i]).getCanonicalPath();
                 String path = String.format("%s/%s/A.apk", canonical, appdir[j]);
 
-                Assert.assertEquals(j == 1 && i != 3, systemPartition.containsPrivPath(path));
+                Assert.assertEquals(j == 1 && i != 3, scanPartition.containsPrivPath(path));
 
-                final int scanFlag = systemPartition.scanFlag;
+                final int scanFlag = scanPartition.scanFlag;
                 Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR);
                 Assert.assertEquals(i == 2, scanFlag == PackageManagerService.SCAN_AS_ODM);
                 Assert.assertEquals(i == 3, scanFlag == PackageManagerService.SCAN_AS_OEM);
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index cf51fa3..acfe71a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -431,7 +431,8 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 0,
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         final PackageSetting testPkgSetting01 = new PackageSetting(origPkgSetting01);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
     }
@@ -452,7 +453,8 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
                 0,
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         final PackageSetting testPkgSetting01 = new PackageSetting(
                 PACKAGE_NAME /*pkgName*/,
                 REAL_PACKAGE_NAME /*realPkgName*/,
@@ -467,7 +469,8 @@
                 0 /*pkgPrivateFlags*/,
                 0,
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         testPkgSetting01.copyFrom(origPkgSetting01);
         verifySettingCopy(origPkgSetting01, testPkgSetting01);
     }
@@ -494,7 +497,8 @@
                 0 /*pkgPrivateFlags*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
         assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
         assertThat(testPkgSetting01.pkgFlags, is(0));
@@ -527,7 +531,8 @@
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.primaryCpuAbiString, is("arm64-v8a"));
         assertThat(testPkgSetting01.secondaryCpuAbiString, is("armeabi"));
         assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
@@ -566,7 +571,8 @@
                     0 /*pkgPrivateFlags*/,
                     UserManagerService.getInstance(),
                     null /*usesStaticLibraries*/,
-                    null /*usesStaticLibrariesVersions*/);
+                    null /*usesStaticLibrariesVersions*/,
+                    null /*mimeGroups*/);
             fail("Expected a PackageManagerException");
         } catch (PackageManagerException expected) {
         }
@@ -598,7 +604,8 @@
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
         assertThat(testPkgSetting01.pkgFlags, is(ApplicationInfo.FLAG_SYSTEM));
@@ -637,7 +644,8 @@
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.appId, is(0));
         assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -682,7 +690,8 @@
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.appId, is(10064));
         assertThat(testPkgSetting01.codePath, is(INITIAL_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -724,7 +733,8 @@
                 false /*virtualPreload*/,
                 UserManagerService.getInstance(),
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
         assertThat(testPkgSetting01.appId, is(10064));
         assertThat(testPkgSetting01.codePath, is(UPDATED_CODE_PATH));
         assertThat(testPkgSetting01.name, is(PACKAGE_NAME));
@@ -795,6 +805,8 @@
                 testPkgSetting.legacyNativeLibraryPathString);
         assertThat(origPkgSetting.legacyNativeLibraryPathString,
                 is(testPkgSetting.legacyNativeLibraryPathString));
+        assertNotSame(origPkgSetting.mimeGroups, testPkgSetting.mimeGroups);
+        assertThat(origPkgSetting.mimeGroups, is(testPkgSetting.mimeGroups));
         assertNotSame(origPkgSetting.mPermissionsState, testPkgSetting.mPermissionsState);
         assertThat(origPkgSetting.mPermissionsState, is(testPkgSetting.mPermissionsState));
         assertThat(origPkgSetting.name, is(testPkgSetting.name));
@@ -854,7 +866,8 @@
                 0 /*privateFlags*/,
                 sharedUserId,
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
     }
 
     private PackageSetting createPackageSetting(String packageName) {
@@ -872,7 +885,8 @@
                 0 /*privateFlags*/,
                 0,
                 null /*usesStaticLibraries*/,
-                null /*usesStaticLibrariesVersions*/);
+                null /*usesStaticLibrariesVersions*/,
+                null /*mimeGroups*/);
     }
 
     private @NonNull List<UserInfo> createFakeUsers() {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 56ac7c5..d2ec500 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -21,6 +21,7 @@
 import static org.junit.Assert.assertSame;
 import static org.junit.Assert.assertTrue;
 
+import android.annotation.NonNull;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ConfigurationInfo;
@@ -31,32 +32,34 @@
 import android.content.pm.PackageUserState;
 import android.content.pm.ProviderInfo;
 import android.content.pm.ServiceInfo;
-import android.content.pm.SharedLibraryInfo;
 import android.content.pm.Signature;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils;
-import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
-import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
-import android.content.pm.parsing.ComponentParseUtils.ParsedInstrumentation;
-import android.content.pm.parsing.ComponentParseUtils.ParsedIntentInfo;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermissionGroup;
-import android.content.pm.parsing.ComponentParseUtils.ParsedProvider;
-import android.content.pm.parsing.ComponentParseUtils.ParsedService;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.PackageInfoUtils;
-import android.content.pm.parsing.ParsedPackage;
 import android.content.pm.parsing.ParsingPackage;
+import android.content.pm.parsing.component.ParsedActivity;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedInstrumentation;
+import android.content.pm.parsing.component.ParsedIntentInfo;
+import android.content.pm.parsing.component.ParsedPermission;
+import android.content.pm.parsing.component.ParsedPermissionGroup;
+import android.content.pm.parsing.component.ParsedProvider;
+import android.content.pm.parsing.component.ParsedService;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
+import android.util.DisplayMetrics;
 
+import androidx.annotation.Nullable;
 import androidx.test.filters.MediumTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.PackageCacher;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -70,12 +73,12 @@
 import java.lang.reflect.Field;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 @MediumTest
 public class PackageParserTest {
@@ -96,13 +99,13 @@
 
     @Test
     public void testParse_noCache() throws Exception {
-        PackageParser pp = new CachePackageNameParser();
-        ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */,
+        CachePackageNameParser pp = new CachePackageNameParser(null, false, null, null, null);
+        ParsedPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                 false /* useCaches */);
         assertNotNull(pkg);
 
         pp.setCacheDir(mTmpDir);
-        pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */,
+        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                 false /* useCaches */);
         assertNotNull(pkg);
 
@@ -113,39 +116,37 @@
 
     @Test
     public void testParse_withCache() throws Exception {
-        PackageParser pp = new CachePackageNameParser();
+        CachePackageNameParser pp = new CachePackageNameParser(null, false, null, null, null);
 
         pp.setCacheDir(mTmpDir);
         // The first parse will write this package to the cache.
-        pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+        pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
 
         // Now attempt to parse the package again, should return the
         // cached result.
-        ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */,
+        ParsedPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                 true /* useCaches */);
         assertEquals("cache_android", pkg.getPackageName());
 
         // Try again, with useCaches == false, shouldn't return the parsed
         // result.
-        pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
         assertEquals("android", pkg.getPackageName());
 
         // We haven't set a cache directory here : the parse should still succeed,
         // just not using the cached results.
-        pp = new CachePackageNameParser();
-        pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
+        pp = new CachePackageNameParser(null, false, null, null, null);
+        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, true /* useCaches */);
         assertEquals("android", pkg.getPackageName());
 
-        pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
+        pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */, false /* useCaches */);
         assertEquals("android", pkg.getPackageName());
     }
 
     @Test
     public void test_serializePackage() throws Exception {
-        PackageParser pp = new PackageParser();
-        pp.setCacheDir(mTmpDir);
-
-        ParsedPackage pkg = pp.parseParsedPackage(FRAMEWORK, 0 /* parseFlags */,
+        PackageParser2 pp = new PackageParser2(null, false, null, mTmpDir, null);
+        ParsedPackage pkg = pp.parsePackage(FRAMEWORK, 0 /* parseFlags */,
                 true /* useCaches */);
 
         Parcel p = Parcel.obtain();
@@ -161,7 +162,7 @@
     @SmallTest
     @Presubmit
     public void test_roundTripKnownFields() throws Exception {
-        ParsingPackage pkg = PackageImpl.forParsing("foo");
+        ParsingPackage pkg = PackageImpl.forTesting("foo");
         setKnownFields(pkg);
 
         Parcel p = Parcel.obtain();
@@ -174,7 +175,7 @@
 
     @Test
     public void test_stringInterning() throws Exception {
-        ParsingPackage pkg = PackageImpl.forParsing("foo");
+        ParsingPackage pkg = PackageImpl.forTesting("foo");
         setKnownFields(pkg);
 
         Parcel p = Parcel.obtain();
@@ -212,19 +213,44 @@
      * A trivial subclass of package parser that only caches the package name, and throws away
      * all other information.
      */
-    public static class CachePackageNameParser extends PackageParser {
-        @Override
-        public byte[] toCacheEntry(ParsedPackage pkg) {
-            return ("cache_" + pkg.getPackageName()).getBytes(StandardCharsets.UTF_8);
+    public static class CachePackageNameParser extends PackageParser2 {
+
+        CachePackageNameParser(String[] separateProcesses, boolean onlyCoreApps,
+                DisplayMetrics displayMetrics, @Nullable File cacheDir,
+                PackageParser2.Callback callback) {
+            super(separateProcesses, onlyCoreApps, displayMetrics, cacheDir, callback);
+            if (cacheDir != null) {
+                setCacheDir(cacheDir);
+            }
         }
 
-        @Override
-        public ParsedPackage fromCacheEntry(byte[] cacheEntry) {
-            return PackageImpl.forParsing(new String(cacheEntry, StandardCharsets.UTF_8))
-                    .hideAsParsed();
+        void setCacheDir(@NonNull File cacheDir) {
+            this.mCacher = new PackageCacher(cacheDir) {
+                @Override
+                public byte[] toCacheEntry(ParsedPackage pkg) {
+                    return ("cache_" + pkg.getPackageName()).getBytes(StandardCharsets.UTF_8);
+                }
+
+                @Override
+                public ParsedPackage fromCacheEntry(byte[] cacheEntry) {
+                    return ((ParsedPackage) PackageImpl.forTesting(
+                            new String(cacheEntry, StandardCharsets.UTF_8))
+                            .hideAsParsed());
+                }
+            };
         }
     }
 
+    private static PackageSetting mockPkgSetting(AndroidPackage pkg) {
+        return new PackageSetting(pkg.getPackageName(), pkg.getRealPackage(),
+                new File(pkg.getCodePath()), new File(pkg.getCodePath()), null,
+                pkg.getPrimaryCpuAbi(), pkg.getSecondaryCpuAbi(),
+                null, pkg.getVersionCode(),
+                PackageInfoUtils.appInfoFlags(pkg, null),
+                PackageInfoUtils.appInfoPrivateFlags(pkg, null),
+                pkg.getSharedUserLabel(), null, null, null);
+    }
+
     // NOTE: The equality assertions below are based on code autogenerated by IntelliJ.
 
     public static void assertPackagesEqual(AndroidPackage a, AndroidPackage b) {
@@ -232,7 +258,6 @@
         assertEquals(a.isBaseHardwareAccelerated(), b.isBaseHardwareAccelerated());
         assertEquals(a.getVersionCode(), b.getVersionCode());
         assertEquals(a.getSharedUserLabel(), b.getSharedUserLabel());
-        assertEquals(a.getPreferredOrder(), b.getPreferredOrder());
         assertEquals(a.getInstallLocation(), b.getInstallLocation());
         assertEquals(a.isCoreApp(), b.isCoreApp());
         assertEquals(a.isRequiredForAllUsers(), b.isRequiredForAllUsers());
@@ -249,9 +274,9 @@
         assertArrayEquals(a.getSplitFlags(), b.getSplitFlags());
 
         PackageInfo aInfo = PackageInfoUtils.generate(a, new int[]{}, 0, 0, 0,
-                Collections.emptySet(), new PackageUserState(), 0);
+                Collections.emptySet(), new PackageUserState(), 0, mockPkgSetting(a));
         PackageInfo bInfo = PackageInfoUtils.generate(b, new int[]{}, 0, 0, 0,
-                Collections.emptySet(), new PackageUserState(), 0);
+                Collections.emptySet(), new PackageUserState(), 0, mockPkgSetting(b));
         assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo);
 
         assertEquals(ArrayUtils.size(a.getPermissions()), ArrayUtils.size(b.getPermissions()));
@@ -298,15 +323,13 @@
         assertEquals(a.getLibraryNames(), b.getLibraryNames());
         assertEquals(a.getUsesLibraries(), b.getUsesLibraries());
         assertEquals(a.getUsesOptionalLibraries(), b.getUsesOptionalLibraries());
-        assertArrayEquals(a.getUsesLibraryFiles(), b.getUsesLibraryFiles());
         assertEquals(a.getOriginalPackages(), b.getOriginalPackages());
         assertEquals(a.getRealPackage(), b.getRealPackage());
         assertEquals(a.getAdoptPermissions(), b.getAdoptPermissions());
-        assertBundleApproximateEquals(a.getAppMetaData(), b.getAppMetaData());
+        assertBundleApproximateEquals(a.getMetaData(), b.getMetaData());
         assertEquals(a.getVersionName(), b.getVersionName());
         assertEquals(a.getSharedUserId(), b.getSharedUserId());
         assertArrayEquals(a.getSigningDetails().signatures, b.getSigningDetails().signatures);
-        assertArrayEquals(a.getLastPackageUsageTimeInMills(), b.getLastPackageUsageTimeInMills());
         assertEquals(a.getRestrictedAccountType(), b.getRestrictedAccountType());
         assertEquals(a.getRequiredAccountType(), b.getRequiredAccountType());
         assertEquals(a.getOverlayTarget(), b.getOverlayTarget());
@@ -317,7 +340,6 @@
         assertEquals(a.getSigningDetails().publicKeys, b.getSigningDetails().publicKeys);
         assertEquals(a.getUpgradeKeySets(), b.getUpgradeKeySets());
         assertEquals(a.getKeySetMapping(), b.getKeySetMapping());
-        assertEquals(a.getCpuAbiOverride(), b.getCpuAbiOverride());
         assertArrayEquals(a.getRestrictUpdateHash(), b.getRestrictUpdateHash());
     }
 
@@ -333,44 +355,42 @@
         assertEquals(a.toString(), b.toString());
     }
 
-    private static void assertComponentsEqual(ParsedComponent<?> a,
-            ParsedComponent<?> b) {
-        assertEquals(a.className, b.className);
+    private static void assertComponentsEqual(ParsedComponent a, ParsedComponent b) {
+        assertEquals(a.getName(), b.getName());
         assertBundleApproximateEquals(a.getMetaData(), b.getMetaData());
         assertEquals(a.getComponentName(), b.getComponentName());
 
-        if (a.intents != null && b.intents != null) {
-            assertEquals(a.intents.size(), b.intents.size());
-        } else if (a.intents == null || b.intents == null) {
+        if (a.getIntents() != null && b.getIntents() != null) {
+            assertEquals(a.getIntents().size(), b.getIntents().size());
+        } else if (a.getIntents() == null || b.getIntents() == null) {
             return;
         }
 
-        for (int i = 0; i < a.intents.size(); ++i) {
-            ParsedIntentInfo aIntent = a.intents.get(i);
-            ParsedIntentInfo bIntent = b.intents.get(i);
+        for (int i = 0; i < a.getIntents().size(); ++i) {
+            ParsedIntentInfo aIntent = a.getIntents().get(i);
+            ParsedIntentInfo bIntent = b.getIntents().get(i);
 
-            assertEquals(aIntent.hasDefault, bIntent.hasDefault);
-            assertEquals(aIntent.labelRes, bIntent.labelRes);
-            assertEquals(aIntent.nonLocalizedLabel, bIntent.nonLocalizedLabel);
-            assertEquals(aIntent.icon, bIntent.icon);
+            assertEquals(aIntent.isHasDefault(), bIntent.isHasDefault());
+            assertEquals(aIntent.getLabelRes(), bIntent.getLabelRes());
+            assertEquals(aIntent.getNonLocalizedLabel(), bIntent.getNonLocalizedLabel());
+            assertEquals(aIntent.getIcon(), bIntent.getIcon());
         }
     }
 
-    private static void assertPermissionsEqual(ParsedPermission a,
-            ParsedPermission b) {
+    private static void assertPermissionsEqual(ParsedPermission a, ParsedPermission b) {
         assertComponentsEqual(a, b);
-        assertEquals(a.tree, b.tree);
+        assertEquals(a.isTree(), b.isTree());
 
         // Verify basic flags in PermissionInfo to make sure they're consistent. We don't perform
         // a full structural equality here because the code that serializes them isn't parser
         // specific and is tested elsewhere.
         assertEquals(a.getProtection(), b.getProtection());
         assertEquals(a.getGroup(), b.getGroup());
-        assertEquals(a.flags, b.flags);
+        assertEquals(a.getFlags(), b.getFlags());
 
-        if (a.parsedPermissionGroup != null && b.parsedPermissionGroup != null) {
-            assertPermissionGroupsEqual(a.parsedPermissionGroup, b.parsedPermissionGroup);
-        } else if (a.parsedPermissionGroup != null || b.parsedPermissionGroup != null) {
+        if (a.getParsedPermissionGroup() != null && b.getParsedPermissionGroup() != null) {
+            assertPermissionGroupsEqual(a.getParsedPermissionGroup(), b.getParsedPermissionGroup());
+        } else if (a.getParsedPermissionGroup() != null || b.getParsedPermissionGroup() != null) {
             throw new AssertionError();
         }
     }
@@ -382,6 +402,8 @@
         // Sanity check for InstrumentationInfo.
         assertEquals(a.getTargetPackage(), b.getTargetPackage());
         assertEquals(a.getTargetProcesses(), b.getTargetProcesses());
+        assertEquals(a.isHandleProfiling(), b.isHandleProfiling());
+        assertEquals(a.isFunctionalTest(), b.isFunctionalTest());
     }
 
     private static void assertServicesEqual(
@@ -393,10 +415,10 @@
         assertComponentsEqual(a, b);
 
         // Sanity check for ServiceInfo.
-        ServiceInfo aInfo = PackageInfoUtils.generateServiceInfo(aPkg, a, 0, new PackageUserState(),
-                0);
-        ServiceInfo bInfo = PackageInfoUtils.generateServiceInfo(bPkg, b, 0, new PackageUserState(),
-                0);
+        ServiceInfo aInfo = PackageInfoUtils.generateServiceInfo(aPkg, a, 0,
+                new PackageUserState(), 0, mockPkgSetting(aPkg));
+        ServiceInfo bInfo = PackageInfoUtils.generateServiceInfo(bPkg, b, 0,
+                new PackageUserState(), 0, mockPkgSetting(bPkg));
         assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo);
         assertEquals(a.getName(), b.getName());
     }
@@ -411,9 +433,9 @@
 
         // Sanity check for ProviderInfo
         ProviderInfo aInfo = PackageInfoUtils.generateProviderInfo(aPkg, a, 0,
-                new PackageUserState(), 0);
+                new PackageUserState(), 0, mockPkgSetting(aPkg));
         ProviderInfo bInfo = PackageInfoUtils.generateProviderInfo(bPkg, b, 0,
-                new PackageUserState(), 0);
+                new PackageUserState(), 0, mockPkgSetting(bPkg));
         assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo);
         assertEquals(a.getName(), b.getName());
     }
@@ -428,9 +450,9 @@
 
         // Sanity check for ActivityInfo.
         ActivityInfo aInfo = PackageInfoUtils.generateActivityInfo(aPkg, a, 0,
-                new PackageUserState(), 0);
+                new PackageUserState(), 0, mockPkgSetting(aPkg));
         ActivityInfo bInfo = PackageInfoUtils.generateActivityInfo(bPkg, b, 0,
-                new PackageUserState(), 0);
+                new PackageUserState(), 0, mockPkgSetting(bPkg));
         assertApplicationInfoEqual(aInfo.applicationInfo, bInfo.applicationInfo);
         assertEquals(a.getName(), b.getName());
     }
@@ -441,7 +463,7 @@
 
         // Sanity check for PermissionGroupInfo.
         assertEquals(a.getName(), b.getName());
-        assertEquals(a.descriptionRes, b.descriptionRes);
+        assertEquals(a.getDescriptionRes(), b.getDescriptionRes());
     }
 
     private static void assertApplicationInfoEqual(ApplicationInfo a, ApplicationInfo that) {
@@ -494,12 +516,11 @@
         bundle.putString("key", "value");
 
         ParsedPermission permission = new ParsedPermission();
-        permission.parsedPermissionGroup = new ParsedPermissionGroup();
+        permission.setParsedPermissionGroup(new ParsedPermissionGroup());
 
-        pkg.setBaseRevisionCode(100)
+        ((ParsedPackage) pkg.setBaseRevisionCode(100)
                 .setBaseHardwareAccelerated(true)
                 .setSharedUserLabel(100)
-                .setPreferredOrder(100)
                 .setInstallLocation(100)
                 .setRequiredForAllUsers(true)
                 .asSplit(
@@ -510,7 +531,6 @@
                 )
                 .setUse32BitAbi(true)
                 .setVolumeUuid("foo3")
-                .setCodePath("foo4")
                 .addPermission(permission)
                 .addPermissionGroup(new ParsedPermissionGroup())
                 .addActivity(new ParsedActivity())
@@ -532,7 +552,7 @@
                 .addOriginalPackage("foo14")
                 .setRealPackage("foo15")
                 .addAdoptPermission("foo16")
-                .setAppMetaData(bundle)
+                .setMetaData(bundle)
                 .setVersionName("foo17")
                 .setSharedUserId("foo18")
                 .setSigningDetails(
@@ -547,8 +567,7 @@
                 .setOverlayTarget("foo21")
                 .setOverlayPriority(100)
                 .setUpgradeKeySets(new ArraySet<>())
-                .addPreferredActivityFilter(
-                        new ComponentParseUtils.ParsedActivityIntentInfo("foo", "className"))
+                .addPreferredActivityFilter("className", new ParsedIntentInfo())
                 .addConfigPreference(new ConfigurationInfo())
                 .addReqFeature(new FeatureInfo())
                 .addFeatureGroup(new FeatureGroupInfo())
@@ -559,19 +578,14 @@
                 .setOverlayTargetName("foo26")
                 .setVisibleToInstantApps(true)
                 .setSplitHasCode(0, true)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setBaseCodePath("foo5")
+                .setCodePath("foo4")
                 .setVersionCode(100)
-                .setCpuAbiOverride("foo22")
                 .setRestrictUpdateHash(new byte[16])
                 .setVersionCodeMajor(100)
                 .setCoreApp(true)
-                .hideAsFinal()
-                .mutate()
-                .setUsesLibraryInfos(Arrays.asList(
-                        new SharedLibraryInfo(null, null, null, null, 0L, 0, null, null, null)
-                ))
-                .setUsesLibraryFiles(new String[]{"foo13"});
+                .hideAsFinal();
     }
 
     private static void assertAllFieldsExist(ParsedPackage pkg) throws Exception {
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 338d5fa..d12ea894 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -18,10 +18,13 @@
 
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
-import android.content.pm.parsing.AndroidPackage;
+import android.util.ArraySet;
 import android.util.SparseArray;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+
 import java.io.File;
+import java.util.Map;
 
 public class PackageSettingBuilder {
     private String mName;
@@ -38,6 +41,7 @@
     private int mSharedUserId;
     private String[] mUsesStaticLibraries;
     private long[] mUsesStaticLibrariesVersions;
+    private Map<String, ArraySet<String>> mMimeGroups;
     private String mVolumeUuid;
     private SparseArray<PackageUserState> mUserStates = new SparseArray<>();
     private AndroidPackage mPkg;
@@ -127,6 +131,11 @@
         return this;
     }
 
+    public PackageSettingBuilder setMimeGroups(Map<String, ArraySet<String>> mimeGroups) {
+        this.mMimeGroups = mimeGroups;
+        return this;
+    }
+
     public PackageSettingBuilder setVolumeUuid(String volumeUuid) {
         this.mVolumeUuid = volumeUuid;
         return this;
@@ -156,7 +165,7 @@
                 new File(mCodePath), new File(mResourcePath),
                 mLegacyNativeLibraryPathString, mPrimaryCpuAbiString, mSecondaryCpuAbiString,
                 mCpuAbiOverrideString, mPVersionCode, mPkgFlags, mPrivateFlags, mSharedUserId,
-                mUsesStaticLibraries, mUsesStaticLibrariesVersions);
+                mUsesStaticLibraries, mUsesStaticLibrariesVersions, mMimeGroups);
         packageSetting.signatures = mSigningDetails != null
                 ? new PackageSignatures(mSigningDetails)
                 : new PackageSignatures();
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
index 04e769d..55bc681 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSignaturesTest.java
@@ -467,7 +467,7 @@
         File appPath = new File("/data/app/app");
         PackageSetting result = new PackageSetting("test.app", null, appPath, appPath,
                 "/data/app/app", null, null, null,
-                1, 940097092, 0, 0 /*userId*/, null, null);
+                1, 940097092, 0, 0 /*userId*/, null, null, null /*mimeGroups*/);
         return result;
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
index da5986f7..9d3ac17 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ParallelPackageParserTest.java
@@ -17,11 +17,14 @@
 package com.android.server.pm;
 
 import android.content.pm.PackageParser;
-import android.content.pm.parsing.ParsedPackage;
+import android.platform.test.annotations.Presubmit;
 import android.util.Log;
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import junit.framework.Assert;
 
 import org.junit.Before;
@@ -36,6 +39,7 @@
 /**
  * Tests for {@link ParallelPackageParser}
  */
+@Presubmit
 @RunWith(AndroidJUnit4.class)
 public class ParallelPackageParserTest {
     private static final String TAG = ParallelPackageParserTest.class.getSimpleName();
@@ -44,7 +48,7 @@
 
     @Before
     public void setUp() {
-        mParser = new TestParallelPackageParser(new PackageParser(),
+        mParser = new TestParallelPackageParser(new PackageParser2(null, false, null, null, null),
                 ParallelPackageParser.makeExecutorService());
     }
 
@@ -72,7 +76,7 @@
 
     private class TestParallelPackageParser extends ParallelPackageParser {
 
-        TestParallelPackageParser(PackageParser packageParser, ExecutorService executorService) {
+        TestParallelPackageParser(PackageParser2 packageParser, ExecutorService executorService) {
             super(packageParser, executorService);
         }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
index 30108c6..efc1c05 100644
--- a/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/SELinuxMMACTest.java
@@ -22,12 +22,13 @@
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.when;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
 import android.os.Build;
 import android.platform.test.annotations.Presubmit;
 
 import com.android.server.compat.PlatformCompat;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -79,9 +80,9 @@
     }
 
     private AndroidPackage makePackage(int targetSdkVersion) {
-        return PackageImpl.forParsing(PACKAGE_NAME)
+        return ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(targetSdkVersion)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
index 11f154b..12fb400 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanRequestBuilder.java
@@ -16,10 +16,13 @@
 
 package com.android.server.pm;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.UserHandle;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 class ScanRequestBuilder {
     private final ParsedPackage mPkg;
     private AndroidPackage mOldPkg;
@@ -32,6 +35,8 @@
     private int mScanFlags;
     private UserHandle mUser;
     private boolean mIsPlatformPackage;
+    @Nullable
+    private String mCpuAbiOverride;
 
     ScanRequestBuilder(ParsedPackage pkg) {
         this.mPkg = pkg;
@@ -97,10 +102,16 @@
         return this;
     }
 
+    @NonNull
+    public ScanRequestBuilder setCpuAbiOverride(@Nullable String cpuAbiOverride) {
+        this.mCpuAbiOverride = cpuAbiOverride;
+        return this;
+    }
+
     PackageManagerService.ScanRequest build() {
         return new PackageManagerService.ScanRequest(
                 mPkg, mSharedUserSetting, mOldPkg, mPkgSetting, mDisabledPkgSetting,
                 mOriginalPkgSetting, mRealPkgName, mParseFlags, mScanFlags, mIsPlatformPackage,
-                mUser);
+                mUser, mCpuAbiOverride);
     }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
index 583cf58..09f946d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java
@@ -42,9 +42,6 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.SharedLibraryInfo;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.PackageInfoUtils;
-import android.content.pm.parsing.ParsedPackage;
 import android.content.pm.parsing.ParsingPackage;
 import android.content.res.TypedArray;
 import android.os.Environment;
@@ -54,6 +51,10 @@
 import android.util.Pair;
 
 import com.android.server.compat.PlatformCompat;
+import com.android.server.pm.parsing.PackageInfoUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.hamcrest.BaseMatcher;
 import org.hamcrest.Description;
@@ -101,18 +102,18 @@
     @Before
     public void setupDefaultAbiBehavior() throws Exception {
         when(mMockPackageAbiHelper.derivePackageAbi(
-                any(ParsedPackage.class), nullable(String.class), anyBoolean()))
+                any(AndroidPackage.class), anyBoolean(), nullable(String.class), anyBoolean()))
                 .thenReturn(new Pair<>(
                         new PackageAbiHelper.Abis("derivedPrimary", "derivedSecondary"),
                         new PackageAbiHelper.NativeLibraryPaths(
                                 "derivedRootDir", true, "derivedNativeDir", "derivedNativeDir2")));
         when(mMockPackageAbiHelper.getNativeLibraryPaths(
-                any(ParsedPackage.class), any(File.class)))
+                any(AndroidPackage.class), any(PackageSetting.class), any(File.class)))
                 .thenReturn(new PackageAbiHelper.NativeLibraryPaths(
                         "getRootDir", true, "getNativeDir", "getNativeDir2"
                 ));
         when(mMockPackageAbiHelper.getBundledAppAbis(
-                any(ParsedPackage.class)))
+                any(AndroidPackage.class)))
                 .thenReturn(new PackageAbiHelper.Abis("bundledPrimary", "bundledSecondary"));
     }
 
@@ -223,10 +224,10 @@
 
     @Test
     public void installStaticSharedLibrary() throws Exception {
-        final ParsedPackage pkg = createBasicPackage("static.lib.pkg")
+        final ParsedPackage pkg = ((ParsedPackage) createBasicPackage("static.lib.pkg")
                 .setStaticSharedLibName("static.lib")
                 .setStaticSharedLibVersion(123L)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setPackageName("static.lib.pkg.123")
                 .setVersionCodeMajor(1)
                 .setVersionCode(234)
@@ -255,10 +256,11 @@
 
     @Test
     public void installDynamicLibraries() throws Exception {
-        final ParsedPackage pkg = createBasicPackage("dynamic.lib.pkg")
+        final ParsedPackage pkg = ((ParsedPackage) createBasicPackage(
+                "dynamic.lib.pkg")
                 .addLibraryName("liba")
                 .addLibraryName("libb")
-                .hideAsParsed()
+                .hideAsParsed())
                 .setVersionCodeMajor(1)
                 .setVersionCode(234)
                 .setBaseCodePath("/some/path.apk")
@@ -304,9 +306,9 @@
                         .setVolumeUuid("someUuid")
                         .build();
 
-        final ParsedPackage basicPackage = createBasicPackage(DUMMY_PACKAGE_NAME)
-                .hideAsParsed()
-                .setApplicationVolumeUuid(UUID_TWO.toString());
+        final ParsedPackage basicPackage = ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME)
+                .setVolumeUuid(UUID_TWO.toString())
+                .hideAsParsed());
 
 
         final PackageManagerService.ScanResult scanResult = executeScan(
@@ -321,9 +323,8 @@
                 createBasicPackageSettingBuilder(DUMMY_PACKAGE_NAME).build();
 
         final ParsedPackage basicPackage =
-                createBasicPackage(DUMMY_PACKAGE_NAME)
-                        .hideAsParsed()
-                        .setCpuAbiOverride("testOverride");
+                ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME)
+                        .hideAsParsed());
 
 
         final PackageManagerService.ScanResult scanResult = executeScan(new ScanRequestBuilder(
@@ -341,7 +342,7 @@
                 createBasicPackageSettingBuilder("original.package").build();
 
         final ParsedPackage basicPackage =
-                createBasicPackage(DUMMY_PACKAGE_NAME)
+                (ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME)
                         .hideAsParsed();
 
 
@@ -411,8 +412,9 @@
 
         final PackageManagerService.ScanResult scanResult = executeScan(scanRequest);
 
-        assertThat(scanResult.request.parsedPackage.getFlags(),
-                hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP));
+        int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.request.parsedPackage,
+                scanResult.pkgSetting);
+        assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_UPDATED_SYSTEM_APP));
     }
 
     @Test
@@ -426,14 +428,15 @@
                 true /*isUnderFactoryTest*/,
                 System.currentTimeMillis());
 
-        assertThat(scanResult.request.parsedPackage.getFlags(),
-                hasFlag(ApplicationInfo.FLAG_FACTORY_TEST));
+        int appInfoFlags = PackageInfoUtils.appInfoFlags(scanResult.request.parsedPackage,
+                scanResult.request.pkgSetting);
+        assertThat(appInfoFlags, hasFlag(ApplicationInfo.FLAG_FACTORY_TEST));
     }
 
     @Test
     public void scanSystemApp_isOrphanedTrue() throws Exception {
-        final ParsedPackage pkg = createBasicPackage(DUMMY_PACKAGE_NAME)
-                .hideAsParsed()
+        final ParsedPackage pkg = ((ParsedPackage) createBasicPackage(DUMMY_PACKAGE_NAME)
+                .hideAsParsed())
                 .setSystem(true);
 
         final PackageManagerService.ScanRequest scanRequest =
@@ -474,10 +477,6 @@
                 System.currentTimeMillis());
     }
 
-    private static String createResourcePath(String packageName) {
-        return "/data/app/" + packageName + "-randompath/base.apk";
-    }
-
     private static String createCodePath(String packageName) {
         return "/data/app/" + packageName + "-randompath";
     }
@@ -486,11 +485,11 @@
         return new PackageSettingBuilder()
                 .setName(packageName)
                 .setCodePath(createCodePath(packageName))
-                .setResourcePath(createResourcePath(packageName));
+                .setResourcePath(createCodePath(packageName));
     }
 
     private static ScanRequestBuilder createBasicScanRequestBuilder(ParsingPackage pkg) {
-        return new ScanRequestBuilder(pkg.hideAsParsed())
+        return new ScanRequestBuilder((ParsedPackage) pkg.hideAsParsed())
                 .setUser(UserHandle.of(0));
     }
 
@@ -501,16 +500,15 @@
 
     private static ParsingPackage createBasicPackage(String packageName) {
         // TODO(b/135203078): Make this use PackageImpl.forParsing and separate the steps
-        return new PackageImpl(packageName, null, mock(TypedArray.class), false)
-                .setCodePath("/data/tmp/randompath")
-                .setApplicationInfoCodePath(createCodePath(packageName))
-                .setApplicationInfoResourcePath(createResourcePath(packageName))
-                .setApplicationVolumeUuid(UUID_ONE.toString())
-                .setBaseCodePath("/data/tmp/randompath/base.apk")
+        return (ParsingPackage) ((ParsedPackage) new PackageImpl(packageName,
+                "/data/tmp/randompath/base.apk", createCodePath(packageName),
+                mock(TypedArray.class), false)
+                .setVolumeUuid(UUID_ONE.toString())
                 .addUsesStaticLibrary("some.static.library")
                 .addUsesStaticLibraryVersion(234L)
                 .addUsesStaticLibrary("some.other.static.library")
                 .addUsesStaticLibraryVersion(456L)
+                .hideAsParsed())
                 .setNativeLibraryRootDir("/data/tmp/randompath/base.apk:/lib")
                 .setVersionCodeMajor(1)
                 .setVersionCode(2345);
@@ -524,7 +522,7 @@
         assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting);
 
         final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
-                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0);
+                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0, pkgSetting);
         assertBasicApplicationInfo(scanResult, applicationInfo);
     }
 
@@ -537,7 +535,7 @@
         assertThat(pkgSetting.usesStaticLibrariesVersions, is(new long[]{234L, 456L}));
         assertThat(pkgSetting.pkg, is(scanResult.request.parsedPackage));
         assertThat(pkgSetting.codePath, is(new File(createCodePath(packageName))));
-        assertThat(pkgSetting.resourcePath, is(new File(createResourcePath(packageName))));
+        assertThat(pkgSetting.resourcePath, is(new File(createCodePath(packageName))));
         assertThat(pkgSetting.versionCode, is(PackageInfo.composeLongVersionCode(1, 2345)));
     }
 
@@ -559,7 +557,7 @@
     private static void assertAbiAndPathssDerived(PackageManagerService.ScanResult scanResult) {
         PackageSetting pkgSetting = scanResult.pkgSetting;
         final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
-                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0);
+                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0, pkgSetting);
         assertThat(applicationInfo.primaryCpuAbi, is("derivedPrimary"));
         assertThat(applicationInfo.secondaryCpuAbi, is("derivedSecondary"));
 
@@ -573,7 +571,7 @@
     private static void assertPathsNotDerived(PackageManagerService.ScanResult scanResult) {
         PackageSetting pkgSetting = scanResult.pkgSetting;
         final ApplicationInfo applicationInfo = PackageInfoUtils.generateApplicationInfo(
-                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0);
+                pkgSetting.pkg, 0, pkgSetting.readUserState(0), 0, pkgSetting);
         assertThat(applicationInfo.nativeLibraryRootDir, is("getRootDir"));
         assertThat(pkgSetting.legacyNativeLibraryPathString, is("getRootDir"));
         assertThat(applicationInfo.nativeLibraryRootRequiresIsa, is(true));
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 2936bdd..56460fb 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -379,6 +379,113 @@
         });
     }
 
+    public void testPushDynamicShortcut() {
+
+        setCaller(CALLING_PACKAGE_1, USER_0);
+
+        final ShortcutInfo s1 = makeShortcut("s1");
+        final ShortcutInfo s2 = makeShortcut("s2");
+        final ShortcutInfo s3 = makeShortcut("s3");
+        final ShortcutInfo s4 = makeShortcut("s4");
+
+        final ShortcutInfo s10 = makeShortcut("s10");
+        final ShortcutInfo s11 = makeShortcut("s11");
+        final ShortcutInfo s12 = makeShortcut("s12");
+        final ShortcutInfo s13 = makeShortcut("s13");
+        final ShortcutInfo s14 = makeShortcut("s14");
+
+        // Test push as first shortcut
+        mManager.pushDynamicShortcut(s1);
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()), "s1");
+        assertEquals(0, getCallerShortcut("s1").getRank());
+
+        // Test push when other shortcuts exist
+        assertTrue(mManager.setDynamicShortcuts(list(s1, s2)));
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()), "s1", "s2");
+        mManager.pushDynamicShortcut(s3);
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
+                "s1", "s2", "s3");
+        assertEquals(0, getCallerShortcut("s3").getRank());
+        assertEquals(1, getCallerShortcut("s1").getRank());
+        assertEquals(2, getCallerShortcut("s2").getRank());
+
+        mInjectedCurrentTimeMillis += INTERVAL; // reset
+
+        // Push with set rank
+        s4.setRank(2);
+        mManager.pushDynamicShortcut(s4);
+        assertEquals(2, getCallerShortcut("s4").getRank());
+        assertEquals(3, getCallerShortcut("s2").getRank());
+
+        // Push existing shortcut with set rank
+        final ShortcutInfo s4_2 = makeShortcut("s4");
+        s4_2.setRank(4);
+        mManager.pushDynamicShortcut(s4_2);
+        assertEquals(2, getCallerShortcut("s2").getRank());
+        assertEquals(3, getCallerShortcut("s4").getRank());
+
+        mInjectedCurrentTimeMillis += INTERVAL; // reset
+
+        // Test push as last
+        assertTrue(mManager.addDynamicShortcuts(makeShortcuts("s5", "s6", "s7", "s8", "s9")));
+        mManager.pushDynamicShortcut(s10);
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
+                "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10");
+        assertEquals(0, getCallerShortcut("s10").getRank());
+        assertEquals(1, getCallerShortcut("s5").getRank());
+        assertEquals(6, getCallerShortcut("s3").getRank());
+        assertEquals(7, getCallerShortcut("s1").getRank());
+        assertEquals(8, getCallerShortcut("s2").getRank());
+        assertEquals(9, getCallerShortcut("s4").getRank());
+
+        // Push when max has already reached
+        mManager.pushDynamicShortcut(s11);
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
+                "s1", "s2", "s3", "s5", "s6", "s7", "s8", "s9", "s10", "s11");
+        assertEquals(0, getCallerShortcut("s11").getRank());
+        assertEquals(1, getCallerShortcut("s10").getRank());
+        assertEquals(9, getCallerShortcut("s2").getRank());
+
+        mInjectedCurrentTimeMillis += INTERVAL; // reset
+
+        // Push with different activity
+        s12.setActivity(makeComponent(ShortcutActivity2.class));
+        mManager.pushDynamicShortcut(s12);
+        assertEquals(makeComponent(ShortcutActivity2.class),
+                getCallerShortcut("s12").getActivity());
+        assertEquals(0, getCallerShortcut("s12").getRank());
+
+        // Push to update shortcut with different activity
+        final ShortcutInfo s1_2 = makeShortcut("s1");
+        s1_2.setActivity(makeComponent(ShortcutActivity2.class));
+        s1_2.setRank(1);
+        mManager.pushDynamicShortcut(s1_2);
+        assertEquals(0, getCallerShortcut("s12").getRank());
+        assertEquals(1, getCallerShortcut("s1").getRank());
+        assertEquals(0, getCallerShortcut("s11").getRank());
+        assertEquals(1, getCallerShortcut("s10").getRank());
+        assertEquals(7, getCallerShortcut("s3").getRank());
+        assertEquals(8, getCallerShortcut("s2").getRank());
+
+        mInjectedCurrentTimeMillis += INTERVAL; // reset
+
+        // Test push when dropped shortcut is cached
+        s13.setLongLived();
+        s13.setRank(100);
+        mManager.pushDynamicShortcut(s13);
+        assertEquals(9, getCallerShortcut("s13").getRank());
+        runWithCaller(LAUNCHER_1, USER_0, () -> {
+            mLauncherApps.cacheShortcuts(CALLING_PACKAGE_1, list("s13"), HANDLE_USER_0);
+        });
+
+        mManager.pushDynamicShortcut(s14);
+        assertShortcutIds(assertAllNotKeyFieldsOnly(mManager.getDynamicShortcuts()),
+                "s1", "s2", "s3", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "s12", "s14");
+        // Verify s13 stayed as cached
+        assertShortcutIds(mManager.getShortcuts(ShortcutManager.FLAG_MATCH_CACHED),
+                "s13");
+    }
+
     public void testUnlimitedCalls() {
         setCaller(CALLING_PACKAGE_1, USER_0);
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 118c540..bec37e9 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -812,7 +812,7 @@
                 "android", 0, mUserManager.getPrimaryUser().getUserHandle())
                 .getSystemService(Context.USER_SERVICE);
 
-        List<UserHandle> profiles = um.getUserProfiles(false);
+        List<UserHandle> profiles = um.getAllProfiles();
         assertThat(profiles.size()).isEqualTo(2);
         assertThat(profiles.get(0).equals(userProfile.getUserHandle())
                 || profiles.get(1).equals(userProfile.getUserHandle())).isTrue();
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
index 3db832b..ce21099 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserSystemPackageInstallerTest.java
@@ -39,8 +39,6 @@
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.os.UserManager;
@@ -56,6 +54,9 @@
 
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.After;
 import org.junit.Before;
@@ -252,14 +253,14 @@
         final Set<String> userWhitelist = new ArraySet<>();
         userWhitelist.add(packageName1);
 
-        final AndroidPackage pkg1 = PackageImpl.forParsing(packageName1)
-                .hideAsParsed().hideAsFinal();
-        final AndroidPackage pkg2 = PackageImpl.forParsing(packageName2)
-                .hideAsParsed().hideAsFinal();
-        final AndroidPackage pkg3 = PackageImpl.forParsing(packageName3)
-                .hideAsParsed().hideAsFinal();
-        final AndroidPackage pkg4 = PackageImpl.forParsing(packageName4)
-                .hideAsParsed().hideAsFinal();
+        final AndroidPackage pkg1 = ((ParsedPackage) PackageImpl.forTesting(packageName1)
+                .hideAsParsed()).hideAsFinal();
+        final AndroidPackage pkg2 = ((ParsedPackage) PackageImpl.forTesting(packageName2)
+                .hideAsParsed()).hideAsFinal();
+        final AndroidPackage pkg3 = ((ParsedPackage) PackageImpl.forTesting(packageName3)
+                .hideAsParsed()).hideAsFinal();
+        final AndroidPackage pkg4 = ((ParsedPackage) PackageImpl.forTesting(packageName4)
+                .hideAsParsed()).hideAsFinal();
 
         // No implicit whitelist, so only install pkg1.
         boolean implicit = false;
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
index f5e5e2a..d69e1b8 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexManagerTests.java
@@ -532,6 +532,61 @@
         assertHasDclInfo(mBarUser0, mBarUser0, secondaries);
     }
 
+    @Test
+    public void testPrimaryAndSecondaryDexLoad() {
+        // Foo loads both primary and secondary dexes
+        List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+        List<String> fooDexes = new ArrayList<>(mFooUser0.getBaseAndSplitDexPaths());
+        int primaryCount = fooDexes.size();
+        fooDexes.addAll(fooSecondaries);
+
+        notifyDexLoad(mFooUser0, fooDexes, mUser0);
+
+        PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+        assertIsUsedByOtherApps(mFooUser0, pui, false);
+        assertEquals(fooSecondaries.size(), pui.getDexUseInfoMap().size());
+
+        // Below we want to verify that the secondary dex files within fooDexes have been correctly
+        // reported and their class loader contexts were correctly recorded.
+        //
+        // In order to achieve this we first use DexoptUtils.processContextForDexLoad to compute the
+        // class loader contexts for all the dex files.
+        String[] allClassLoaderContexts = DexoptUtils.processContextForDexLoad(
+                Arrays.asList(mFooUser0.mClassLoader),
+                Arrays.asList(String.join(File.pathSeparator, fooDexes)));
+        // Next we filter out the class loader contexts corresponding to non-secondary dex files.
+        String[] secondaryClassLoaderContexts = Arrays.copyOfRange(allClassLoaderContexts,
+                primaryCount, allClassLoaderContexts.length);
+        assertSecondaryUse(mFooUser0, pui, fooSecondaries, /*isUsedByOtherApps*/false, mUser0,
+                secondaryClassLoaderContexts);
+
+        assertHasDclInfo(mFooUser0, mFooUser0, fooSecondaries);
+    }
+
+    @Test
+    public void testNotifySecondary_withSharedLibrary() {
+        // Foo loads its own secondary files.
+        List<String> fooSecondaries = mFooUser0.getSecondaryDexPaths();
+
+        String contextSuffix = "{PCL[/system/framework/org.apache.http.legacy.jar]}";
+        String[] expectedContexts = DexoptUtils.processContextForDexLoad(
+                Arrays.asList(mFooUser0.mClassLoader),
+                Arrays.asList(String.join(File.pathSeparator, fooSecondaries)));
+        for (int i = 0; i < expectedContexts.length; i++) {
+            expectedContexts[i] += contextSuffix;
+        }
+
+        notifyDexLoad(mFooUser0, fooSecondaries, expectedContexts, mUser0);
+
+        PackageUseInfo pui = getPackageUseInfo(mFooUser0);
+        assertIsUsedByOtherApps(mFooUser0, pui, false);
+        assertEquals(fooSecondaries.size(), pui.getDexUseInfoMap().size());
+        assertSecondaryUse(mFooUser0, pui, fooSecondaries, /*isUsedByOtherApps*/false, mUser0,
+                expectedContexts);
+
+        assertHasDclInfo(mFooUser0, mFooUser0, fooSecondaries);
+    }
+
     private void assertSecondaryUse(TestData testData, PackageUseInfo pui,
             List<String> secondaries, boolean isUsedByOtherApps, int ownerUserId,
             String[] expectedContexts) {
@@ -572,17 +627,43 @@
         // By default, assume a single class loader in the chain.
         // This makes writing tests much easier.
         List<String> classLoaders = Arrays.asList(testData.mClassLoader);
-        List<String> classPaths = (dexPaths == null)
-                                  ? Arrays.asList((String) null)
-                                  : Arrays.asList(String.join(File.pathSeparator, dexPaths));
+        List<String> classPaths = dexPaths != null
+                ? Arrays.<String>asList(String.join(File.pathSeparator, dexPaths)) : null;
         notifyDexLoad(testData, classLoaders, classPaths, loaderUserId);
     }
 
     private void notifyDexLoad(TestData testData, List<String> classLoaders,
             List<String> classPaths, int loaderUserId) {
+        String[] classLoaderContexts = computeClassLoaderContexts(classLoaders, classPaths);
         // We call the internal function so any exceptions thrown cause test failures.
-        mDexManager.notifyDexLoadInternal(testData.mPackageInfo.applicationInfo, classLoaders,
-                classPaths, testData.mLoaderIsa, loaderUserId);
+        List<String> dexPaths = classPaths != null
+                ? Arrays.asList(classPaths.get(0).split(File.pathSeparator)) : Arrays.asList();
+        notifyDexLoad(testData, dexPaths, classLoaderContexts, loaderUserId);
+    }
+
+    private void notifyDexLoad(TestData testData, List<String> dexPaths,
+            String[] classLoaderContexts, int loaderUserId) {
+        assertTrue(dexPaths.size() == classLoaderContexts.length);
+        HashMap<String, String> dexPathMapping = new HashMap<>(dexPaths.size());
+        for (int i = 0; i < dexPaths.size(); i++) {
+            dexPathMapping.put(dexPaths.get(i), classLoaderContexts != null
+                    ? classLoaderContexts[i] : PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT);
+        }
+        mDexManager.notifyDexLoadInternal(testData.mPackageInfo.applicationInfo, dexPathMapping,
+                testData.mLoaderIsa, loaderUserId);
+    }
+
+    private String[] computeClassLoaderContexts(List<String> classLoaders,
+            List<String> classPaths) {
+        if (classPaths == null) {
+            return new String[0];
+        }
+        String[] results = DexoptUtils.processContextForDexLoad(classLoaders, classPaths);
+        if (results == null) {
+            results = new String[classPaths.get(0).split(File.pathSeparator).length];
+            Arrays.fill(results, PackageDexUsage.UNSUPPORTED_CLASS_LOADER_CONTEXT);
+        }
+        return results;
     }
 
     private PackageUseInfo getPackageUseInfo(TestData testData) {
diff --git a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
similarity index 86%
rename from core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
rename to services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
index 1e0bfb0..f87f68d 100644
--- a/core/tests/coretests/src/android/content/pm/dex/DexMetadataHelperTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexMetadataHelperTest.java
@@ -1,5 +1,5 @@
-/**
- * Copyright (C) 2018 The Android Open Source Project
+/*
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm.dex;
+package com.android.server.pm.dex;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -27,14 +27,17 @@
 import android.content.pm.PackageParser.ApkLite;
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
-import android.content.pm.parsing.ParsedPackage;
+import android.content.pm.dex.DexMetadataHelper;
 import android.os.FileUtils;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.frameworks.coretests.R;
+import com.android.frameworks.servicestests.R;
+import com.android.server.pm.parsing.PackageParser2;
+import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -90,13 +93,17 @@
         return outFile;
     }
 
+    private PackageParser2 makeParser() {
+        return new PackageParser2(null, false, null, null, null);
+    }
+
     @Test
     public void testParsePackageWithDmFileValid() throws IOException, PackageParserException {
         copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
         createDexMetadataFile("install_split_base.apk");
-        ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false);
+        ParsedPackage pkg = makeParser().parsePackage(mTmpDir, 0 /* flags */, false);
 
-        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
         assertEquals(1, packageDexMetadata.size());
         String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath());
         assertNotNull(baseDexMetadata);
@@ -110,9 +117,9 @@
         copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
         createDexMetadataFile("install_split_base.apk");
         createDexMetadataFile("install_split_feature_a.apk");
-        ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false);
+        ParsedPackage pkg = makeParser().parsePackage(mTmpDir, 0 /* flags */, false);
 
-        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
         assertEquals(2, packageDexMetadata.size());
         String baseDexMetadata = packageDexMetadata.get(pkg.getBaseCodePath());
         assertNotNull(baseDexMetadata);
@@ -129,9 +136,9 @@
         copyApkToToTmpDir("install_split_base.apk", R.raw.install_split_base);
         copyApkToToTmpDir("install_split_feature_a.apk", R.raw.install_split_feature_a);
         createDexMetadataFile("install_split_feature_a.apk");
-        ParsedPackage pkg = new PackageParser().parseParsedPackage(mTmpDir, 0 /* flags */, false);
+        ParsedPackage pkg = makeParser().parsePackage(mTmpDir, 0 /* flags */, false);
 
-        Map<String, String> packageDexMetadata = DexMetadataHelper.getPackageDexMetadata(pkg);
+        Map<String, String> packageDexMetadata = AndroidPackageUtils.getPackageDexMetadata(pkg);
         assertEquals(1, packageDexMetadata.size());
 
         String splitDexMetadata = packageDexMetadata.get(pkg.getSplitCodePaths()[0]);
@@ -145,9 +152,8 @@
         File invalidDmFile = new File(mTmpDir, "install_split_base.dm");
         Files.createFile(invalidDmFile.toPath());
         try {
-            ParsedPackage pkg = new PackageParser()
-                    .parseParsedPackage(mTmpDir, 0 /* flags */, false);
-            DexMetadataHelper.validatePackageDexMetadata(pkg);
+            ParsedPackage pkg = makeParser().parsePackage(mTmpDir, 0 /* flags */, false);
+            AndroidPackageUtils.validatePackageDexMetadata(pkg);
         } catch (PackageParserException e) {
             assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
         }
@@ -163,9 +169,8 @@
         Files.createFile(invalidDmFile.toPath());
 
         try {
-            ParsedPackage pkg = new PackageParser()
-                    .parseParsedPackage(mTmpDir, 0 /* flags */, false);
-            DexMetadataHelper.validatePackageDexMetadata(pkg);
+            ParsedPackage pkg = makeParser().parsePackage(mTmpDir, 0 /* flags */, false);
+            AndroidPackageUtils.validatePackageDexMetadata(pkg);
         } catch (PackageParserException e) {
             assertEquals(e.error, PackageManager.INSTALL_FAILED_BAD_DEX_METADATA);
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
index 66a4946..3846be0 100644
--- a/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/dex/DexoptUtilsTest.java
@@ -23,15 +23,16 @@
 import static org.junit.Assert.fail;
 
 import android.content.pm.SharedLibraryInfo;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
 import android.content.pm.parsing.ParsingPackage;
 import android.util.SparseArray;
 
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import dalvik.system.DelegateLastClassLoader;
 import dalvik.system.DexClassLoader;
 import dalvik.system.PathClassLoader;
@@ -61,7 +62,8 @@
     private TestData createMockApplicationInfo(String baseClassLoader, boolean addSplits,
             boolean addSplitDependencies, boolean isolatedSplitLoading) {
         String codeDir = "/data/app/mock.android.com";
-        ParsingPackage parsingPackage = PackageImpl.forParsing("mock.android.com")
+        ParsingPackage parsingPackage = PackageImpl.forTesting("mock.android.com",
+                codeDir + "/base.dex")
                 .setClassLoaderName(baseClassLoader);
 
         parsingPackage.setIsolatedSplitLoading(isolatedSplitLoading);
@@ -122,8 +124,7 @@
                     .setSplitClassLoaderName(7, null);
         }
 
-        ParsedPackage parsedPackage = parsingPackage.hideAsParsed()
-                .setBaseCodePath(codeDir + "/base.dex");
+        ParsedPackage parsedPackage = (ParsedPackage) parsingPackage.hideAsParsed();
 
         TestData data = new TestData();
         data.pkg = parsedPackage.hideAsFinal();
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
index 27d02e1..0a32e4a 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageInfoFlagBehaviorTest.kt
@@ -20,9 +20,10 @@
 import android.content.pm.PackageInfo
 import android.content.pm.PackageManager
 import android.content.pm.PackageParser
-import android.content.pm.parsing.AndroidPackage
+import android.platform.test.annotations.Presubmit
 import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.appInfo
 import com.android.server.pm.parsing.AndroidPackageInfoFlagBehaviorTest.Companion.Param.Companion.pkgInfo
+import com.android.server.pm.parsing.pkg.AndroidPackage
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Test
@@ -36,6 +37,7 @@
  * This test has to be updated manually whenever the info generation behavior changes, since
  * there's no single place where flag -> field is defined besides this test.
  */
+@Presubmit
 @RunWith(Parameterized::class)
 class AndroidPackageInfoFlagBehaviorTest : AndroidPackageParsingTestBase() {
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
index 925af7f..191c038 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingEquivalenceTest.kt
@@ -17,6 +17,7 @@
 package com.android.server.pm.parsing
 
 import android.content.pm.PackageManager
+import android.platform.test.annotations.Presubmit
 import com.google.common.truth.Truth.assertWithMessage
 import org.junit.Test
 
@@ -24,6 +25,7 @@
  * Collects APKs from the device and verifies that the new parsing behavior outputs
  * the same exposed Info object as the old parsing logic.
  */
+@Presubmit
 class AndroidPackageParsingEquivalenceTest : AndroidPackageParsingTestBase() {
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index afd6e18..ca6b296 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -27,26 +27,27 @@
 import android.content.pm.PackageUserState
 import android.content.pm.PermissionInfo
 import android.content.pm.ProviderInfo
-import android.content.pm.parsing.AndroidPackage
-import android.content.pm.parsing.PackageImpl
-import android.content.pm.parsing.PackageInfoUtils
 import android.os.Debug
 import android.os.Environment
 import android.util.SparseArray
 import androidx.test.platform.app.InstrumentationRegistry
+import com.android.server.om.mockThrowOnUnmocked
+import com.android.server.om.whenever
 import com.android.server.pm.PackageManagerService
+import com.android.server.pm.PackageSetting
+import com.android.server.pm.parsing.pkg.AndroidPackage
+import com.android.server.pm.pkg.PackageStateUnserialized
 import org.junit.BeforeClass
 import org.mockito.Mockito
+import org.mockito.Mockito.anyInt
+import org.mockito.Mockito.mock
 import java.io.File
 
 open class AndroidPackageParsingTestBase {
 
     companion object {
 
-        /**
-         * By default, don't parse all APKs on device, only the framework one.
-         * Toggle this manually if working on package parsing.
-         */
+        // TODO(chiuwinson): Enable in separate change to fail all presubmit builds and fix errors
         private const val VERIFY_ALL_APKS = false
 
         /** For auditing memory usage differences */
@@ -59,6 +60,11 @@
             setCallback { true }
         }
 
+        protected val packageParser2 = PackageParser2(null, false, context.resources.displayMetrics,
+                null, object : PackageParser2.Callback() {
+            override fun hasFeature(feature: String?) = true
+        })
+
         /**
          * It would be difficult to mock all possibilities, so just use the APKs on device.
          * Unfortunately, this means the device must be bootable to verify potentially
@@ -80,9 +86,9 @@
                             .toList()
                 }
 
-        private val dummyState = Mockito.mock(PackageUserState::class.java).apply {
+        private val dummyUserState = mock(PackageUserState::class.java).apply {
             installed = true
-            Mockito.`when`(isAvailable(Mockito.anyInt())).thenReturn(true)
+            Mockito.`when`(isAvailable(anyInt())).thenReturn(true)
         }
 
         lateinit var oldPackages: List<PackageParser.Package>
@@ -98,7 +104,7 @@
             }
 
             this.newPackages = apks.map {
-                packageParser.parseParsedPackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
+                packageParser2.parsePackage(it, PackageParser.PARSE_IS_SYSTEM_DIR, false)
             }
 
             if (DUMP_HPROF_TO_EXTERNAL) {
@@ -111,19 +117,27 @@
         }
 
         fun oldAppInfo(pkg: PackageParser.Package, flags: Int = 0): ApplicationInfo? {
-            return PackageParser.generateApplicationInfo(pkg, flags, dummyState, 0)
+            return PackageParser.generateApplicationInfo(pkg, flags, dummyUserState, 0)
         }
 
         fun newAppInfo(pkg: AndroidPackage, flags: Int = 0): ApplicationInfo? {
-            return PackageInfoUtils.generateApplicationInfo(pkg, flags, dummyState, 0)
+            return PackageInfoUtils.generateApplicationInfo(pkg, flags, dummyUserState, 0,
+                    mockPkgSetting(pkg))
         }
 
         fun oldPackageInfo(pkg: PackageParser.Package, flags: Int = 0): PackageInfo? {
-            return PackageParser.generatePackageInfo(pkg, intArrayOf(), flags, 5, 6, emptySet(), dummyState)
+            return PackageParser.generatePackageInfo(pkg, intArrayOf(), flags, 5, 6, emptySet(),
+                    dummyUserState)
         }
 
         fun newPackageInfo(pkg: AndroidPackage, flags: Int = 0): PackageInfo? {
-            return PackageInfoUtils.generate(pkg, intArrayOf(), flags, 5, 6, emptySet(), dummyState, 0)
+            return PackageInfoUtils.generate(pkg, intArrayOf(), flags, 5, 6, emptySet(),
+                    dummyUserState, 0, mockPkgSetting(pkg))
+        }
+
+        private fun mockPkgSetting(aPkg: AndroidPackage) = mockThrowOnUnmocked<PackageSetting> {
+            this.pkg = aPkg
+            whenever(pkgState) { PackageStateUnserialized() }
         }
     }
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
similarity index 87%
rename from core/tests/coretests/src/android/content/pm/PackageParserTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
index dfd762b..66cd466 100644
--- a/core/tests/coretests/src/android/content/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/PackageParserLegacyCoreTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2016 The Android Open Source Project
+ * 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.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package com.android.server.pm.parsing;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
@@ -24,20 +24,26 @@
 
 import android.apex.ApexInfo;
 import android.content.Context;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
-import android.content.pm.parsing.ComponentParseUtils.ParsedPermission;
-import android.content.pm.parsing.ParsedPackage;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageParser;
+import android.content.pm.PermissionInfo;
+import android.content.pm.parsing.component.ParsedComponent;
+import android.content.pm.parsing.component.ParsedPermission;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.FileUtils;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
-import com.android.frameworks.coretests.R;
+import com.android.frameworks.servicestests.R;
 import com.android.internal.util.ArrayUtils;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -46,9 +52,19 @@
 import java.io.InputStream;
 import java.util.function.Function;
 
+/**
+ * {@link ParsedPackage} was moved to the server, so this test moved along with it.
+ *
+ * This should be eventually refactored to a comprehensive parsing test, combined with its
+ * server variant in the parent package.
+ *
+ * TODO(b/135203078): Remove this test and replicate the cases in the actual com.android.server
+ *  variant.
+ */
+@Presubmit
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class PackageParserTest {
+public class PackageParserLegacyCoreTest {
     private static final String RELEASED = null;
     private static final String OLDER_PRE_RELEASE = "A";
     private static final String PRE_RELEASE = "B";
@@ -86,6 +102,10 @@
         }
     }
 
+    private PackageParser2 makeParser() {
+        return new PackageParser2(null, false, null, null, null);
+    }
+
     @Test
     public void testComputeMinSdkVersion_preReleasePlatform() {
         // Do allow older release minSdkVersion on pre-release platform.
@@ -338,7 +358,7 @@
         try {
             outFile = copyRawResourceToFile(apkFileName, apkResourceId);
             return converter.apply(
-                    new PackageParser().parseParsedPackage(outFile, 0 /* flags */, false));
+                    makeParser().parsePackage(outFile, 0 /* flags */, false));
         } finally {
             if (outFile != null) {
                 outFile.delete();
@@ -349,9 +369,9 @@
     /**
      * Asserts basic properties about a component.
      */
-    private void assertComponent(String className, int numIntents, ParsedComponent<?> component) {
-        assertEquals(className, component.className);
-        assertEquals(numIntents, component.intents.size());
+    private void assertComponent(String className, int numIntents, ParsedComponent component) {
+        assertEquals(className, component.getName());
+        assertEquals(numIntents, component.getIntents().size());
     }
 
     /**
@@ -405,7 +425,7 @@
     @Test
     public void testPackageWithComponents_cached() throws Exception {
         checkPackageWithComponents(p ->
-                PackageParser.fromCacheEntryStatic(PackageParser.toCacheEntryStatic(p)));
+                PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p)));
     }
 
     private void checkPackageWithComponents(
@@ -421,21 +441,11 @@
                 "com.android.frameworks.coretests.install_complete_package_info.test_permission",
                 PermissionInfo.PROTECTION_NORMAL, p.getPermissions().get(0));
 
-        // Hidden "app details" activity is added to every package.
-        boolean foundAppDetailsActivity = false;
-        for (int i = 0; i < ArrayUtils.size(p.getActivities()); i++) {
-            if (p.getActivities().get(i).className.equals(
-                    PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) {
-                foundAppDetailsActivity = true;
-                p.getActivities().remove(i);
-                break;
-            }
-        }
-        assertTrue("Did not find app details activity", foundAppDetailsActivity);
+        findAndRemoveAppDetailsActivity(p);
 
         assertOneComponentOfEachType("com.android.frameworks.coretests.Test%s", p);
 
-        assertMetadata(p.getAppMetaData(),
+        assertMetadata(p.getMetaData(),
                 "key1", "value1",
                 "key2", "this_is_app");
         assertMetadata(p.getActivities().get(0).getMetaData(),
@@ -450,6 +460,52 @@
         assertMetadata(p.getProviders().get(0).getMetaData(),
                 "key1", "value1",
                 "key2", "this_is_provider");
+
+    }
+
+    private void findAndRemoveAppDetailsActivity(ParsedPackage p) {
+        // Hidden "app details" activity is added to every package.
+        boolean foundAppDetailsActivity = false;
+        for (int i = 0; i < ArrayUtils.size(p.getActivities()); i++) {
+            if (p.getActivities().get(i).getClassName().equals(
+                    PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) {
+                foundAppDetailsActivity = true;
+                p.getActivities().remove(i);
+                break;
+            }
+        }
+        assertTrue("Did not find app details activity", foundAppDetailsActivity);
+    }
+
+    @Test
+    public void testPackageWithIntentFilters_no_cache() throws Exception {
+        checkPackageWithIntentFilters(p -> p);
+    }
+
+    @Test
+    public void testPackageWithIntentFilters_cached() throws Exception {
+        checkPackageWithIntentFilters(p ->
+                PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p)));
+    }
+
+    private void checkPackageWithIntentFilters(
+            Function<ParsedPackage, ParsedPackage> converter) throws Exception {
+        ParsedPackage p = parsePackage(
+                "install_intent_filters.apk", R.raw.install_intent_filters,
+                converter);
+        String packageName = "com.android.frameworks.servicestests.install_intent_filters";
+
+        assertEquals(packageName, p.getPackageName());
+
+        findAndRemoveAppDetailsActivity(p);
+
+        assertEquals("Expected exactly one activity", 1, p.getActivities().size());
+        assertEquals("Expected exactly one intent filter",
+                1, p.getActivities().get(0).getIntents().size());
+        assertEquals("Expected exactly one mime group in intent filter",
+                1, p.getActivities().get(0).getIntents().get(0).countMimeGroups());
+        assertTrue("Did not find expected mime group 'mime_group_1'",
+                p.getActivities().get(0).getIntents().get(0).hasMimeGroup("mime_group_1"));
     }
 
     @Test
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
similarity index 67%
rename from core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
index 21479c0..6b60042 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidHidlUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidHidlUpdaterTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,25 +14,28 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_HIDL_MANAGER;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
 /**
- * Test for {@link AndroidHidlUpdater}
+ * Test for {@link com.android.server.pm.parsing.library.AndroidHidlUpdater}
  */
+@Presubmit
 @SmallTest
 @RunWith(JUnit4.class)
 public class AndroidHidlUpdaterTest extends PackageSharedLibraryUpdaterTest {
@@ -41,13 +44,13 @@
 
     @Test
     public void targeted_at_P() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // no change, not system
@@ -56,17 +59,17 @@
 
     @Test
     public void targeted_at_P_system() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true);
 
         // Should add both HIDL libraries
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(ANDROID_HIDL_MANAGER)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true)
                 .hideAsFinal();
 
@@ -75,15 +78,15 @@
 
     @Test
     public void targeted_at_P_not_empty_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // no change, not system
@@ -92,20 +95,20 @@
 
     @Test
     public void targeted_at_P_not_empty_usesLibraries_system() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true);
 
         // The hidl jars should be added at the start of the list because it
         // is not on the bootclasspath and the package targets pre-P.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(ANDROID_HIDL_MANAGER)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true)
                 .hideAsFinal();
 
@@ -114,15 +117,15 @@
 
     @Test
     public void targeted_at_P_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(ANDROID_HIDL_MANAGER)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // Libraries are removed because they are not available for non-system apps
@@ -131,18 +134,18 @@
 
     @Test
     public void targeted_at_P_in_usesLibraries_system() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(ANDROID_HIDL_MANAGER)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true);
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.P)
                 .addUsesLibrary(ANDROID_HIDL_MANAGER)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .setSystem(true)
                 .hideAsFinal();
 
@@ -153,15 +156,15 @@
 
     @Test
     public void in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // Dependency is removed, it is not available.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // Libraries are removed because they are not available for apps targeting Q+
@@ -170,15 +173,15 @@
 
     @Test
     public void in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_HIDL_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // Dependency is removed, it is not available.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // Libraries are removed because they are not available for apps targeting Q+
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
similarity index 68%
rename from core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
index 65ae219..f536052 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestBaseUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestBaseUpdaterTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -14,42 +14,44 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
 
-import android.content.pm.OptionalClassRunner;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 /**
  * Test for {@link AndroidTestBaseUpdater}
  */
+@Presubmit
 @SmallTest
 @RunWith(OptionalClassRunner.class)
-@OptionalClassRunner.OptionalClass("android.content.pm.parsing.library.AndroidTestBaseUpdater")
+@OptionalClassRunner.OptionalClass("com.android.server.pm.parsing.library.AndroidTestBaseUpdater")
 public class AndroidTestBaseUpdaterTest extends PackageSharedLibraryUpdaterTest {
 
     private static final String OTHER_LIBRARY = "other.library";
 
     @Test
     public void targeted_at_Q() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // Should add org.apache.http.legacy.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -57,18 +59,18 @@
 
     @Test
     public void targeted_at_Q_not_empty_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // The org.apache.http.legacy jar should be added at the start of the list because it
         // is not on the bootclasspath and the package targets pre-Q.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesLibrary(ANDROID_TEST_BASE)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -76,15 +78,15 @@
 
     @Test
     public void targeted_at_Q_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because although org.apache.http.legacy has been removed from
@@ -94,15 +96,15 @@
 
     @Test
     public void targeted_at_Q_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.Q)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because although org.apache.http.legacy has been removed from
@@ -112,15 +114,15 @@
 
     @Test
     public void in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because the package explicitly requests org.apache.http.legacy
@@ -130,15 +132,15 @@
 
     @Test
     public void in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because the package explicitly requests org.apache.http.legacy
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
similarity index 68%
rename from core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
index 38755b9..77197e3 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/AndroidTestRunnerSplitUpdaterTest.java
@@ -14,19 +14,21 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
-import android.content.pm.parsing.library.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.library.PackageBackwardCompatibility.AndroidTestRunnerSplitUpdater;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -34,22 +36,23 @@
 /**
  * Test for {@link AndroidTestRunnerSplitUpdater}
  */
+@Presubmit
 @SmallTest
 @RunWith(JUnit4.class)
 public class AndroidTestRunnerSplitUpdaterTest extends PackageSharedLibraryUpdaterTest {
 
     @Test
     public void android_test_runner_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_TEST_RUNNER)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_TEST_MOCK)
                 .addUsesOptionalLibrary(ANDROID_TEST_RUNNER)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -57,17 +60,17 @@
 
     @Test
     public void android_test_runner_in_usesLibraries_android_test_mock_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_RUNNER)
                 .addUsesOptionalLibrary(ANDROID_TEST_MOCK)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_RUNNER)
                 .addUsesOptionalLibrary(ANDROID_TEST_MOCK)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
diff --git a/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OptionalClassRunner.java
similarity index 97%
rename from core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/OptionalClassRunner.java
index 05db8ee..0ebfe1a 100644
--- a/core/tests/coretests/src/android/content/pm/OptionalClassRunner.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OptionalClassRunner.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2018 The Android Open Source Project
+ * Copyright (C) 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.content.pm;
+package com.android.server.pm.parsing.library;
 
 import org.junit.Assume;
 import org.junit.runner.Description;
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
similarity index 68%
rename from core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
index 4c7899b..95b8d3f 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/OrgApacheHttpLegacyUpdaterTest.java
@@ -14,42 +14,44 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
-import android.content.pm.OptionalClassRunner;
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 /**
- * Test for {@link OrgApacheHttpLegacyUpdater}
+ * Test for {@link com.android.server.pm.parsing.library.OrgApacheHttpLegacyUpdater}
  */
+@Presubmit
 @SmallTest
 @RunWith(OptionalClassRunner.class)
-@OptionalClassRunner.OptionalClass("android.content.pm.parsing.library.OrgApacheHttpLegacyUpdater")
+@OptionalClassRunner.OptionalClass("com.android.server.pm.parsing.library.OrgApacheHttpLegacyUpdater")
 public class OrgApacheHttpLegacyUpdaterTest extends PackageSharedLibraryUpdaterTest {
 
     private static final String OTHER_LIBRARY = "other.library";
 
     @Test
     public void targeted_at_O() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // Should add org.apache.http.legacy.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -57,18 +59,18 @@
 
     @Test
     public void targeted_at_O_not_empty_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // The org.apache.http.legacy jar should be added at the start of the list because it
         // is not on the bootclasspath and the package targets pre-P.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -76,15 +78,15 @@
 
     @Test
     public void targeted_at_O_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because although org.apache.http.legacy has been removed from
@@ -94,15 +96,15 @@
 
     @Test
     public void targeted_at_O_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because although org.apache.http.legacy has been removed from
@@ -112,15 +114,15 @@
 
     @Test
     public void in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because the package explicitly requests org.apache.http.legacy
@@ -130,15 +132,15 @@
 
     @Test
     public void in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change is required because the package explicitly requests org.apache.http.legacy
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
similarity index 71%
rename from core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
index 00d468d..ca38860 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/PackageBackwardCompatibilityTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageBackwardCompatibilityTest.java
@@ -14,40 +14,43 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
-import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_MOCK;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_RUNNER;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
 import android.content.pm.parsing.ParsingPackage;
-import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Assume;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
+@Presubmit
 @SmallTest
 @RunWith(JUnit4.class)
 public class PackageBackwardCompatibilityTest extends PackageSharedLibraryUpdaterTest {
 
     @Test
     public void null_usesLibraries_and_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -74,12 +77,12 @@
      */
     @Test
     public void targeted_at_O() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        ParsingPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsingPackage after = PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .setTargetSdkVersion(Build.VERSION_CODES.O);
 
@@ -88,7 +91,7 @@
         }
         after.addUsesLibrary(ORG_APACHE_HTTP_LEGACY);
 
-        checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal());
+        checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
     }
 
     /**
@@ -105,16 +108,16 @@
                         + ANDROID_TEST_BASE + " is on the bootclasspath",
                 PackageBackwardCompatibility.bootClassPathContainsATB());
 
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -129,12 +132,12 @@
      */
     @Test
     public void android_test_runner_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_RUNNER)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        ParsingPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsingPackage after = PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT);
         if (!PackageBackwardCompatibility.bootClassPathContainsATB()) {
             after.addUsesLibrary(ANDROID_TEST_BASE);
@@ -142,7 +145,7 @@
         after.addUsesLibrary(ANDROID_TEST_MOCK);
         after.addUsesLibrary(ANDROID_TEST_RUNNER);
 
-        checkBackwardsCompatibility(before, after.hideAsParsed().hideAsFinal());
+        checkBackwardsCompatibility(before, ((ParsedPackage) after.hideAsParsed()).hideAsFinal());
     }
 
     private void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after) {
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
similarity index 88%
rename from core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
index e7a80e1a..a71572f 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/PackageSharedLibraryUpdaterTest.java
@@ -14,12 +14,12 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
 import static org.junit.Assert.assertEquals;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.ParsedPackage;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
 
 import java.util.function.Supplier;
 
@@ -32,7 +32,7 @@
 
     static void checkBackwardsCompatibility(ParsedPackage before, AndroidPackage after,
             Supplier<PackageSharedLibraryUpdater> updaterSupplier) {
-        updaterSupplier.get().updatePackage(before);
+        updaterSupplier.get().updatePackage(before, false);
         check(before.hideAsFinal(), after);
     }
 
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
similarity index 69%
rename from core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
index fd3ba2b..1122490 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryAndroidTestBaseLibraryTest.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ANDROID_TEST_BASE;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
-import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryAndroidTestBaseLibrary;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -33,6 +35,7 @@
 /**
  * Test for {@link RemoveUnnecessaryAndroidTestBaseLibrary}
  */
+@Presubmit
 @SmallTest
 @RunWith(JUnit4.class)
 public class RemoveUnnecessaryAndroidTestBaseLibraryTest
@@ -42,13 +45,13 @@
 
     @Test
     public void targeted_at_O() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change required.
@@ -57,15 +60,15 @@
 
     @Test
     public void targeted_at_O_not_empty_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change required.
@@ -74,16 +77,16 @@
 
     @Test
     public void targeted_at_O_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -91,16 +94,16 @@
 
     @Test
     public void targeted_at_O_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -108,14 +111,14 @@
 
     @Test
     public void in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .addUsesLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
-                .hideAsParsed()
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -123,16 +126,16 @@
 
     @Test
     public void in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -140,17 +143,17 @@
 
     @Test
     public void in_bothLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ANDROID_TEST_BASE)
                 .addUsesOptionalLibrary(ANDROID_TEST_BASE)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // android.test.base should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
diff --git a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
similarity index 68%
rename from core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
rename to services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
index d3494d9..3cc8475 100644
--- a/core/tests/coretests/src/android/content/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/library/RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest.java
@@ -14,18 +14,20 @@
  * limitations under the License.
  */
 
-package android.content.pm.parsing.library;
+package com.android.server.pm.parsing.library;
 
-import static android.content.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
+import static com.android.server.pm.parsing.library.SharedLibraryNames.ORG_APACHE_HTTP_LEGACY;
 
-import android.content.pm.parsing.AndroidPackage;
-import android.content.pm.parsing.PackageImpl;
-import android.content.pm.parsing.ParsedPackage;
-import android.content.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
 import android.os.Build;
+import android.platform.test.annotations.Presubmit;
 
 import androidx.test.filters.SmallTest;
 
+import com.android.server.pm.parsing.library.PackageBackwardCompatibility.RemoveUnnecessaryOrgApacheHttpLegacyLibrary;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
+import com.android.server.pm.parsing.pkg.PackageImpl;
+import com.android.server.pm.parsing.pkg.ParsedPackage;
+
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
@@ -33,6 +35,7 @@
 /**
  * Test for {@link RemoveUnnecessaryOrgApacheHttpLegacyLibrary}
  */
+@Presubmit
 @SmallTest
 @RunWith(JUnit4.class)
 public class RemoveUnnecessaryOrgApacheHttpLegacyLibraryTest
@@ -42,13 +45,13 @@
 
     @Test
     public void targeted_at_O() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change required.
@@ -57,15 +60,15 @@
 
     @Test
     public void targeted_at_O_not_empty_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed();
+                .hideAsParsed());
 
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(OTHER_LIBRARY)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         // No change required.
@@ -74,16 +77,16 @@
 
     @Test
     public void targeted_at_O_in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // org.apache.http.legacy should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -91,16 +94,16 @@
 
     @Test
     public void targeted_at_O_in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // org.apache.http.legacy should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.O)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -108,15 +111,16 @@
 
     @Test
     public void in_usesLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // org.apache.http.legacy should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
-                .hideAsParsed()
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -124,15 +128,16 @@
 
     @Test
     public void in_usesOptionalLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // org.apache.http.legacy should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
-                .hideAsParsed()
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
+                .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
@@ -140,17 +145,17 @@
 
     @Test
     public void in_bothLibraries() {
-        ParsedPackage before = PackageImpl.forParsing(PACKAGE_NAME)
+        ParsedPackage before = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
                 .addUsesLibrary(ORG_APACHE_HTTP_LEGACY)
                 .addUsesOptionalLibrary(ORG_APACHE_HTTP_LEGACY)
-                .hideAsParsed();
+                .hideAsParsed());
 
         // org.apache.http.legacy should be removed from the libraries because it is provided
         // on the bootclasspath and providing both increases start up cost unnecessarily.
-        AndroidPackage after = PackageImpl.forParsing(PACKAGE_NAME)
+        AndroidPackage after = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME)
                 .setTargetSdkVersion(Build.VERSION_CODES.CUR_DEVELOPMENT)
-                .hideAsParsed()
+                .hideAsParsed())
                 .hideAsFinal();
 
         checkBackwardsCompatibility(before, after);
diff --git a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
index ccf7ca9..624cb83 100644
--- a/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/power/ThermalManagerServiceTest.java
@@ -28,10 +28,12 @@
 import static org.mockito.Mockito.when;
 
 import android.content.Context;
+import android.hardware.thermal.V2_0.TemperatureThreshold;
 import android.os.CoolingDevice;
 import android.os.IBinder;
 import android.os.IPowerManager;
 import android.os.IThermalEventListener;
+import android.os.IThermalService;
 import android.os.IThermalStatusListener;
 import android.os.PowerManager;
 import android.os.RemoteException;
@@ -72,6 +74,8 @@
     @Mock
     private IPowerManager mIPowerManagerMock;
     @Mock
+    private IThermalService mIThermalServiceMock;
+    @Mock
     private IThermalEventListener mEventListener1;
     @Mock
     private IThermalEventListener mEventListener2;
@@ -133,6 +137,12 @@
         }
 
         @Override
+        protected List<TemperatureThreshold> getTemperatureThresholds(boolean shouldFilter,
+                int type) {
+            return new ArrayList<>();
+        }
+
+        @Override
         protected boolean connectToHal() {
             return true;
         }
@@ -153,7 +163,7 @@
     public void setUp() throws RemoteException {
         MockitoAnnotations.initMocks(this);
         mFakeHal = new ThermalHalFake();
-        mPowerManager = new PowerManager(mContext, mIPowerManagerMock, null);
+        mPowerManager = new PowerManager(mContext, mIPowerManagerMock, mIThermalServiceMock, null);
         when(mContext.getSystemServiceName(PowerManager.class)).thenReturn(Context.POWER_SERVICE);
         when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
         resetListenerMock();
diff --git a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
index d5cdbeb..035a2f1 100644
--- a/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/recoverysystem/RecoverySystemServiceTest.java
@@ -36,6 +36,7 @@
 import android.os.Handler;
 import android.os.IPowerManager;
 import android.os.IRecoverySystemProgressListener;
+import android.os.IThermalService;
 import android.os.Looper;
 import android.os.PowerManager;
 
@@ -62,6 +63,7 @@
     private RecoverySystemService.UncryptSocket mUncryptSocket;
     private Context mContext;
     private IPowerManager mIPowerManager;
+    private IThermalService mIThermalService;
     private FileWriter mUncryptUpdateFileWriter;
     private LockSettingsInternal mLockSettingsInternal;
 
@@ -77,8 +79,9 @@
 
         Looper looper = InstrumentationRegistry.getContext().getMainLooper();
         mIPowerManager = mock(IPowerManager.class);
+        mIThermalService = mock(IThermalService.class);
         PowerManager powerManager = new PowerManager(mock(Context.class), mIPowerManager,
-                new Handler(looper));
+                mIThermalService, new Handler(looper));
 
         mRecoverySystemService = new RecoverySystemServiceTestable(mContext, mSystemProperties,
                 powerManager, mUncryptUpdateFileWriter, mUncryptSocket, mLockSettingsInternal);
diff --git a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
index 9e57763..0fdffd5 100644
--- a/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
+++ b/services/tests/servicestests/src/com/android/server/usage/AppStandbyControllerTests.java
@@ -66,6 +66,7 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArraySet;
 import android.view.Display;
@@ -83,6 +84,7 @@
 import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -101,6 +103,8 @@
     private static final int UID_EXEMPTED_1 = 10001;
     private static final int USER_ID = 0;
     private static final int USER_ID2 = 10;
+    private static final UserHandle USER_HANDLE_USER2 = new UserHandle(USER_ID2);
+    private static final int USER_ID3 = 11;
 
     private static final String PACKAGE_UNKNOWN = "com.example.unknown";
 
@@ -150,6 +154,8 @@
         boolean mDisplayOn;
         DisplayManager.DisplayListener mDisplayListener;
         String mBoundWidgetPackage = PACKAGE_EXEMPTED_1;
+        int[] mRunningUsers = new int[] {USER_ID};
+        List<UserHandle> mCrossProfileTargets = Collections.emptyList();
 
         MyInjector(Context context, Looper looper) {
             super(context, looper);
@@ -212,7 +218,7 @@
 
         @Override
         int[] getRunningUserIds() {
-            return new int[] {USER_ID};
+            return mRunningUsers;
         }
 
         @Override
@@ -248,6 +254,11 @@
             return false;
         }
 
+        @Override
+        public List<UserHandle> getValidCrossProfileTargets(String pkg, int userId) {
+            return mCrossProfileTargets;
+        }
+
         // Internal methods
 
         void setDisplayOn(boolean on) {
@@ -379,10 +390,15 @@
     }
 
     private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket) {
+        assertTimeout(controller, elapsedTime, bucket, USER_ID);
+    }
+
+    private void assertTimeout(AppStandbyController controller, long elapsedTime, int bucket,
+            int userId) {
         mInjector.mElapsedRealtime = elapsedTime;
-        controller.checkIdleStates(USER_ID);
+        controller.checkIdleStates(userId);
         assertEquals(bucket,
-                controller.getAppStandbyBucket(PACKAGE_1, USER_ID, mInjector.mElapsedRealtime,
+                controller.getAppStandbyBucket(PACKAGE_1, userId, mInjector.mElapsedRealtime,
                         false));
     }
 
@@ -397,7 +413,11 @@
     }
 
     private int getStandbyBucket(AppStandbyController controller, String packageName) {
-        return controller.getAppStandbyBucket(packageName, USER_ID, mInjector.mElapsedRealtime,
+        return getStandbyBucket(USER_ID, controller, packageName);
+    }
+
+    private int getStandbyBucket(int userId, AppStandbyController controller, String packageName) {
+        return controller.getAppStandbyBucket(packageName, userId, mInjector.mElapsedRealtime,
                 true);
     }
 
@@ -1012,6 +1032,29 @@
         assertIsNotActiveAdmin(ADMIN_PKG2, USER_ID);
     }
 
+    @Test
+    public void testUserInteraction_CrossProfile() throws Exception {
+        mInjector.mRunningUsers = new int[] {USER_ID, USER_ID2, USER_ID3};
+        mInjector.mCrossProfileTargets = Arrays.asList(USER_HANDLE_USER2);
+        reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+        assertEquals("Cross profile connected package bucket should be elevated on usage",
+                STANDBY_BUCKET_ACTIVE, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
+        assertEquals("Not Cross profile connected package bucket should not be elevated on usage",
+                STANDBY_BUCKET_NEVER, getStandbyBucket(USER_ID3, mController, PACKAGE_1));
+
+        assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID);
+        assertTimeout(mController, WORKING_SET_THRESHOLD - 1, STANDBY_BUCKET_ACTIVE, USER_ID2);
+
+        assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID);
+        assertTimeout(mController, WORKING_SET_THRESHOLD + 1, STANDBY_BUCKET_WORKING_SET, USER_ID2);
+
+        mInjector.mCrossProfileTargets = Collections.emptyList();
+        reportEvent(mController, USER_INTERACTION, 0, PACKAGE_1);
+        assertEquals("No longer cross profile connected package bucket should not be "
+                        + "elevated on usage",
+                STANDBY_BUCKET_WORKING_SET, getStandbyBucket(USER_ID2, mController, PACKAGE_1));
+    }
+
     private String getAdminAppsStr(int userId) {
         return getAdminAppsStr(userId, mController.getActiveAdminAppsForTest(userId));
     }
diff --git a/services/tests/uiservicestests/Android.bp b/services/tests/uiservicestests/Android.bp
index 3f0cda3..b7199f7 100644
--- a/services/tests/uiservicestests/Android.bp
+++ b/services/tests/uiservicestests/Android.bp
@@ -29,6 +29,7 @@
     libs: [
         "android.test.runner",
         "android.test.base",
+        "android.test.mock",
     ],
 
     dxflags: ["--multi-dex"],
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index e5ffb4d..d0283f7 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -359,8 +359,12 @@
 
     @Before
     public void setUp() throws Exception {
+        // Shell permisssions will override permissions of our app, so add all necessary permissions
+        // fo this test here:
         InstrumentationRegistry.getInstrumentation().getUiAutomation().adoptShellPermissionIdentity(
-                "android.permission.WRITE_DEVICE_CONFIG", "android.permission.READ_DEVICE_CONFIG");
+                "android.permission.WRITE_DEVICE_CONFIG",
+                "android.permission.READ_DEVICE_CONFIG",
+                "android.permission.READ_CONTACTS");
 
         MockitoAnnotations.initMocks(this);
 
@@ -2902,21 +2906,21 @@
     }
 
     @Test
-    public void testSetListenerAccess_doesNothingOnLowRam() throws Exception {
+    public void testSetListenerAccess_onLowRam() throws Exception {
         when(mActivityManager.isLowRamDevice()).thenReturn(true);
         ComponentName c = ComponentName.unflattenFromString("package/Component");
         mBinderService.setNotificationListenerAccessGranted(c, true);
 
-        verify(mListeners, never()).setPackageOrComponentEnabled(
+        verify(mListeners).setPackageOrComponentEnabled(
                 anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mConditionProviders, never()).setPackageOrComponentEnabled(
+        verify(mConditionProviders).setPackageOrComponentEnabled(
                 anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mAssistants, never()).setPackageOrComponentEnabled(
-                any(), anyInt(), anyBoolean(), anyBoolean());
+        verify(mAssistants).migrateToXml();
+        verify(mAssistants).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
-    public void testSetAssistantAccess_doesNothingOnLowRam() throws Exception {
+    public void testSetAssistantAccess_onLowRam() throws Exception {
         when(mActivityManager.isLowRamDevice()).thenReturn(true);
         ComponentName c = ComponentName.unflattenFromString("package/Component");
         List<UserInfo> uis = new ArrayList<>();
@@ -2927,26 +2931,28 @@
 
         mBinderService.setNotificationAssistantAccessGranted(c, true);
 
-        verify(mListeners, never()).setPackageOrComponentEnabled(
+        verify(mListeners).migrateToXml();
+        verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+                anyInt());
+        verify(mConditionProviders).setPackageOrComponentEnabled(
                 anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mConditionProviders, never()).setPackageOrComponentEnabled(
-                anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mAssistants, never()).setPackageOrComponentEnabled(
-                any(), anyInt(), anyBoolean(), anyBoolean());
+        verify(mAssistants).migrateToXml();
+        verify(mAssistants).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
-    public void testSetDndAccess_doesNothingOnLowRam() throws Exception {
+    public void testSetDndAccess_onLowRam() throws Exception {
         when(mActivityManager.isLowRamDevice()).thenReturn(true);
         ComponentName c = ComponentName.unflattenFromString("package/Component");
         mBinderService.setNotificationPolicyAccessGranted(c.getPackageName(), true);
 
-        verify(mListeners, never()).setPackageOrComponentEnabled(
+        verify(mListeners).migrateToXml();
+        verify(mListeners).notifyNotificationChannelChanged(anyString(), any(), any(),
+                anyInt());
+        verify(mConditionProviders).setPackageOrComponentEnabled(
                 anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mConditionProviders, never()).setPackageOrComponentEnabled(
-                anyString(), anyInt(), anyBoolean(), anyBoolean());
-        verify(mAssistants, never()).setPackageOrComponentEnabled(
-                any(), anyInt(), anyBoolean(), anyBoolean());
+        verify(mAssistants).migrateToXml();
+        verify(mAssistants).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
@@ -3240,7 +3246,7 @@
                 new BufferedInputStream(new ByteArrayInputStream(upgradeXml.getBytes())),
                 false,
                 UserHandle.USER_ALL);
-        verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class));
+        verify(mSnoozeHelper, times(1)).readXml(any(XmlPullParser.class), anyLong());
     }
 
     @Test
@@ -4288,68 +4294,13 @@
     }
 
     @Test
-    public void testCanUseManagedServicesLowRamNoWatchNullPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
-        when(mActivityManager.isLowRamDevice()).thenReturn(true);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
-        assertEquals(false, mService.canUseManagedServices(null, 0, null));
+    public void testCanUseManagedServicesNullPkg() {
+        assertEquals(true, mService.canUseManagedServices(null, 0, null));
     }
 
-    @Test
-    public void testCanUseManagedServicesLowRamNoWatchValidPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
-        when(mActivityManager.isLowRamDevice()).thenReturn(true);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
-        assertEquals(true, mService.canUseManagedServices("b", 0, null));
-    }
 
     @Test
-    public void testCanUseManagedServicesLowRamNoWatchNoValidPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
-        when(mActivityManager.isLowRamDevice()).thenReturn(true);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
-        assertEquals(false, mService.canUseManagedServices("d", 0, null));
-    }
-
-    @Test
-    public void testCanUseManagedServicesLowRamWatchNoValidPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
-        when(mActivityManager.isLowRamDevice()).thenReturn(true);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
-        assertEquals(true, mService.canUseManagedServices("d", 0, null));
-    }
-
-    @Test
-    public void testCanUseManagedServicesNoLowRamNoWatchValidPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(false);
-        when(mActivityManager.isLowRamDevice()).thenReturn(false);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
-        assertEquals(true, mService.canUseManagedServices("d", 0 , null));
-    }
-
-    @Test
-    public void testCanUseManagedServicesNoLowRamWatchValidPkg() {
-        when(mPackageManagerClient.hasSystemFeature(FEATURE_WATCH)).thenReturn(true);
-        when(mActivityManager.isLowRamDevice()).thenReturn(false);
-        when(mResources.getStringArray(R.array.config_allowedManagedServicesOnLowRamDevices))
-                .thenReturn(new String[] {"a", "b", "c"});
-        when(mContext.getResources()).thenReturn(mResources);
-
+    public void testCanUseManagedServicesNoValidPkg() {
         assertEquals(true, mService.canUseManagedServices("d", 0, null));
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
index 0ea53fa..d765042 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationTest.java
@@ -22,9 +22,7 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 import android.app.ActivityManager;
@@ -32,15 +30,12 @@
 import android.app.PendingIntent;
 import android.app.Person;
 import android.app.RemoteInput;
-import android.content.Context;
-import android.content.pm.ApplicationInfo;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Color;
 import android.graphics.Typeface;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
-import android.os.Build;
 import android.text.SpannableStringBuilder;
 import android.text.Spanned;
 import android.text.style.StyleSpan;
@@ -74,91 +69,13 @@
     }
 
     @Test
-    public void testStripsExtendersInLowRamModeNoWhitelistNoTv() {
+    public void testDoesNotStripsExtenders() {
         Notification.Builder nb = new Notification.Builder(mContext, "channel");
         nb.extend(new Notification.CarExtender().setColor(Color.RED));
         nb.extend(new Notification.TvExtender().setChannelId("different channel"));
         nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
         Notification before = nb.build();
-
-        // No whitelist
-        Context context = spy(getContext());
-        when(context.getResources()).thenReturn(mResources);
-        when(mResources.getStringArray(anyInt())).thenReturn(new String[0]);
-
-        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
-                context);
-
-        assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
-        assertNull(new Notification.TvExtender(after).getChannelId());
-
-        assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
-        assertEquals(Notification.COLOR_DEFAULT, new Notification.CarExtender(after).getColor());
-
-        assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
-        assertNull(new Notification.WearableExtender(after).getDismissalId());
-    }
-
-    @Test
-    public void testStripsExtendersInLowRamModeHasWhitelist() {
-        Notification.Builder nb = new Notification.Builder(mContext, "channel");
-        nb.extend(new Notification.CarExtender().setColor(Color.RED));
-        nb.extend(new Notification.TvExtender().setChannelId("different channel"));
-        nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
-        Notification before = nb.build();
-
-        // Has whitelist
-        Context context = spy(mContext);
-        when(context.getResources()).thenReturn(mResources);
-        when(mResources.getStringArray(anyInt())).thenReturn(new String[1]);
-
-        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
-                context);
-
-        assertEquals("different channel", new Notification.TvExtender(before).getChannelId());
-        assertEquals("different channel", new Notification.TvExtender(after).getChannelId());
-
-        assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
-        assertEquals(Color.RED, new Notification.CarExtender(after).getColor());
-
-        assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
-        assertEquals("dismiss", new Notification.WearableExtender(after).getDismissalId());
-    }
-
-    @Test
-    public void testStripsRemoteViewsInLowRamMode() {
-        Context context = spy(mContext);
-        ApplicationInfo ai = new ApplicationInfo();
-        ai.targetSdkVersion = Build.VERSION_CODES.M;
-        when(context.getApplicationInfo()).thenReturn(ai);
-
-        final Notification.BigTextStyle style = new Notification.BigTextStyle()
-                .bigText("hello")
-                .setSummaryText("And the summary");
-        Notification before = new Notification.Builder(context, "channel")
-                .setContentText("hi")
-                .setStyle(style)
-                .build();
-
-        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, true,
-                mContext);
-        assertNotNull(before.contentView);
-        assertNotNull(before.bigContentView);
-        assertNotNull(before.headsUpContentView);
-        assertNull(after.contentView);
-        assertNull(after.bigContentView);
-        assertNull(after.headsUpContentView);
-    }
-
-    @Test
-    public void testDoesNotStripsExtendersInNormalRamMode() {
-        Notification.Builder nb = new Notification.Builder(mContext, "channel");
-        nb.extend(new Notification.CarExtender().setColor(Color.RED));
-        nb.extend(new Notification.TvExtender().setChannelId("different channel"));
-        nb.extend(new Notification.WearableExtender().setDismissalId("dismiss"));
-        Notification before = nb.build();
-        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before, false,
-                mContext);
+        Notification after = Notification.Builder.maybeCloneStrippedForDelivery(before);
 
         assertTrue(before == after);
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 0adf15c..5829961 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -36,9 +36,10 @@
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -67,6 +68,7 @@
 import android.provider.Settings.Global;
 import android.provider.Settings.Secure;
 import android.service.notification.ConversationChannelWrapper;
+import android.test.mock.MockIContentProvider;
 import android.test.suitebuilder.annotation.SmallTest;
 import android.testing.TestableContentResolver;
 import android.util.ArrayMap;
@@ -87,6 +89,7 @@
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -108,6 +111,7 @@
     private static final int UID_N_MR1 = 0;
     private static final UserHandle USER = UserHandle.of(0);
     private static final int UID_O = 1111;
+    private static final int UID_P = 2222;
     private static final String SYSTEM_PKG = "android";
     private static final int SYSTEM_UID = 1000;
     private static final UserHandle USER2 = UserHandle.of(10);
@@ -122,7 +126,7 @@
     @Mock NotificationUsageStats mUsageStats;
     @Mock RankingHandler mHandler;
     @Mock PackageManager mPm;
-    @Mock IContentProvider mTestIContentProvider;
+    @Spy IContentProvider mTestIContentProvider = new MockIContentProvider();
     @Mock Context mContext;
     @Mock ZenModeHelper mMockZenModeHelper;
 
@@ -141,9 +145,11 @@
         upgrade.targetSdkVersion = Build.VERSION_CODES.O;
         when(mPm.getApplicationInfoAsUser(eq(PKG_N_MR1), anyInt(), anyInt())).thenReturn(legacy);
         when(mPm.getApplicationInfoAsUser(eq(PKG_O), anyInt(), anyInt())).thenReturn(upgrade);
+        when(mPm.getApplicationInfoAsUser(eq(PKG_P), anyInt(), anyInt())).thenReturn(upgrade);
         when(mPm.getApplicationInfoAsUser(eq(SYSTEM_PKG), anyInt(), anyInt())).thenReturn(upgrade);
         when(mPm.getPackageUidAsUser(eq(PKG_N_MR1), anyInt())).thenReturn(UID_N_MR1);
         when(mPm.getPackageUidAsUser(eq(PKG_O), anyInt())).thenReturn(UID_O);
+        when(mPm.getPackageUidAsUser(eq(PKG_P), anyInt())).thenReturn(UID_P);
         when(mPm.getPackageUidAsUser(eq(SYSTEM_PKG), anyInt())).thenReturn(SYSTEM_UID);
         PackageInfo info = mock(PackageInfo.class);
         info.signatures = new Signature[] {mock(Signature.class)};
@@ -167,12 +173,12 @@
         when(testContentProvider.getIContentProvider()).thenReturn(mTestIContentProvider);
         contentResolver.addProvider(TEST_AUTHORITY, testContentProvider);
 
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI)))
-                .thenReturn(CANONICAL_SOUND_URI);
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(CANONICAL_SOUND_URI);
-        when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(SOUND_URI);
+        doReturn(CANONICAL_SOUND_URI)
+                .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
+        doReturn(CANONICAL_SOUND_URI)
+                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+        doReturn(SOUND_URI)
+                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
 
         mTestNotificationPolicy = new NotificationManager.Policy(0, 0, 0, 0,
                 NotificationManager.Policy.STATE_CHANNELS_BYPASSING_DND, 0);
@@ -503,12 +509,13 @@
                 .appendQueryParameter("title", "Test")
                 .appendQueryParameter("canonical", "1")
                 .build();
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(canonicalBasedOnLocal);
-        when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(localUri);
-        when(mTestIContentProvider.uncanonicalize(any(), any(), eq(canonicalBasedOnLocal)))
-                .thenReturn(localUri);
+        doReturn(canonicalBasedOnLocal)
+                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+        doReturn(localUri)
+                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+        doReturn(localUri)
+                .when(mTestIContentProvider).uncanonicalize(any(), any(),
+                eq(canonicalBasedOnLocal));
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -527,10 +534,10 @@
     @Test
     public void testRestoreXml_withNonExistentCanonicalizedSoundUri() throws Exception {
         Thread.sleep(3000);
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(null);
-        when(mTestIContentProvider.uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI)))
-                .thenReturn(null);
+        doReturn(null)
+                .when(mTestIContentProvider).canonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
+        doReturn(null)
+                .when(mTestIContentProvider).uncanonicalize(any(), any(), eq(CANONICAL_SOUND_URI));
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -554,7 +561,8 @@
     @Test
     public void testRestoreXml_withUncanonicalizedNonLocalSoundUri() throws Exception {
         // Not a local uncanonicalized uri, simulating that it fails to exist locally
-        when(mTestIContentProvider.canonicalize(any(), any(), eq(SOUND_URI))).thenReturn(null);
+        doReturn(null)
+                .when(mTestIContentProvider).canonicalize(any(), any(), eq(SOUND_URI));
         String id = "id";
         String backupWithUncanonicalizedSoundUri = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -2945,6 +2953,92 @@
     }
 
     @Test
+    public void testGetConversations_all() {
+        String convoId = "convo";
+        NotificationChannel messages =
+                new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false);
+        NotificationChannel calls =
+                new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false);
+        NotificationChannel p =
+                new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false);
+
+        NotificationChannel channel =
+                new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT);
+        channel.setConversationId(messages.getId(), convoId);
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false);
+
+        NotificationChannel diffConvo =
+                new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT);
+        diffConvo.setConversationId(p.getId(), "different convo");
+        mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false);
+
+        NotificationChannel channel2 =
+                new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT);
+        channel2.setConversationId(calls.getId(), convoId);
+        channel2.setImportantConversation(true);
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false);
+
+        List<ConversationChannelWrapper> convos = mHelper.getConversations(false);
+
+        assertEquals(3, convos.size());
+        assertTrue(conversationWrapperContainsChannel(convos, channel));
+        assertTrue(conversationWrapperContainsChannel(convos, diffConvo));
+        assertTrue(conversationWrapperContainsChannel(convos, channel2));
+    }
+
+    @Test
+    public void testGetConversations_onlyImportant() {
+        String convoId = "convo";
+        NotificationChannel messages =
+                new NotificationChannel("messages", "Messages", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_O, UID_O, messages, true, false);
+        NotificationChannel calls =
+                new NotificationChannel("calls", "Calls", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_O, UID_O, calls, true, false);
+        NotificationChannel p =
+                new NotificationChannel("p calls", "Calls", IMPORTANCE_DEFAULT);
+        mHelper.createNotificationChannel(PKG_P, UID_P, p, true, false);
+
+        NotificationChannel channel =
+                new NotificationChannel("A person msgs", "messages from A", IMPORTANCE_DEFAULT);
+        channel.setConversationId(messages.getId(), convoId);
+        channel.setImportantConversation(true);
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel, true, false);
+
+        NotificationChannel diffConvo =
+                new NotificationChannel("B person msgs", "messages from B", IMPORTANCE_DEFAULT);
+        diffConvo.setConversationId(p.getId(), "different convo");
+        diffConvo.setImportantConversation(true);
+        mHelper.createNotificationChannel(PKG_P, UID_P, diffConvo, true, false);
+
+        NotificationChannel channel2 =
+                new NotificationChannel("A person calls", "calls from A", IMPORTANCE_DEFAULT);
+        channel2.setConversationId(calls.getId(), convoId);
+        mHelper.createNotificationChannel(PKG_O, UID_O, channel2, true, false);
+
+        List<ConversationChannelWrapper> convos = mHelper.getConversations(true);
+
+        assertEquals(2, convos.size());
+        assertTrue(conversationWrapperContainsChannel(convos, channel));
+        assertTrue(conversationWrapperContainsChannel(convos, diffConvo));
+        assertFalse(conversationWrapperContainsChannel(convos, channel2));
+    }
+
+    private boolean conversationWrapperContainsChannel(List<ConversationChannelWrapper> list,
+            NotificationChannel expected) {
+        for (ConversationChannelWrapper ccw : list) {
+            if (ccw.getNotificationChannel().equals(expected)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    @Test
     public void testGetConversations_invalidPkg() {
         assertThat(mHelper.getConversations("bad", 1)).isEmpty();
     }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 1dd0b1a..816e8e5 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -22,6 +22,7 @@
 import static junit.framework.Assert.assertNull;
 import static junit.framework.Assert.assertTrue;
 
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
@@ -96,10 +97,33 @@
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml_string.getBytes())), null);
-        mSnoozeHelper.readXml(parser);
-        assertTrue("Should read the notification time from xml and it should be more than zero",
-                0 < mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
-                        0, "pkg", "key").doubleValue());
+        mSnoozeHelper.readXml(parser, 1);
+        assertEquals((long) Long.MAX_VALUE, (long) mSnoozeHelper
+                .getSnoozeTimeForUnpostedNotification(0, "pkg", "key"));
+        verify(mAm, never()).setExactAndAllowWhileIdle(anyInt(), anyLong(), any());
+    }
+
+    @Test
+    public void testWriteXML_afterReading_noNPE()
+            throws XmlPullParserException, IOException {
+        final String max_time_str = Long.toString(Long.MAX_VALUE);
+        final String xml_string = "<snoozed-notifications>"
+                + "<notification version=\"1\" user-id=\"0\" notification=\"notification\" "
+                + "pkg=\"pkg\" key=\"key\" time=\"" + max_time_str + "\"/>"
+                + "<notification version=\"1\" user-id=\"0\" notification=\"notification\" "
+                + "pkg=\"pkg\" key=\"key2\" time=\"" + max_time_str + "\"/>"
+                + "</snoozed-notifications>";
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml_string.getBytes())), null);
+        mSnoozeHelper.readXml(parser, 1);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        XmlSerializer serializer = new FastXmlSerializer();
+        serializer.setOutput(new BufferedOutputStream(baos), "utf-8");
+        serializer.startDocument(null, true);
+        mSnoozeHelper.writeXml(serializer);
+        serializer.endDocument();
+        serializer.flush();
     }
 
     @Test
@@ -115,7 +139,7 @@
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(xml_string.getBytes())), null);
-        mSnoozeHelper.readXml(parser);
+        mSnoozeHelper.readXml(parser, 1);
         assertEquals("Should read the notification context from xml and it should be `uri",
                 "uri", mSnoozeHelper.getSnoozeContextForUnpostedNotification(
                         0, "pkg", "key"));
@@ -137,7 +161,7 @@
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), "utf-8");
-        mSnoozeHelper.readXml(parser);
+        mSnoozeHelper.readXml(parser, 1);
         assertTrue("Should read the notification time from xml and it should be more than zero",
                 0 < mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
                         0, "pkg", r.getKey()).doubleValue());
@@ -161,7 +185,7 @@
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(new BufferedInputStream(
                 new ByteArrayInputStream(baos.toByteArray())), "utf-8");
-        mSnoozeHelper.readXml(parser);
+        mSnoozeHelper.readXml(parser, 2);
         int systemUser = UserHandle.SYSTEM.getIdentifier();
         assertTrue("Should see a past time returned",
                 System.currentTimeMillis() >  mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
@@ -195,6 +219,30 @@
     }
 
     @Test
+    public void testScheduleRepostsForPersistedNotifications() throws Exception {
+        final String xml_string = "<snoozed-notifications>"
+                + "<notification version=\"1\" user-id=\"0\" notification=\"notification\" "
+                + "pkg=\"pkg\" key=\"key\" time=\"" + 10 + "\"/>"
+                + "<notification version=\"1\" user-id=\"0\" notification=\"notification\" "
+                + "pkg=\"pkg\" key=\"key2\" time=\"" + 15+ "\"/>"
+                + "</snoozed-notifications>";
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new BufferedInputStream(
+                new ByteArrayInputStream(xml_string.getBytes())), null);
+        mSnoozeHelper.readXml(parser, 4);
+
+        mSnoozeHelper.scheduleRepostsForPersistedNotifications(5);
+
+        ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq((long) 10), captor.capture());
+        assertEquals("key", captor.getValue().getIntent().getStringExtra(EXTRA_KEY));
+
+        ArgumentCaptor<PendingIntent> captor2 = ArgumentCaptor.forClass(PendingIntent.class);
+        verify(mAm).setExactAndAllowWhileIdle(anyInt(), eq((long) 15), captor2.capture());
+        assertEquals("key2", captor2.getValue().getIntent().getStringExtra(EXTRA_KEY));
+    }
+
+    @Test
     public void testSnoozeForTime() throws Exception {
         NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
         mSnoozeHelper.snooze(r, 1000);
@@ -414,6 +462,23 @@
     }
 
     @Test
+    public void testGetSnoozedGroupNotifications_nonGrouped() throws Exception {
+        IntArray profileIds = new IntArray();
+        profileIds.add(UserHandle.USER_CURRENT);
+        when(mUserProfiles.getCurrentProfileIds()).thenReturn(profileIds);
+        NotificationRecord r = getNotificationRecord("pkg", 1, "tag",
+                UserHandle.CURRENT, "group", true);
+        NotificationRecord r2 = getNotificationRecord("pkg", 2, "tag",
+                UserHandle.CURRENT, null, true);
+        mSnoozeHelper.snooze(r, 1000);
+        mSnoozeHelper.snooze(r2, 1000);
+
+        assertEquals(1,
+                mSnoozeHelper.getNotifications("pkg", "group", UserHandle.USER_CURRENT).size());
+        // and no NPE
+    }
+
+    @Test
     public void testGetSnoozedNotificationByKey() throws Exception {
         IntArray profileIds = new IntArray();
         profileIds.add(UserHandle.USER_CURRENT);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index bc2766c..cee486f 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -16,6 +16,19 @@
 
 package com.android.server.notification;
 
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_ALARMS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_EVENTS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MEDIA;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REMINDERS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_BADGE;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
@@ -219,7 +232,7 @@
     public void testZenOff_NoMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_OFF;
         mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
-                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
+                PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         doNothing().when(mZenModeHelperSpy).applyRestrictions(eq(false), anyBoolean(), anyInt());
@@ -230,10 +243,73 @@
     }
 
     @Test
+    public void testZenOn_NotificationApplied() {
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        // The most permissive policy
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
+                | PRIORITY_CATEGORY_CONVERSATIONS | PRIORITY_CATEGORY_CALLS
+                | PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_EVENTS | PRIORITY_CATEGORY_REMINDERS
+                | PRIORITY_CATEGORY_REPEAT_CALLERS | PRIORITY_CATEGORY_SYSTEM, PRIORITY_SENDERS_ANY,
+                PRIORITY_SENDERS_ANY, 0, CONVERSATION_SENDERS_ANYONE);
+        mZenModeHelperSpy.applyRestrictions();
+
+        doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyBoolean(), anyInt());
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION);
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION_EVENT);
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_DELAYED);
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_INSTANT);
+    }
+
+    @Test
+    public void testZenOn_StarredCallers_CallTypesBlocked() {
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        // The most permissive policy
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
+                | PRIORITY_CATEGORY_CONVERSATIONS | PRIORITY_CATEGORY_CALLS
+                | PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_EVENTS | PRIORITY_CATEGORY_REMINDERS
+                | PRIORITY_CATEGORY_SYSTEM,
+                PRIORITY_SENDERS_STARRED,
+                PRIORITY_SENDERS_ANY, 0, CONVERSATION_SENDERS_ANYONE);
+        mZenModeHelperSpy.applyRestrictions();
+
+        doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyBoolean(), anyInt());
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+        verify(mZenModeHelperSpy).applyRestrictions(true, true,
+                AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
+    }
+
+    @Test
+    public void testZenOn_AllCallers_CallTypesAllowed() {
+        mZenModeHelperSpy.mZenMode = Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
+        // The most permissive policy
+        mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
+                PRIORITY_CATEGORY_MEDIA | PRIORITY_CATEGORY_MESSAGES
+                | PRIORITY_CATEGORY_CONVERSATIONS | PRIORITY_CATEGORY_CALLS
+                | PRIORITY_CATEGORY_ALARMS | PRIORITY_CATEGORY_EVENTS | PRIORITY_CATEGORY_REMINDERS
+                | PRIORITY_CATEGORY_REPEAT_CALLERS | PRIORITY_CATEGORY_SYSTEM,
+                PRIORITY_SENDERS_ANY,
+                PRIORITY_SENDERS_ANY, 0, CONVERSATION_SENDERS_ANYONE);
+        mZenModeHelperSpy.applyRestrictions();
+
+        doNothing().when(mZenModeHelperSpy).applyRestrictions(anyBoolean(), anyBoolean(), anyInt());
+        verify(mZenModeHelperSpy).applyRestrictions(true, false,
+                AudioAttributes.USAGE_NOTIFICATION_RINGTONE);
+        verify(mZenModeHelperSpy).applyRestrictions(true, false,
+                AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST);
+    }
+
+    @Test
     public void testZenOn_AllowAlarmsMedia_NoAlarmMediaMuteApplied() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
-                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
+                PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
 
         mZenModeHelperSpy.applyRestrictions();
         verify(mZenModeHelperSpy, atLeastOnce()).applyRestrictions(true, false,
@@ -261,7 +337,7 @@
     public void testTotalSilence() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
         mZenModeHelperSpy.mConsolidatedPolicy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS |
-                Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
+                PRIORITY_CATEGORY_MEDIA, 0, 0, 0, 0, 0);
         mZenModeHelperSpy.applyRestrictions();
 
         // Total silence will silence alarms, media and system noises (but not vibrations)
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index a0ea729..c9c3649 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -1025,9 +1025,9 @@
     public void testDestroyIfPossible_lastActivityAboveEmptyHomeStack() {
         // Empty the home stack.
         final ActivityStack homeStack = mActivity.getDisplay().getRootHomeTask();
-        homeStack.forAllTasks((t) -> {
+        homeStack.forAllLeafTasks((t) -> {
             homeStack.removeChild(t, "test");
-        }, true /* traverseTopToBottom */, homeStack);
+        }, true /* traverseTopToBottom */);
         mActivity.finishing = true;
         doReturn(false).when(mRootWindowContainer).resumeFocusedStacksTopActivities();
         spyOn(mStack);
@@ -1051,9 +1051,9 @@
     public void testCompleteFinishing_lastActivityAboveEmptyHomeStack() {
         // Empty the home stack.
         final ActivityStack homeStack = mActivity.getDisplay().getRootHomeTask();
-        homeStack.forAllTasks((t) -> {
+        homeStack.forAllLeafTasks((t) -> {
             homeStack.removeChild(t, "test");
-        }, true /* traverseTopToBottom */, homeStack);
+        }, true /* traverseTopToBottom */);
         mActivity.finishing = true;
         spyOn(mStack);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
index fa182d6..b917e1b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStarterTests.java
@@ -29,6 +29,7 @@
 import static android.app.ActivityManager.START_SWITCHES_CANCELED;
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
+import static android.app.WindowConfiguration.ACTIVITY_TYPE_UNDEFINED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
@@ -64,8 +65,10 @@
 import static org.mockito.ArgumentMatchers.anyString;
 import static org.mockito.ArgumentMatchers.eq;
 
+import android.app.ActivityManager;
 import android.app.ActivityOptions;
 import android.app.IApplicationThread;
+import android.app.WindowConfiguration;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
@@ -80,6 +83,9 @@
 import android.platform.test.annotations.Presubmit;
 import android.service.voice.IVoiceInteractionSession;
 import android.view.Gravity;
+import android.view.ITaskOrganizer;
+import android.view.IWindowContainer;
+import android.view.SurfaceControl;
 
 import androidx.test.filters.SmallTest;
 
@@ -372,7 +378,7 @@
         doReturn(mMockPackageManager).when(mService).getPackageManagerInternalLocked();
         doReturn(false).when(mMockPackageManager).isInstantAppInstallerComponent(any());
         doReturn(null).when(mMockPackageManager).resolveIntent(any(), any(), anyInt(), anyInt(),
-                anyBoolean(), anyInt());
+                anyInt(), anyBoolean(), anyInt());
 
         // Never review permissions
         doReturn(false).when(mMockPackageManager).isPermissionsReviewRequired(any(), anyInt());
@@ -999,7 +1005,8 @@
         assertThat(outActivity[0].inSplitScreenWindowingMode()).isFalse();
 
         // Move activity to split-screen-primary stack and make sure it has the focus.
-        top.getRootTask().setWindowingMode(WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+        TestSplitOrganizer splitOrg = new TestSplitOrganizer(mService, top.getDisplayId());
+        splitOrg.mPrimary.addChild(top.getRootTask(), 0 /* index */);
         top.getRootTask().moveToFront("testWindowingModeOptionsLaunchAdjacent");
 
         // Activity must landed on split-screen-secondary when launch adjacent.
@@ -1022,4 +1029,58 @@
 
         verify(recentTasks, times(1)).add(any());
     }
+
+    static class TestSplitOrganizer extends ITaskOrganizer.Stub {
+        final ActivityTaskManagerService mService;
+        TaskTile mPrimary;
+        TaskTile mSecondary;
+        boolean mInSplit = false;
+        int mDisplayId;
+        TestSplitOrganizer(ActivityTaskManagerService service, int displayId) {
+            mService = service;
+            mDisplayId = displayId;
+            mService.mTaskOrganizerController.registerTaskOrganizer(this,
+                    WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+            mService.mTaskOrganizerController.registerTaskOrganizer(this,
+                    WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
+            IWindowContainer primary = mService.mTaskOrganizerController.createRootTask(
+                    displayId, WINDOWING_MODE_SPLIT_SCREEN_PRIMARY).token;
+            mPrimary = TaskTile.forToken(primary.asBinder());
+            IWindowContainer secondary = mService.mTaskOrganizerController.createRootTask(
+                    displayId, WINDOWING_MODE_SPLIT_SCREEN_SECONDARY).token;
+            mSecondary = TaskTile.forToken(secondary.asBinder());
+        }
+        @Override
+        public void taskAppeared(ActivityManager.RunningTaskInfo info) {
+        }
+        @Override
+        public void taskVanished(IWindowContainer wc) {
+        }
+        @Override
+        public void transactionReady(int id, SurfaceControl.Transaction t) {
+        }
+        @Override
+        public void onTaskInfoChanged(ActivityManager.RunningTaskInfo info) {
+            if (mInSplit) {
+                return;
+            }
+            if (info.topActivityType != ACTIVITY_TYPE_UNDEFINED) {
+                if (info.configuration.windowConfiguration.getWindowingMode()
+                        == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
+                    mInSplit = true;
+                    mService.mTaskOrganizerController.setLaunchRoot(mDisplayId,
+                            mSecondary.mRemoteToken);
+                    // move everything to secondary because test expects this but usually sysui
+                    // does it.
+                    DisplayContent dc = mService.mRootWindowContainer.getDisplayContent(mDisplayId);
+                    for (int i = dc.getStackCount() - 1; i >= 0; --i) {
+                        if (!WindowConfiguration.isSplitScreenWindowingMode(
+                                dc.getStackAt(i).getWindowingMode())) {
+                            mSecondary.addChild(dc.getStackAt(i), 0);
+                        }
+                    }
+                }
+            }
+        }
+    };
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
index 70e5ee7..683fca4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppWindowTokenTests.java
@@ -209,6 +209,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 149760957)
     public void testSizeCompatBounds() {
         // Disable the real configuration resolving because we only simulate partial flow.
         // TODO: Have test use full flow.
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
index 8ac1d24..cc9173a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayAreaPolicyBuilderTest.java
@@ -40,6 +40,8 @@
 import android.platform.test.annotations.Presubmit;
 import android.view.SurfaceControl;
 
+import androidx.test.filters.FlakyTest;
+
 import org.hamcrest.CustomTypeSafeMatcher;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
@@ -65,6 +67,7 @@
     private TestWindowManagerPolicy mPolicy = new TestWindowManagerPolicy(null, null);
 
     @Test
+    @FlakyTest(bugId = 149760939)
     public void testBuilder() {
         WindowManagerService wms = mSystemServices.getWindowManagerService();
         DisplayArea.Root root = new SurfacelessDisplayAreaRoot(wms);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 1a8f2a6..b3c6b22 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -27,6 +27,7 @@
 import static android.view.DisplayCutout.BOUNDS_POSITION_LEFT;
 import static android.view.DisplayCutout.BOUNDS_POSITION_TOP;
 import static android.view.DisplayCutout.fromBoundingRect;
+import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.SYSTEM_UI_FLAG_FULLSCREEN;
 import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
@@ -998,12 +999,10 @@
     public void testApplyTopFixedRotationTransform() {
         mWm.mIsFixedRotationTransformEnabled = true;
         final Configuration config90 = new Configuration();
-        mDisplayContent.getDisplayRotation().setRotation(ROTATION_90);
-        mDisplayContent.computeScreenConfiguration(config90);
-        mDisplayContent.onRequestedOverrideConfigurationChanged(config90);
+        mDisplayContent.computeScreenConfiguration(config90, ROTATION_90);
 
         final Configuration config = new Configuration();
-        mDisplayContent.getDisplayRotation().setRotation(Surface.ROTATION_0);
+        mDisplayContent.getDisplayRotation().setRotation(ROTATION_0);
         mDisplayContent.computeScreenConfiguration(config);
         mDisplayContent.onRequestedOverrideConfigurationChanged(config);
 
@@ -1014,11 +1013,18 @@
         app.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
 
         assertTrue(app.isFixedRotationTransforming());
+        assertTrue(mDisplayContent.getDisplayRotation().shouldRotateSeamlessly(
+                ROTATION_0 /* oldRotation */, ROTATION_90 /* newRotation */,
+                false /* forceUpdate */));
+        // The display should keep current orientation and the rotated configuration should apply
+        // to the activity.
         assertEquals(config.orientation, mDisplayContent.getConfiguration().orientation);
         assertEquals(config90.orientation, app.getConfiguration().orientation);
+        assertEquals(config90.windowConfiguration.getBounds(), app.getBounds());
 
         mDisplayContent.mAppTransition.notifyAppTransitionFinishedLocked(app.token);
 
+        // The display should be rotated after the launch is finished.
         assertFalse(app.hasFixedRotationTransform());
         assertEquals(config90.orientation, mDisplayContent.getConfiguration().orientation);
     }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index c19312d..2b0ad89 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -599,11 +599,13 @@
     }
 
     @Test
+    @FlakyTest(bugId = 149760800)
     public void layoutWindowLw_withLongEdgeDisplayCutout() {
         addLongEdgeDisplayCutout();
 
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+        mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         addWindow(mWindow);
 
         mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
@@ -618,11 +620,13 @@
     }
 
     @Test
+    @FlakyTest(bugId = 149760800)
     public void layoutWindowLw_withLongEdgeDisplayCutout_never() {
         addLongEdgeDisplayCutout();
 
         mWindow.mAttrs.flags =
                 FLAG_LAYOUT_IN_SCREEN | FLAG_LAYOUT_INSET_DECOR | FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
+        mWindow.mAttrs.setFitInsetsTypes(0 /* types */);
         mWindow.mAttrs.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
         addWindow(mWindow);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
index a672a95..4449069 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentTasksTest.java
@@ -1098,7 +1098,6 @@
         assertSecurityException(expectCallable,
                 () -> mService.setTaskWindowingModeSplitScreenPrimary(0,
                         SPLIT_SCREEN_CREATE_MODE_TOP_OR_LEFT, true, true, new Rect(), true));
-        assertSecurityException(expectCallable, () -> mService.dismissSplitScreenMode(true));
         assertSecurityException(expectCallable, () -> mService.dismissPip(true, 0));
         assertSecurityException(expectCallable,
                 () -> mService.moveTopActivityToPinnedStack(INVALID_STACK_ID, new Rect()));
diff --git a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
index 7753a32..6a8917c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RecentsAnimationControllerTest.java
@@ -20,7 +20,9 @@
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
+import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_ACTIVITY_CLOSE;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.atLeast;
@@ -53,6 +55,8 @@
 import static org.mockito.Mockito.never;
 
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.IInterface;
@@ -65,12 +69,16 @@
 
 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
 
+import com.google.common.truth.Truth;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+
 /**
  * Build/Install/Run:
  *  atest WmTests:RecentsAnimationControllerTest
@@ -330,6 +338,107 @@
         assertTrue(activity.shouldAnimate(TRANSIT_ACTIVITY_CLOSE));
     }
 
+    @Test
+    public void testRecentViewInFixedPortraitWhenTopAppInLandscape() {
+        mWm.mIsFixedRotationTransformEnabled = true;
+        mWm.setRecentsAnimationController(mController);
+
+        final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final ActivityRecord homeAppWindow =
+                new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+                        .setStack(homeStack)
+                        .setCreateTask(true)
+                        .build();
+        final ActivityRecord appWindow = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState win0 = createWindow(null, TYPE_BASE_APPLICATION, appWindow, "win1");
+        appWindow.addWindow(win0);
+
+        final ActivityRecord landActivity = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        landActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+        final WindowState win1 = createWindow(null, TYPE_BASE_APPLICATION, landActivity, "win1");
+        landActivity.addWindow(win1);
+
+        assertEquals(landActivity.getTask().getTopVisibleActivity(), landActivity);
+        assertEquals(landActivity.findMainWindow(), win1);
+
+        // Ensure that the display is in Landscape
+        landActivity.onDescendantOrientationChanged(landActivity.token, landActivity);
+        assertEquals(Configuration.ORIENTATION_LANDSCAPE,
+                mDisplayContent.getConfiguration().orientation);
+
+        mController.initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeAppWindow);
+
+        // Check that the home app is in portrait
+        assertEquals(Configuration.ORIENTATION_PORTRAIT,
+                homeAppWindow.getConfiguration().orientation);
+    }
+
+    @Test
+    public void testWallpaperHasFixedRotationApplied() {
+        mWm.mIsFixedRotationTransformEnabled = true;
+        mWm.setRecentsAnimationController(mController);
+
+        // Create a portrait home stack, a wallpaper and a landscape application displayed on top.
+
+        // Home stack
+        final ActivityStack homeStack = mDisplayContent.getOrCreateStack(
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_HOME, ON_TOP);
+        final ActivityRecord homeActivity =
+                new ActivityTestsBase.ActivityBuilder(mWm.mAtmService)
+                        .setStack(homeStack)
+                        .setCreateTask(true)
+                        .build();
+        homeActivity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+
+        final WindowState homeWindow = createWindow(null, TYPE_BASE_APPLICATION, homeActivity,
+                "homeWindow");
+        homeActivity.addWindow(homeWindow);
+        homeWindow.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+
+        // Landscape application
+        final ActivityRecord activity = createActivityRecord(mDisplayContent,
+                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState applicationWindow = createWindow(null, TYPE_BASE_APPLICATION, activity,
+                "applicationWindow");
+        activity.addWindow(applicationWindow);
+        activity.setOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+
+        // Wallpaper
+        final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
+                mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
+        final WindowState wallpaperWindow = createWindow(null, TYPE_WALLPAPER, wallpaperWindowToken,
+                "wallpaperWindow");
+
+        // Make sure the landscape activity is on top and the display is in landscape
+        activity.moveFocusableActivityToTop("test");
+        mDisplayContent.getConfiguration().windowConfiguration.setRotation(
+                mDisplayContent.getRotation());
+
+
+        spyOn(mDisplayContent.mWallpaperController);
+        doReturn(true).when(mDisplayContent.mWallpaperController).isWallpaperVisible();
+
+        // Start the recents animation
+        mController
+                .initialize(ACTIVITY_TYPE_HOME, new SparseBooleanArray(), homeActivity);
+
+        mDisplayContent.mWallpaperController.adjustWallpaperWindows();
+
+        // Check preconditions
+        ArrayList<WallpaperWindowToken> wallpapers = new ArrayList<>(1);
+        mDisplayContent.forAllWallpaperWindows(wallpapers::add);
+
+        Truth.assertThat(wallpapers).hasSize(1);
+        Truth.assertThat(wallpapers.get(0).getTopChild()).isEqualTo(wallpaperWindow);
+
+        // Actual check
+        assertEquals(Configuration.ORIENTATION_PORTRAIT,
+                wallpapers.get(0).getConfiguration().orientation);
+    }
+
     private static void verifyNoMoreInteractionsExceptAsBinder(IInterface binder) {
         verify(binder, atLeast(0)).asBinder();
         verifyNoMoreInteractions(binder);
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
index dd46673..ec20262 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootActivityContainerTests.java
@@ -313,8 +313,8 @@
      */
     @Test
     public void testResizeDockedStackForSplitScreenPrimary() {
-        final Rect taskSize = new Rect(0, 0, 1000, 1000);
-        final Rect stackSize = new Rect(0, 0, 300, 300);
+        final Rect configSize = new Rect(0, 0, 1000, 1000);
+        final Rect displayedSize = new Rect(0, 0, 300, 300);
 
         // Create primary split-screen stack with a task.
         final ActivityStack primaryStack = new StackBuilder(mRootWindowContainer)
@@ -325,11 +325,13 @@
         final Task task = primaryStack.getTopMostTask();
 
         // Resize dock stack.
-        mService.resizeDockedStack(stackSize, taskSize, null, null, null);
+        mService.resizeDockedStack(displayedSize, configSize, null, null, null);
 
         // Verify dock stack & its task bounds if is equal as resized result.
-        assertEquals(stackSize, primaryStack.getBounds());
-        assertEquals(taskSize, task.getBounds());
+        assertEquals(displayedSize, primaryStack.getDisplayedBounds());
+        assertEquals(displayedSize, primaryStack.getDisplayedBounds());
+        assertEquals(configSize, primaryStack.getBounds());
+        assertEquals(configSize, task.getBounds());
     }
 
     /**
diff --git a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
index eda1fb8..851b052 100644
--- a/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
+++ b/services/tests/wmtests/src/com/android/server/wm/StubTransaction.java
@@ -255,4 +255,14 @@
             int priority) {
         return this;
     }
+
+    @Override
+    public SurfaceControl.Transaction unsetColor(SurfaceControl sc) {
+        return this;
+    }
+
+    @Override
+    public SurfaceControl.Transaction setShadowRadius(SurfaceControl sc, float shadowRadius) {
+        return this;
+    }
 }
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 8ad7505..55d12db 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -137,6 +137,7 @@
                         }
                         throw t;
                     }
+                    if (throwable != null) throw throwable;
                 }
             }
         };
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java
new file mode 100644
index 0000000..4056c71
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRuleTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.wm;
+
+import static junit.framework.Assert.assertTrue;
+
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runners.model.Statement;
+
+import java.io.IOException;
+
+@Presubmit
+public class SystemServicesTestRuleTest {
+    @Rule
+    public ExpectedException mExpectedException = ExpectedException.none();
+
+    @Test
+    public void testRule_rethrows_unchecked_exceptions() throws Throwable {
+        final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
+        Statement statement = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                throw new RuntimeException("A failing test!");
+            }
+        };
+        mExpectedException.expect(RuntimeException.class);
+        mWmsRule.apply(statement, null /* Description*/).evaluate();
+    }
+
+    @Test
+    public void testRule_rethrows_checked_exceptions() throws Throwable {
+        final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
+        Statement statement = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                throw new IOException("A failing test!");
+            }
+        };
+        mExpectedException.expect(IOException.class);
+        mWmsRule.apply(statement, null /* Description*/).evaluate();
+    }
+
+    @Test
+    public void testRule_ranSuccessfully() throws Throwable {
+        final boolean[] testRan = {false};
+        final SystemServicesTestRule mWmsRule = new SystemServicesTestRule();
+        Statement statement = new Statement() {
+            @Override
+            public void evaluate() throws Throwable {
+                testRan[0] = true;
+            }
+        };
+        mWmsRule.apply(statement, null /* Description*/).evaluate();
+        assertTrue(testRan[0]);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
index 0312df6..45b51cf 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskOrganizerTests.java
@@ -28,19 +28,18 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.when;
 
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.never;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
-
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -49,6 +48,7 @@
 import android.app.ActivityManager.RunningTaskInfo;
 import android.app.ActivityManager.StackInfo;
 import android.app.PictureInPictureParams;
+import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -56,7 +56,6 @@
 import android.os.RemoteException;
 import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
-import android.content.pm.ActivityInfo;
 import android.util.Rational;
 import android.view.Display;
 import android.view.ITaskOrganizer;
@@ -302,6 +301,7 @@
         Rect newSize = new Rect(10, 10, 300, 300);
         Configuration c = new Configuration(tile1.getRequestedOverrideConfiguration());
         c.windowConfiguration.setBounds(newSize);
+        doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
         tile1.onRequestedOverrideConfigurationChanged(c);
         assertEquals(newSize, stack.getBounds());
 
@@ -458,9 +458,9 @@
     private List<TaskTile> getTaskTiles(DisplayContent dc) {
         ArrayList<TaskTile> out = new ArrayList<>();
         for (int i = dc.getStackCount() - 1; i >= 0; --i) {
-            final Task t = dc.getStackAt(i);
-            if (t instanceof TaskTile) {
-                out.add((TaskTile) t);
+            final TaskTile t = dc.getStackAt(i).asTile();
+            if (t != null) {
+                out.add(t);
             }
         }
         return out;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
index 6e4be88..6387a3b 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskStackTests.java
@@ -16,9 +16,11 @@
 
 package com.android.server.wm;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
@@ -33,6 +35,7 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.clearInvocations;
 
+import android.app.WindowConfiguration;
 import android.graphics.Rect;
 import android.platform.test.annotations.Presubmit;
 
@@ -184,6 +187,16 @@
         doReturn(stackOutset).when(stack).getStackOutset();
         doReturn(true).when(stack).inMultiWindowMode();
 
+        // Mock the resolved override windowing mode to non-fullscreen
+        final WindowConfiguration windowConfiguration =
+                stack.getResolvedOverrideConfiguration().windowConfiguration;
+        spyOn(windowConfiguration);
+        doReturn(WINDOWING_MODE_SPLIT_SCREEN_SECONDARY)
+                .when(windowConfiguration).getWindowingMode();
+
+        // Prevent adjust task dimensions
+        doNothing().when(stack).adjustForMinimalTaskDimensions(any(), any());
+
         final Rect stackBounds = new Rect(200, 200, 800, 1000);
         // Update surface position and size by the given bounds.
         stack.setBounds(stackBounds);
diff --git a/services/usage/java/com/android/server/usage/StorageStatsService.java b/services/usage/java/com/android/server/usage/StorageStatsService.java
index 18b640f..c3d3d83 100644
--- a/services/usage/java/com/android/server/usage/StorageStatsService.java
+++ b/services/usage/java/com/android/server/usage/StorageStatsService.java
@@ -86,6 +86,7 @@
 public class StorageStatsService extends IStorageStatsManager.Stub {
     private static final String TAG = "StorageStatsService";
 
+    private static final String PROP_STORAGE_CRATES = "fw.storage_crates";
     private static final String PROP_DISABLE_QUOTA = "fw.disable_quota";
     private static final String PROP_VERIFY_STORAGE = "fw.verify_storage";
 
@@ -595,6 +596,13 @@
                 Uri.parse("content://com.android.externalstorage.documents/"), null, false);
     }
 
+    private static void checkCratesEnable() {
+        final boolean enable = SystemProperties.getBoolean(PROP_STORAGE_CRATES, false);
+        if (!enable) {
+            throw new IllegalStateException("Storage Crate feature is disabled.");
+        }
+    }
+
     /**
      * To enforce the calling or self to have the {@link android.Manifest.permission#MANAGE_CRATES}
      * permission.
@@ -650,6 +658,7 @@
     @Override
     public ParceledListSlice<CrateInfo> queryCratesForPackage(String volumeUuid,
             @NonNull String packageName, @UserIdInt int userId, @NonNull String callingPackage) {
+        checkCratesEnable();
         if (userId != UserHandle.getCallingUserId()) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
@@ -677,6 +686,7 @@
     @Override
     public ParceledListSlice<CrateInfo> queryCratesForUid(String volumeUuid, int uid,
             @NonNull String callingPackage) {
+        checkCratesEnable();
         final int userId = UserHandle.getUserId(uid);
         if (userId != UserHandle.getCallingUserId()) {
             mContext.enforceCallingOrSelfPermission(
@@ -718,6 +728,7 @@
     @Override
     public ParceledListSlice<CrateInfo> queryCratesForUser(String volumeUuid, int userId,
             @NonNull String callingPackage) {
+        checkCratesEnable();
         if (userId != UserHandle.getCallingUserId()) {
             mContext.enforceCallingOrSelfPermission(
                     android.Manifest.permission.INTERACT_ACROSS_USERS, TAG);
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index df5b311..0d1b352 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -86,6 +86,7 @@
 
 import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.LocalServices;
@@ -104,6 +105,7 @@
 import java.io.PrintWriter;
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -1121,7 +1123,7 @@
 
             boolean checkin = false;
             boolean compact = false;
-            String pkg = null;
+            final ArrayList<String> pkgs = new ArrayList<>();
 
             if (args != null) {
                 for (int i = 0; i < args.length; i++) {
@@ -1214,8 +1216,7 @@
                         return;
                     } else if (arg != null && !arg.startsWith("-")) {
                         // Anything else that doesn't start with '-' is a pkg to filter
-                        pkg = arg;
-                        break;
+                        pkgs.add(arg);
                     }
                 }
             }
@@ -1230,15 +1231,15 @@
                     if (checkin) {
                         mUserState.valueAt(i).checkin(idpw);
                     } else {
-                        mUserState.valueAt(i).dump(idpw, pkg, compact);
+                        mUserState.valueAt(i).dump(idpw, pkgs, compact);
                         idpw.println();
                     }
                 }
-                mAppStandby.dumpUser(idpw, userId, pkg);
+                mAppStandby.dumpUser(idpw, userId, pkgs);
                 idpw.decreaseIndent();
             }
 
-            if (pkg == null) {
+            if (CollectionUtils.isEmpty(pkgs)) {
                 pw.println();
                 mAppStandby.dumpState(args, pw);
             }
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index db26d88..b7779fd 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -48,6 +48,7 @@
 import android.util.SparseIntArray;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.CollectionUtils;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
 
@@ -753,18 +754,21 @@
         });
     }
 
-    void dump(IndentingPrintWriter pw, String pkg) {
-        dump(pw, pkg, false);
+    void dump(IndentingPrintWriter pw, List<String> pkgs) {
+        dump(pw, pkgs, false);
     }
-    void dump(IndentingPrintWriter pw, String pkg, boolean compact) {
-        printLast24HrEvents(pw, !compact, pkg);
+
+    void dump(IndentingPrintWriter pw, List<String> pkgs, boolean compact) {
+        printLast24HrEvents(pw, !compact, pkgs);
         for (int interval = 0; interval < mCurrentStats.length; interval++) {
             pw.print("In-memory ");
             pw.print(intervalToString(interval));
             pw.println(" stats");
-            printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkg);
+            printIntervalStats(pw, mCurrentStats[interval], !compact, true, pkgs);
         }
-        mDatabase.dump(pw, compact);
+        if (CollectionUtils.isEmpty(pkgs)) {
+            mDatabase.dump(pw, compact);
+        }
     }
 
     void dumpDatabaseInfo(IndentingPrintWriter ipw) {
@@ -894,7 +898,8 @@
         pw.println();
     }
 
-    void printLast24HrEvents(IndentingPrintWriter pw, boolean prettyDates, final String pkg) {
+    void printLast24HrEvents(IndentingPrintWriter pw, boolean prettyDates,
+            final List<String> pkgs) {
         final long endTime = System.currentTimeMillis();
         UnixCalendar yesterday = new UnixCalendar(endTime);
         yesterday.addDays(-1);
@@ -914,7 +919,7 @@
                             }
 
                             Event event = stats.events.get(i);
-                            if (pkg != null && !pkg.equals(event.mPackage)) {
+                            if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(event.mPackage)) {
                                 continue;
                             }
                             accumulatedResult.add(event);
@@ -958,7 +963,7 @@
     }
 
     void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats,
-            boolean prettyDates, boolean skipEvents, String pkg) {
+            boolean prettyDates, boolean skipEvents, List<String> pkgs) {
         if (prettyDates) {
             pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
                     stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
@@ -974,7 +979,7 @@
         final int pkgCount = pkgStats.size();
         for (int i = 0; i < pkgCount; i++) {
             final UsageStats usageStats = pkgStats.valueAt(i);
-            if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
+            if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(usageStats.mPackageName)) {
                 continue;
             }
             pw.printPair("package", usageStats.mPackageName);
@@ -998,7 +1003,7 @@
         pw.println("ChooserCounts");
         pw.increaseIndent();
         for (UsageStats usageStats : pkgStats.values()) {
-            if (pkg != null && !pkg.equals(usageStats.mPackageName)) {
+            if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(usageStats.mPackageName)) {
                 continue;
             }
             pw.printPair("package", usageStats.mPackageName);
@@ -1023,7 +1028,7 @@
         }
         pw.decreaseIndent();
 
-        if (pkg == null) {
+        if (CollectionUtils.isEmpty(pkgs)) {
             pw.println("configurations");
             pw.increaseIndent();
             final ArrayMap<Configuration, ConfigurationStats> configStats = stats.configurations;
@@ -1060,7 +1065,7 @@
             final int eventCount = events != null ? events.size() : 0;
             for (int i = 0; i < eventCount; i++) {
                 final Event event = events.get(i);
-                if (pkg != null && !pkg.equals(event.mPackage)) {
+                if (!CollectionUtils.isEmpty(pkgs) && !pkgs.contains(event.mPackage)) {
                     continue;
                 }
                 printEvent(pw, event, prettyDates);
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 6407ec7..84f411f 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -41,6 +41,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.debug.AdbManagerInternal;
+import android.debug.AdbTransportType;
 import android.debug.IAdbTransport;
 import android.hardware.usb.ParcelableUsbPort;
 import android.hardware.usb.UsbAccessory;
@@ -775,8 +776,10 @@
             }
 
             @Override
-            public void onAdbEnabled(boolean enabled) {
-                mHandler.sendMessage(MSG_ENABLE_ADB, enabled);
+            public void onAdbEnabled(boolean enabled, byte transportType) {
+                if (transportType == AdbTransportType.USB) {
+                    mHandler.sendMessage(MSG_ENABLE_ADB, enabled);
+                }
             }
         }
 
@@ -1170,7 +1173,8 @@
         }
 
         protected boolean isAdbEnabled() {
-            return LocalServices.getService(AdbManagerInternal.class).isAdbEnabled();
+            return LocalServices.getService(AdbManagerInternal.class)
+                    .isAdbEnabled(AdbTransportType.USB);
         }
 
         protected void updateAdbNotification(boolean force) {
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
old mode 100644
new mode 100755
index 52213d8..c5fcf67
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -465,8 +465,27 @@
          * @hide
          */
         public static final int CAPABILITY_ADD_PARTICIPANT = 0x02000000;
+
+        /**
+         * When set for a call, indicates that this {@code Call} can be transferred to another
+         * number.
+         * Call supports the blind and assured call transfer feature.
+         *
+         * @hide
+         */
+        public static final int CAPABILITY_TRANSFER = 0x04000000;
+
+        /**
+         * When set for a call, indicates that this {@code Call} can be transferred to another
+         * ongoing call.
+         * Call supports the consultative call transfer feature.
+         *
+         * @hide
+         */
+        public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x08000000;
+
         //******************************************************************************************
-        // Next CAPABILITY value: 0x04000000
+        // Next CAPABILITY value: 0x10000000
         //******************************************************************************************
 
         /**
@@ -699,6 +718,12 @@
             if (can(capabilities, CAPABILITY_ADD_PARTICIPANT)) {
                 builder.append(" CAPABILITY_ADD_PARTICIPANT");
             }
+            if (can(capabilities, CAPABILITY_TRANSFER)) {
+                builder.append(" CAPABILITY_TRANSFER");
+            }
+            if (can(capabilities, CAPABILITY_TRANSFER_CONSULTATIVE)) {
+                builder.append(" CAPABILITY_TRANSFER_CONSULTATIVE");
+            }
             builder.append("]");
             return builder.toString();
         }
@@ -1564,6 +1589,30 @@
     }
 
     /**
+     * Instructs this {@code Call} to be transferred to another number.
+     *
+     * @param targetNumber The address to which the call will be transferred.
+     * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
+     * if {@code false}, it will initiate BLIND transfer.
+     *
+     * @hide
+     */
+    public void transfer(@NonNull Uri targetNumber, boolean isConfirmationRequired) {
+        mInCallAdapter.transferCall(mTelecomCallId, targetNumber, isConfirmationRequired);
+    }
+
+    /**
+     * Instructs this {@code Call} to be transferred to another ongoing call.
+     * This will initiate CONSULTATIVE transfer.
+     * @param toCall The other ongoing {@code Call} to which this call will be transferred.
+     *
+     * @hide
+     */
+    public void transfer(@NonNull android.telecom.Call toCall) {
+        mInCallAdapter.transferCall(mTelecomCallId, toCall.mTelecomCallId);
+    }
+
+    /**
      * Instructs this {@code Call} to disconnect.
      */
     public void disconnect() {
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
old mode 100644
new mode 100755
index 3b0ba25..4604cd2
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -387,8 +387,25 @@
      * @hide
      */
     public static final int CAPABILITY_ADD_PARTICIPANT = 0x04000000;
+
+    /**
+     * Indicates that this {@code Connection} can be transferred to another
+     * number.
+     * Connection supports the blind and assured call transfer feature.
+     * @hide
+     */
+    public static final int CAPABILITY_TRANSFER = 0x08000000;
+
+    /**
+     * Indicates that this {@code Connection} can be transferred to another
+     * ongoing {@code Connection}.
+     * Connection supports the consultative call transfer feature.
+     * @hide
+     */
+    public static final int CAPABILITY_TRANSFER_CONSULTATIVE = 0x10000000;
+
     //**********************************************************************************************
-    // Next CAPABILITY value: 0x08000000
+    // Next CAPABILITY value: 0x20000000
     //**********************************************************************************************
 
     /**
@@ -967,6 +984,13 @@
         if ((capabilities & CAPABILITY_ADD_PARTICIPANT) == CAPABILITY_ADD_PARTICIPANT) {
             builder.append(isLong ? " CAPABILITY_ADD_PARTICIPANT" : " add_participant");
         }
+        if ((capabilities & CAPABILITY_TRANSFER) == CAPABILITY_TRANSFER) {
+            builder.append(isLong ? " CAPABILITY_TRANSFER" : " sup_trans");
+        }
+        if ((capabilities & CAPABILITY_TRANSFER_CONSULTATIVE)
+                == CAPABILITY_TRANSFER_CONSULTATIVE) {
+            builder.append(isLong ? " CAPABILITY_TRANSFER_CONSULTATIVE" : " sup_cTrans");
+        }
         builder.append("]");
         return builder.toString();
     }
@@ -3092,6 +3116,26 @@
     public void onReject(String replyMessage) {}
 
     /**
+     * Notifies this Connection, a request to transfer to a target number.
+     * @param number the number to transfer this {@link Connection} to.
+     * @param isConfirmationRequired when {@code true}, the {@link ConnectionService}
+     * should wait until the transfer has successfully completed before disconnecting
+     * the current {@link Connection}.
+     * When {@code false}, the {@link ConnectionService} should signal the network to
+     * perform the transfer, but should immediately disconnect the call regardless of
+     * the outcome of the transfer.
+     * @hide
+     */
+    public void onTransfer(@NonNull Uri number, boolean isConfirmationRequired) {}
+
+    /**
+     * Notifies this Connection, a request to transfer to another Connection.
+     * @param otherConnection the {@link Connection} to transfer this call to.
+     * @hide
+     */
+    public void onTransfer(@NonNull Connection otherConnection) {}
+
+    /**
      * Notifies this Connection of a request to silence the ringer.
      * <p>
      * The ringer may be silenced by any of the following methods:
@@ -3532,7 +3576,7 @@
      * ATIS-1000082.
      * @return the verification status.
      */
-    public @VerificationStatus int getCallerNumberVerificationStatus() {
+    public final @VerificationStatus int getCallerNumberVerificationStatus() {
         return mCallerNumberVerificationStatus;
     }
 
@@ -3544,7 +3588,7 @@
      * by
      * {@link ConnectionService#onCreateIncomingConnection(PhoneAccountHandle, ConnectionRequest)}.
      */
-    public void setCallerNumberVerificationStatus(
+    public final void setCallerNumberVerificationStatus(
             @VerificationStatus int callerNumberVerificationStatus) {
         mCallerNumberVerificationStatus = callerNumberVerificationStatus;
     }
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
old mode 100644
new mode 100755
index 2aea723..0dca006
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -128,6 +128,8 @@
     private static final String SESSION_ANSWER = "CS.an";
     private static final String SESSION_ANSWER_VIDEO = "CS.anV";
     private static final String SESSION_DEFLECT = "CS.def";
+    private static final String SESSION_TRANSFER = "CS.trans";
+    private static final String SESSION_CONSULTATIVE_TRANSFER = "CS.cTrans";
     private static final String SESSION_REJECT = "CS.r";
     private static final String SESSION_REJECT_MESSAGE = "CS.rWM";
     private static final String SESSION_SILENCE = "CS.s";
@@ -196,6 +198,8 @@
     private static final int MSG_CREATE_CONFERENCE_FAILED = 37;
     private static final int MSG_REJECT_WITH_REASON = 38;
     private static final int MSG_ADD_PARTICIPANT = 39;
+    private static final int MSG_EXPLICIT_CALL_TRANSFER = 40;
+    private static final int MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE = 41;
 
     private static Connection sNullConnection;
 
@@ -481,6 +485,38 @@
         }
 
         @Override
+        public void transfer(@NonNull String callId, @NonNull Uri number,
+                boolean isConfirmationRequired, Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_TRANSFER);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = number;
+                args.argi1 = isConfirmationRequired ? 1 : 0;
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(MSG_EXPLICIT_CALL_TRANSFER, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
+        public void consultativeTransfer(@NonNull String callId, @NonNull String otherCallId,
+                Session.Info sessionInfo) {
+            Log.startSession(sessionInfo, SESSION_CONSULTATIVE_TRANSFER);
+            try {
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = callId;
+                args.arg2 = otherCallId;
+                args.arg3 = Log.createSubsession();
+                mHandler.obtainMessage(
+                        MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE, args).sendToTarget();
+            } finally {
+                Log.endSession();
+            }
+        }
+
+        @Override
         public void silence(String callId, Session.Info sessionInfo) {
             Log.startSession(sessionInfo, SESSION_SILENCE);
             try {
@@ -1108,6 +1144,30 @@
                     }
                     break;
                 }
+                case MSG_EXPLICIT_CALL_TRANSFER: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession((Session) args.arg3, SESSION_HANDLER + SESSION_TRANSFER);
+                    try {
+                        final boolean isConfirmationRequired = args.argi1 == 1;
+                        transfer((String) args.arg1, (Uri) args.arg2, isConfirmationRequired);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
+                case MSG_EXPLICIT_CALL_TRANSFER_CONSULTATIVE: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Log.continueSession(
+                            (Session) args.arg3, SESSION_HANDLER + SESSION_CONSULTATIVE_TRANSFER);
+                    try {
+                        consultativeTransfer((String) args.arg1, (String) args.arg2);
+                    } finally {
+                        args.recycle();
+                        Log.endSession();
+                    }
+                    break;
+                }
                 case MSG_DISCONNECT: {
                     SomeArgs args = (SomeArgs) msg.obj;
                     Log.continueSession((Session) args.arg2, SESSION_HANDLER + SESSION_DISCONNECT);
@@ -2042,6 +2102,18 @@
         findConnectionForAction(callId, "reject").onReject(rejectReason);
     }
 
+    private void transfer(String callId, Uri number, boolean isConfirmationRequired) {
+        Log.d(this, "transfer %s", callId);
+        findConnectionForAction(callId, "transfer").onTransfer(number, isConfirmationRequired);
+    }
+
+    private void consultativeTransfer(String callId, String otherCallId) {
+        Log.d(this, "consultativeTransfer %s", callId);
+        Connection connection1 = findConnectionForAction(callId, "consultativeTransfer");
+        Connection connection2 = findConnectionForAction(otherCallId, " consultativeTransfer");
+        connection1.onTransfer(connection2);
+    }
+
     private void silence(String callId) {
         Log.d(this, "silence %s", callId);
         findConnectionForAction(callId, "silence").onSilence();
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
old mode 100644
new mode 100755
index 9d291740..dd6c153
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -16,6 +16,7 @@
 
 package android.telecom;
 
+import android.annotation.NonNull;
 import android.bluetooth.BluetoothDevice;
 import android.net.Uri;
 import android.os.Bundle;
@@ -102,6 +103,35 @@
     }
 
     /**
+     * Instructs Telecom to transfer the specified call.
+     *
+     * @param callId The identifier of the call to transfer.
+     * @param targetNumber The address to transfer to.
+     * @param isConfirmationRequired if {@code true} it will initiate ASSURED transfer,
+     * if {@code false}, it will initiate BLIND transfer.
+     */
+    public void transferCall(@NonNull String callId, @NonNull Uri targetNumber,
+            boolean isConfirmationRequired) {
+        try {
+            mAdapter.transferCall(callId, targetNumber, isConfirmationRequired);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Instructs Telecom to transfer the specified call to another ongoing call.
+     *
+     * @param callId The identifier of the call to transfer.
+     * @param otherCallId The identifier of the other call to which this will be transferred.
+     */
+    public void transferCall(@NonNull String callId, @NonNull String otherCallId) {
+        try {
+            mAdapter.consultativeTransfer(callId, otherCallId);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Instructs Telecom to disconnect the specified call.
      *
      * @param callId The identifier of the call to disconnect.
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index a397d77..fb54179 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -81,6 +81,11 @@
 
     void rejectWithMessage(String callId, String message, in Session.Info sessionInfo);
 
+    void transfer(String callId, in Uri number, boolean isConfirmationRequired,
+            in Session.Info sessionInfo);
+
+    void consultativeTransfer(String callId, String otherCallId, in Session.Info sessionInfo);
+
     void disconnect(String callId, in Session.Info sessionInfo);
 
     void silence(String callId, in Session.Info sessionInfo);
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
old mode 100644
new mode 100755
index 9beff22..edf1cf4
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -36,6 +36,10 @@
 
     void rejectCallWithReason(String callId, int rejectReason);
 
+    void transferCall(String callId, in Uri targetNumber, boolean isConfirmationRequired);
+
+    void consultativeTransfer(String callId, String otherCallId);
+
     void disconnectCall(String callId);
 
     void holdCall(String callId);
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java
index a27c480..9ae86c8 100644
--- a/telephony/java/android/telephony/Annotation.java
+++ b/telephony/java/android/telephony/Annotation.java
@@ -432,7 +432,7 @@
             DataFailCause.LIMITED_TO_IPV6,
             DataFailCause.VSNCP_TIMEOUT,
             DataFailCause.VSNCP_GEN_ERROR,
-            DataFailCause.VSNCP_APN_UNATHORIZED,
+            DataFailCause.VSNCP_APN_UNAUTHORIZED,
             DataFailCause.VSNCP_PDN_LIMIT_EXCEEDED,
             DataFailCause.VSNCP_NO_PDN_GATEWAY_ADDRESS,
             DataFailCause.VSNCP_PDN_GATEWAY_UNREACHABLE,
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index c51a852..a7e52ea 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -17,7 +17,6 @@
 package android.telephony;
 
 import android.Manifest;
-import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
@@ -28,7 +27,6 @@
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
-import android.net.ipsec.ike.SaProposal;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
 import android.service.carrier.CarrierService;
@@ -38,6 +36,8 @@
 import com.android.internal.telephony.ICarrierConfigLoader;
 import com.android.telephony.Rlog;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Provides access to telephony configuration values that are carrier-specific.
  */
@@ -840,7 +840,8 @@
     /**
      * The default flag specifying whether ETWS/CMAS test setting is forcibly disabled in
      * Settings->More->Emergency broadcasts menu even though developer options is turned on.
-     * @deprecated moved to cellbroadcastreceiver resource show_test_settings
+     * @deprecated Use {@code com.android.cellbroadcastreceiver.CellBroadcastReceiver} resource
+     * {@code show_test_settings} to control whether to show test alert settings or not.
      */
     @Deprecated
     public static final String KEY_CARRIER_FORCE_DISABLE_ETWS_CMAS_TEST_BOOL =
@@ -1989,6 +1990,13 @@
             "carrier_allow_deflect_ims_call_bool";
 
     /**
+     * Flag indicating whether the carrier supports explicit call transfer for an IMS call.
+     * @hide
+     */
+    public static final String KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL =
+            "carrier_allow_transfer_ims_call_bool";
+
+    /**
      * Flag indicating whether the carrier always wants to play an "on-hold" tone when a call has
      * been remotely held.
      * <p>
@@ -2018,10 +2026,15 @@
             "allow_add_call_during_video_call";
 
     /**
-     * When false, indicates that holding a video call is disabled
+     * When {@code true}, indicates that video calls can be put on hold in order to swap to another
+     * call (e.g. a new outgoing call).
+     * When {@code false}, indicates that video calls will be disconnected when swapping to another
+     * call.
+     * <p>
+     * This is {@code true} by default.
      */
-    public static final String KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL =
-            "allow_holding_video_call";
+    public static final String KEY_ALLOW_HOLD_VIDEO_CALL_BOOL =
+            "allow_hold_video_call_bool";
 
     /**
      * When true, indicates that the HD audio icon in the in-call screen should not be shown for
@@ -2468,6 +2481,21 @@
             "parameters_use_for_5g_nr_signal_bar_int";
 
     /**
+     * String array of default bandwidth values per network type.
+     * The entries should be of form "network_name:downstream,upstream", with values in Kbps.
+     * @hide
+     */
+    public static final String KEY_BANDWIDTH_STRING_ARRAY = "bandwidth_string_array";
+
+    /**
+     * For NR (non-standalone), whether to use the LTE value instead of NR value as the default for
+     * upstream bandwidth. Downstream bandwidth will still use the NR value as the default.
+     * @hide
+     */
+    public static final String KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL =
+            "bandwidth_nr_nsa_use_lte_value_for_upstream_bool";
+
+    /**
      * Key identifying if voice call barring notification is required to be shown to the user.
      * @hide
      */
@@ -2969,6 +2997,33 @@
             "5g_icon_display_grace_period_sec_int";
 
     /**
+     * Controls time in milliseconds until DcTracker reevaluates 5G connection state.
+     */
+    public static final String KEY_5G_WATCHDOG_TIME_MS_LONG = "5g_watchdog_time_long";
+
+    /**
+     * Whether NR (non-standalone) should be unmetered for all frequencies.
+     * If either {@link #KEY_UNMETERED_NR_NSA_MMWAVE_BOOL} or
+     * {@link #KEY_UNMETERED_NR_NSA_SUB6_BOOL} are true, then this value will be ignored.
+     * @hide
+     */
+    public static final String KEY_UNMETERED_NR_NSA_BOOL = "unmetered_nr_nsa_bool";
+
+    /**
+     * Whether NR (non-standalone) frequencies above 6GHz (millimeter wave) should be unmetered.
+     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
+     * @hide
+     */
+    public static final String KEY_UNMETERED_NR_NSA_MMWAVE_BOOL = "unmetered_nr_nsa_mmwave_bool";
+
+    /**
+     * Whether NR (non-standalone) frequencies below 6GHz (sub6) should be unmetered.
+     * If this is true, then the value for {@link #KEY_UNMETERED_NR_NSA_BOOL} will be ignored.
+     * @hide
+     */
+    public static final String KEY_UNMETERED_NR_NSA_SUB6_BOOL = "unmetered_nr_nsa_sub6_bool";
+
+    /**
      * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
      * this feature.
      * @hide
@@ -3040,11 +3095,6 @@
             "ping_test_before_data_switch_bool";
 
     /**
-     * Controls time in milliseconds until DcTracker reevaluates 5G connection state.
-     */
-    public static final String KEY_5G_WATCHDOG_TIME_MS_LONG =
-            "5g_watchdog_time_long";
-    /**
      * Controls whether to switch data to primary from opportunistic subscription
      * if primary is out of service. This control only affects system or 1st party app
      * initiated data switch, but will not override data switch initiated by privileged carrier apps
@@ -3391,6 +3441,25 @@
             "subscription_group_uuid_string";
 
     /**
+     * Data switch validation minimal gap time, in milliseconds.
+     *
+     * Which means, if the same subscription on the same network (based on MCC+MNC+TAC+subId)
+     * was recently validated (within this time gap), and Telephony receives a request to switch to
+     * it again, Telephony will skip the validation part and switch to it as soon as connection
+     * is setup, as if it's already validated.
+     *
+     * If the network was validated within the gap but the latest validation result is false, the
+     * validation will not be skipped.
+     *
+     * If not set or set to 0, validation will never be skipped.
+     * The max acceptable value of this config is 24 hours.
+     *
+     * @hide
+     */
+    public static final String KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG =
+            "data_switch_validation_min_gap_LONG";
+
+    /**
     * A boolean property indicating whether this subscription should be managed as an opportunistic
     * subscription.
     *
@@ -3480,369 +3549,6 @@
     public static final String KEY_SHOW_FORWARDED_NUMBER_BOOL =
             "show_forwarded_number_bool";
 
-    /**
-     * Configs used for epdg tunnel bring up.
-     *
-     * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange
-     *        Protocol Version 2 (IKEv2)</a>
-     */
-    public static final class Iwlan {
-        /** Prefix of all Epdg.KEY_* constants. */
-        public static final String KEY_PREFIX = "iwlan.";
-
-        /**
-         * Time in seconds after which the child security association session is terminated if
-         * rekey procedure is not successful. If not set or set to <= 0, the default value is
-         * 3600 seconds.
-         */
-        public static final String KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT =
-                KEY_PREFIX + "child_sa_rekey_hard_timer_sec_int";
-
-        /**
-         * Time in seconds after which the child session rekey procedure is started. If not set or
-         * set to <= 0, default value is 3000 seconds.
-         */
-        public static final String KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT =
-                KEY_PREFIX + "child_sa_rekey_soft_timer_sec_int";
-
-        /** Supported DH groups for IKE negotiation.
-         * Possible values are {@link #DH_GROUP_NONE}, {@link #DH_GROUP_1024_BIT_MODP},
-         * {@link #DH_GROUP_2048_BIT_MODP}
-         */
-        public static final String KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY =
-                KEY_PREFIX + "diffie_hellman_groups_int_array";
-
-        /**
-         * Time in seconds after which a dead peer detection (DPD) request is sent.
-         * If not set or set to <= 0, default value is 120 seconds.
-         */
-        public static final String KEY_DPD_TIMER_SEC_INT = KEY_PREFIX + "dpd_timer_sec_int";
-
-        /**
-         * Method used to authenticate epdg server.
-         * Possible values are {@link #AUTHENTICATION_METHOD_EAP_ONLY},
-         * {@link #AUTHENTICATION_METHOD_CERT}
-         */
-        public static final String KEY_EPDG_AUTHENTICATION_METHOD_INT =
-                KEY_PREFIX + "epdg_authentication_method_int";
-
-        /**
-         * A priority list of ePDG addresses to be used.
-         * Possible values are {@link #EPDG_ADDRESS_STATIC}, {@link #EPDG_ADDRESS_PLMN},
-         * {@link #EPDG_ADDRESS_PCO}
-         */
-        public static final String KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY =
-                KEY_PREFIX + "epdg_address_priority_int_array";
-
-        /** Epdg static IP address or FQDN */
-        public static final String KEY_EPDG_STATIC_ADDRESS_STRING =
-                KEY_PREFIX + "epdg_static_address_string";
-
-        /** Epdg static IP address or FQDN for roaming */
-        public static final String KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING =
-                KEY_PREFIX + "epdg_static_address_roaming_string";
-
-        /**
-         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of child
-         * session.
-         * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
-         * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
-         */
-        public static final String KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
-                KEY_PREFIX + "child_session_aes_cbc_key_size_int_array";
-
-        /**
-         * List of supported key sizes for AES counter (CTR) encryption mode of child session.
-         * Possible values are {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
-         * {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
-         */
-        public static final String KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
-                KEY_PREFIX + "child_encryption_aes_ctr_key_size_int_array";
-
-        /**
-         * List of supported encryption algorithms for child session.
-         * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
-         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
-         * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
-         */
-        public static final String KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
-                KEY_PREFIX + "supported_child_session_encryption_algorithms_int_array";
-
-        /** Controls if IKE message fragmentation is enabled. */
-        public static final String KEY_IKE_FRAGMENTATION_ENABLED_BOOL =
-                KEY_PREFIX + "ike_fragmentation_enabled_bool";
-
-        /**
-         * Time in seconds after which the IKE session is terminated if rekey procedure is not
-         * successful. If not set or set to <= 0, default value is 3600 seconds.
-         */
-        public static final String KEY_IKE_REKEY_HARD_TIMER_SEC_INT =
-                KEY_PREFIX + "ike_rekey_hard_timer_in_sec";
-
-        /**
-         * Time in seconds after which the IKE session rekey procedure is started. If not set or
-         * set to <= 0, default value is 3000 seconds.
-         */
-        public static final String KEY_IKE_REKEY_SOFT_TIMER_SEC_INT =
-                KEY_PREFIX + "ike_rekey_soft_timer_sec_int";
-
-        /**
-         * List of supported key sizes for AES Cipher Block Chaining (CBC) encryption mode of IKE
-         * session.
-         * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
-         *         {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
-         */
-        public static final String KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY =
-                KEY_PREFIX + "ike_session_encryption_aes_cbc_key_size_int_array";
-
-        /**
-         * List of supported key sizes for AES counter (CTR) encryption mode of IKE session.
-         * Possible values - {@link #KEY_LEN_UNUSED}, {@link #KEY_LEN_AES_128},
-         *         {@link #KEY_LEN_AES_192}, {@link #KEY_LEN_AES_256}
-         */
-        public static final String KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY =
-                KEY_PREFIX + "ike_session_aes_ctr_key_size_int_array";
-
-        /**
-        * List of supported encryption algorithms for IKE session.
-        * Possible values are {@link #ENCRYPTION_ALGORITHM_3DES},
-         * {@link #ENCRYPTION_ALGORITHM_AES_CBC}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_8},
-         * {@link #ENCRYPTION_ALGORITHM_AES_GCM_12}, {@link #ENCRYPTION_ALGORITHM_AES_GCM_16}
-        */
-        public static final String KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY =
-                KEY_PREFIX + "supported_ike_session_encryption_algorithms_int_array";
-
-        /**
-         * List of supported integrity algorithms for IKE session
-         * Possible values are {@link #INTEGRITY_ALGORITHM_NONE},
-         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA1_96}, {@link #INTEGRITY_ALGORITHM_AES_XCBC_96},
-         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_256_128},
-         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_384_192},
-         * {@link #INTEGRITY_ALGORITHM_HMAC_SHA2_512_256}
-         */
-        public static final String KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY =
-                KEY_PREFIX + "supported_integrity_algorithms_int_array";
-
-        /** Maximum number of retries for tunnel establishment. */
-        public static final String KEY_MAX_RETRIES_INT = KEY_PREFIX + "max_retries_int";
-
-        /** Controls if nat traversal should be enabled. */
-        public static final String KEY_NATT_ENABLED_BOOL = KEY_PREFIX + "natt_enabled_bool";
-
-        /**
-         * Time in seconds after which a NATT keep alive message is sent. If not set or set to <= 0,
-         * default value is 20 seconds.
-         */
-        public static final String KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT =
-                KEY_PREFIX + "natt_keep_alive_timer_sec_int";
-
-        /** List of comma separated MCC/MNCs used to create ePDG FQDN as per 3GPP TS 23.003 */
-        public static final String KEY_MCC_MNCS_STRING_ARRAY = KEY_PREFIX + "mcc_mncs_string_array";
-
-        /**
-         * List of supported pseudo random function algorithms for IKE session
-         * Possible values are {@link #PSEUDORANDOM_FUNCTION_HMAC_SHA1},
-         * {@link #PSEUDORANDOM_FUNCTION_AES128_XCBC}
-         */
-        public static final String KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY = KEY_PREFIX +
-                "supported_prf_algorithms_int_array";
-
-        /**
-         * Time in seconds after which IKE message is retransmitted. If not set or set to <= 0,
-         * default value is 2 seconds.
-         */
-        public static final String KEY_RETRANSMIT_TIMER_SEC_INT =
-                KEY_PREFIX + "retransmit_timer_sec_int";
-
-        /** @hide */
-        @IntDef({
-                AUTHENTICATION_METHOD_EAP_ONLY,
-                AUTHENTICATION_METHOD_CERT
-        })
-        public @interface AuthenticationMethodType {}
-
-        /**
-         * Certificate sent from the server is ignored. Only Extensible Authentication Protocol
-         * (EAP) is used to authenticate the server.
-         * EAP_ONLY_AUTH payload is added to IKE_AUTH request if supported.
-         * @see <a href="https://tools.ietf.org/html/rfc5998">RFC 5998</a>
-         */
-        public static final int AUTHENTICATION_METHOD_EAP_ONLY = 0;
-        /** Server is authenticated using its certificate. */
-        public static final int AUTHENTICATION_METHOD_CERT = 1;
-
-        /** @hide */
-        @IntDef({
-                EPDG_ADDRESS_STATIC,
-                EPDG_ADDRESS_PLMN,
-                EPDG_ADDRESS_PCO
-        })
-        public @interface EpdgAddressType {}
-
-        /** Use static epdg address. */
-        public static final int EPDG_ADDRESS_STATIC = 0;
-        /** Construct the epdg address using plmn. */
-        public static final int EPDG_ADDRESS_PLMN = 1;
-        /**
-         * Use the epdg address received in protocol configuration options (PCO) from the
-         * network.
-         */
-        public static final int EPDG_ADDRESS_PCO = 2;
-
-        /** @hide */
-        @IntDef({
-                KEY_LEN_UNUSED,
-                KEY_LEN_AES_128,
-                KEY_LEN_AES_192,
-                KEY_LEN_AES_256
-        })
-        public @interface EncrpytionKeyLengthType {}
-
-        public static final int KEY_LEN_UNUSED = SaProposal.KEY_LEN_UNUSED;
-        /** AES Encryption/Ciphering Algorithm key length 128 bits. */
-        public static final int KEY_LEN_AES_128 = SaProposal.KEY_LEN_AES_128;
-        /** AES Encryption/Ciphering Algorithm key length 192 bits. */
-        public static final int KEY_LEN_AES_192 = SaProposal.KEY_LEN_AES_192;
-        /** AES Encryption/Ciphering Algorithm key length 256 bits. */
-        public static final int KEY_LEN_AES_256 = SaProposal.KEY_LEN_AES_256;
-
-        /** @hide */
-        @IntDef({
-                DH_GROUP_NONE,
-                DH_GROUP_1024_BIT_MODP,
-                DH_GROUP_2048_BIT_MODP
-        })
-        public @interface DhGroup {}
-
-        /** None Diffie-Hellman Group. */
-        public static final int DH_GROUP_NONE = SaProposal.DH_GROUP_NONE;
-        /** 1024-bit MODP Diffie-Hellman Group. */
-        public static final int DH_GROUP_1024_BIT_MODP = SaProposal.DH_GROUP_1024_BIT_MODP;
-        /** 2048-bit MODP Diffie-Hellman Group. */
-        public static final int DH_GROUP_2048_BIT_MODP = SaProposal.DH_GROUP_2048_BIT_MODP;
-
-        /** @hide */
-        @IntDef({
-                ENCRYPTION_ALGORITHM_3DES,
-                ENCRYPTION_ALGORITHM_AES_CBC,
-                ENCRYPTION_ALGORITHM_AES_GCM_8,
-                ENCRYPTION_ALGORITHM_AES_GCM_12,
-                ENCRYPTION_ALGORITHM_AES_GCM_16
-        })
-        public @interface EncryptionAlgorithm {}
-
-        /** 3DES Encryption/Ciphering Algorithm. */
-        public static final int ENCRYPTION_ALGORITHM_3DES = SaProposal.ENCRYPTION_ALGORITHM_3DES;
-        /** AES-CBC Encryption/Ciphering Algorithm. */
-        public static final int ENCRYPTION_ALGORITHM_AES_CBC =
-                SaProposal.ENCRYPTION_ALGORITHM_AES_CBC;
-
-        /**
-         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 8-octet ICV
-         * (truncation).
-         */
-        public static final int ENCRYPTION_ALGORITHM_AES_GCM_8 =
-                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8;
-        /**
-         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 12-octet ICV
-         * (truncation).
-         */
-        public static final int ENCRYPTION_ALGORITHM_AES_GCM_12 =
-                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12;
-        /**
-         * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm with 16-octet ICV
-         * (truncation).
-         */
-        public static final int ENCRYPTION_ALGORITHM_AES_GCM_16 =
-                SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16;
-
-        /** @hide */
-        @IntDef({
-                INTEGRITY_ALGORITHM_NONE,
-                INTEGRITY_ALGORITHM_HMAC_SHA1_96,
-                INTEGRITY_ALGORITHM_AES_XCBC_96,
-                INTEGRITY_ALGORITHM_HMAC_SHA2_256_128,
-                INTEGRITY_ALGORITHM_HMAC_SHA2_384_192,
-                INTEGRITY_ALGORITHM_HMAC_SHA2_512_256
-        })
-        public @interface IntegrityAlgorithm {}
-
-        /** None Authentication/Integrity Algorithm. */
-        public static final int INTEGRITY_ALGORITHM_NONE = SaProposal.INTEGRITY_ALGORITHM_NONE;
-        /** HMAC-SHA1 Authentication/Integrity Algorithm. */
-        public static final int INTEGRITY_ALGORITHM_HMAC_SHA1_96 =
-                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA1_96;
-        /** AES-XCBC-96 Authentication/Integrity Algorithm. */
-        public static final int INTEGRITY_ALGORITHM_AES_XCBC_96 =
-                SaProposal.INTEGRITY_ALGORITHM_AES_XCBC_96;
-        /** HMAC-SHA256 Authentication/Integrity Algorithm with 128-bit truncation. */
-        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_256_128 =
-                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_256_128;
-        /** HMAC-SHA384 Authentication/Integrity Algorithm with 192-bit truncation. */
-        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_384_192 =
-                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_384_192;
-        /** HMAC-SHA512 Authentication/Integrity Algorithm with 256-bit truncation. */
-        public static final int INTEGRITY_ALGORITHM_HMAC_SHA2_512_256 =
-                SaProposal.INTEGRITY_ALGORITHM_HMAC_SHA2_512_256;
-
-        /** @hide */
-        @IntDef({
-                PSEUDORANDOM_FUNCTION_HMAC_SHA1,
-                PSEUDORANDOM_FUNCTION_AES128_XCBC
-        })
-        public @interface PseudorandomFunction {}
-
-        /** HMAC-SHA1 Pseudorandom Function. */
-        public static final int PSEUDORANDOM_FUNCTION_HMAC_SHA1 =
-                SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1;
-        /** AES128-XCBC Pseudorandom Function. */
-        public static final int PSEUDORANDOM_FUNCTION_AES128_XCBC =
-                SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC;
-
-        private Iwlan() {}
-
-        private static PersistableBundle getDefaults() {
-            PersistableBundle defaults = new PersistableBundle();
-            defaults.putInt(KEY_IKE_REKEY_SOFT_TIMER_SEC_INT, 3000);
-            defaults.putInt(KEY_IKE_REKEY_HARD_TIMER_SEC_INT, 3600);
-            defaults.putInt(KEY_CHILD_SA_REKEY_SOFT_TIMER_SEC_INT, 3000);
-            defaults.putInt(KEY_CHILD_SA_REKEY_HARD_TIMER_SEC_INT, 3600);
-            defaults.putInt(KEY_RETRANSMIT_TIMER_SEC_INT, 2);
-            defaults.putInt(KEY_DPD_TIMER_SEC_INT, 120);
-            defaults.putInt(KEY_MAX_RETRIES_INT, 3);
-            defaults.putIntArray(KEY_DIFFIE_HELLMAN_GROUPS_INT_ARRAY,
-                    new int[]{DH_GROUP_1024_BIT_MODP, DH_GROUP_2048_BIT_MODP});
-            defaults.putIntArray(KEY_SUPPORTED_IKE_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
-                    new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
-            defaults.putIntArray(KEY_SUPPORTED_CHILD_SESSION_ENCRYPTION_ALGORITHMS_INT_ARRAY,
-                    new int[]{ENCRYPTION_ALGORITHM_3DES, ENCRYPTION_ALGORITHM_AES_CBC});
-            defaults.putIntArray(KEY_SUPPORTED_INTEGRITY_ALGORITHMS_INT_ARRAY,
-                    new int[]{INTEGRITY_ALGORITHM_AES_XCBC_96, INTEGRITY_ALGORITHM_HMAC_SHA1_96,
-                            INTEGRITY_ALGORITHM_HMAC_SHA2_256_128});
-            defaults.putIntArray(KEY_SUPPORTED_PRF_ALGORITHMS_INT_ARRAY,
-                    new int[]{PSEUDORANDOM_FUNCTION_HMAC_SHA1, PSEUDORANDOM_FUNCTION_AES128_XCBC});
-            defaults.putBoolean(KEY_NATT_ENABLED_BOOL, true);
-            defaults.putInt(KEY_EPDG_AUTHENTICATION_METHOD_INT, AUTHENTICATION_METHOD_CERT);
-            defaults.putString(KEY_EPDG_STATIC_ADDRESS_STRING, "");
-            defaults.putString(KEY_EPDG_STATIC_ADDRESS_ROAMING_STRING, "");
-            defaults.putInt(KEY_NATT_KEEP_ALIVE_TIMER_SEC_INT, 20);
-            defaults.putIntArray(KEY_IKE_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
-                    new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
-            defaults.putIntArray(KEY_IKE_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
-                    new int[]{KEY_LEN_AES_128});
-            defaults.putIntArray(KEY_CHILD_SESSION_AES_CBC_KEY_SIZE_INT_ARRAY,
-                    new int[]{KEY_LEN_AES_128, KEY_LEN_AES_256});
-            defaults.putIntArray(KEY_CHILD_SESSION_AES_CTR_KEY_SIZE_INT_ARRAY,
-                    new int[]{KEY_LEN_AES_128});
-            defaults.putBoolean(KEY_IKE_FRAGMENTATION_ENABLED_BOOL, false);
-            defaults.putIntArray(KEY_EPDG_ADDRESS_PRIORITY_INT_ARRAY, new int[]{EPDG_ADDRESS_PLMN,
-                    EPDG_ADDRESS_STATIC});
-            defaults.putStringArray(KEY_MCC_MNCS_STRING_ARRAY, new String[]{});
-
-            return defaults;
-        }
-    }
-
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -3851,6 +3557,7 @@
         sDefaults.putString(KEY_CARRIER_CONFIG_VERSION_STRING, "");
         sDefaults.putBoolean(KEY_ALLOW_HOLD_IN_IMS_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_CARRIER_ALLOW_DEFLECT_IMS_CALL_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_ALLOW_TRANSFER_IMS_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_ALWAYS_PLAY_REMOTE_HOLD_TONE_BOOL, false);
         sDefaults.putBoolean(KEY_AUTO_RETRY_FAILED_WIFI_EMERGENCY_CALL, false);
         sDefaults.putBoolean(KEY_ADDITIONAL_CALL_SETTING_BOOL, true);
@@ -4147,7 +3854,7 @@
         sDefaults.putBoolean(KEY_DROP_VIDEO_CALL_WHEN_ANSWERING_AUDIO_CALL_BOOL, false);
         sDefaults.putBoolean(KEY_ALLOW_MERGE_WIFI_CALLS_WHEN_VOWIFI_OFF_BOOL, true);
         sDefaults.putBoolean(KEY_ALLOW_ADD_CALL_DURING_VIDEO_CALL_BOOL, true);
-        sDefaults.putBoolean(KEY_ALLOW_HOLDING_VIDEO_CALL_BOOL, true);
+        sDefaults.putBoolean(KEY_ALLOW_HOLD_VIDEO_CALL_BOOL, true);
         sDefaults.putBoolean(KEY_WIFI_CALLS_CAN_BE_HD_AUDIO, true);
         sDefaults.putBoolean(KEY_VIDEO_CALLS_CAN_BE_HD_AUDIO, true);
         sDefaults.putBoolean(KEY_GSM_CDMA_CALLS_CAN_BE_HD_AUDIO, false);
@@ -4263,6 +3970,13 @@
                 });
         sDefaults.putInt(KEY_PARAMETERS_USE_FOR_5G_NR_SIGNAL_BAR_INT,
                 CellSignalStrengthNr.USE_SSRSRP);
+        sDefaults.putStringArray(KEY_BANDWIDTH_STRING_ARRAY, new String[]{
+                "GPRS:24,24", "EDGE:70,18", "UMTS:115,115", "CDMA-IS95A:14,14", "CDMA-IS95B:14,14",
+                "1xRTT:30,30", "EvDo-rev.0:750,48", "EvDo-rev.A:950,550", "HSDPA:4300,620",
+                "HSUPA:4300,1800", "HSPA:4300,1800", "EvDo-rev.B:1500,550:", "eHRPD:750,48",
+                "HSPAP:13000,3400", "TD-SCDMA:115,115", "LTE:30000,15000", "NR_NSA:47000,15000",
+                "NR_NSA_MMWAVE:145000,15000", "NR_SA:145000,15000"});
+        sDefaults.putBoolean(KEY_BANDWIDTH_NR_NSA_USE_LTE_VALUE_FOR_UPSTREAM_BOOL, false);
         sDefaults.putString(KEY_WCDMA_DEFAULT_SIGNAL_STRENGTH_MEASUREMENT_STRING, "rssi");
         sDefaults.putBoolean(KEY_CONFIG_SHOW_ORIG_DIAL_STRING_FOR_CDMA_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_CALL_BLOCKING_DISABLED_NOTIFICATION_ALWAYS_BOOL, false);
@@ -4278,6 +3992,11 @@
         sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
                 "connected_mmwave:5G,connected:5G");
         sDefaults.putInt(KEY_5G_ICON_DISPLAY_GRACE_PERIOD_SEC_INT, 0);
+        /* Default value is 1 hour. */
+        sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
+        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
+        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
+        sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_SUB6_BOOL, false);
         sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
         sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
@@ -4296,8 +4015,6 @@
         /* Default value is 3 seconds. */
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 3000);
         sDefaults.putBoolean(KEY_PING_TEST_BEFORE_DATA_SWITCH_BOOL, true);
-        /* Default value is 1 hour. */
-        sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
         sDefaults.putBoolean(KEY_SWITCH_DATA_TO_PRIMARY_IF_PRIMARY_IS_OOS_BOOL, true);
         /* Default value is 60 seconds. */
         sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_PING_PONG_TIME_LONG, 60000);
@@ -4339,7 +4056,7 @@
         sDefaults.putAll(Wifi.getDefaults());
         sDefaults.putBoolean(ENABLE_EAP_METHOD_PREFIX_BOOL, false);
         sDefaults.putBoolean(KEY_SHOW_FORWARDED_NUMBER_BOOL, false);
-        sDefaults.putAll(Iwlan.getDefaults());
+        sDefaults.putLong(KEY_DATA_SWITCH_VALIDATION_MIN_GAP_LONG, TimeUnit.DAYS.toMillis(1));
     }
 
     /**
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index e1c4bef..8b7a243 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -30,10 +30,8 @@
 import java.util.Set;
 
 /**
- * Returned as the reason for a data connection failure as defined by modem and some local errors.
- * @hide
+ * DataFailCause collects data connection failure causes code from different sources.
  */
-@SystemApi
 public final class DataFailCause {
     /** There is no failure */
     public static final int NONE = 0;
@@ -841,8 +839,19 @@
     /**
      * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
      * configuration request because the requested APN is unauthorized.
+     *
+     * @deprecated Use {@link #VSNCP_APN_UNAUTHORIZED} instead.
+     *
+     * @hide
      */
-    public static final int VSNCP_APN_UNATHORIZED = 0x8BE;
+    @SystemApi
+    @Deprecated
+    public static final int VSNCP_APN_UNATHORIZED = 0x8BE; // NOTYPO
+    /**
+     * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
+     * configuration request because the requested APN is unauthorized.
+     */
+    public static final int VSNCP_APN_UNAUTHORIZED = 0x8BE;
     /**
      * Data call bring up fails in the VSNCP phase due to a network rejection of the VSNCP
      * configuration request because the PDN limit has been exceeded.
@@ -1318,6 +1327,7 @@
         sFailCauseMap.put(VSNCP_TIMEOUT, "VSNCP_TIMEOUT");
         sFailCauseMap.put(VSNCP_GEN_ERROR, "VSNCP_GEN_ERROR");
         sFailCauseMap.put(VSNCP_APN_UNATHORIZED, "VSNCP_APN_UNATHORIZED");
+        sFailCauseMap.put(VSNCP_APN_UNAUTHORIZED, "VSNCP_APN_UNAUTHORIZED");
         sFailCauseMap.put(VSNCP_PDN_LIMIT_EXCEEDED, "VSNCP_PDN_LIMIT_EXCEEDED");
         sFailCauseMap.put(VSNCP_NO_PDN_GATEWAY_ADDRESS, "VSNCP_NO_PDN_GATEWAY_ADDRESS");
         sFailCauseMap.put(VSNCP_PDN_GATEWAY_UNREACHABLE, "VSNCP_PDN_GATEWAY_UNREACHABLE");
@@ -1423,8 +1433,8 @@
                 if (configManager != null) {
                     PersistableBundle b = configManager.getConfigForSubId(subId);
                     if (b != null) {
-                        String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager.
-                                KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
+                        String[] permanentFailureStrings = b.getStringArray(CarrierConfigManager
+                                .KEY_CARRIER_DATA_CALL_PERMANENT_FAILURE_STRINGS);
                         if (permanentFailureStrings != null) {
                             permanentFailureSet = new HashSet<>();
                             for (Map.Entry<Integer, String> e : sFailCauseMap.entrySet()) {
diff --git a/telephony/java/android/telephony/ModemInfo.java b/telephony/java/android/telephony/ModemInfo.java
new file mode 100644
index 0000000..c0833af
--- /dev/null
+++ b/telephony/java/android/telephony/ModemInfo.java
@@ -0,0 +1,109 @@
+/*
+ * 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.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Information of a single logical modem indicating
+ * its id, supported rats and whether it supports voice or data, etc.
+ * @hide
+ */
+public class ModemInfo implements Parcelable {
+    public final int modemId;
+    public final int rat; /* bitset */
+    public final boolean isVoiceSupported;
+    public final boolean isDataSupported;
+
+    // TODO b/121394331: Clean up this class after V1_1.PhoneCapability cleanup.
+    public ModemInfo(int modemId) {
+        this(modemId, 0, true, true);
+    }
+
+    public ModemInfo(int modemId, int rat, boolean isVoiceSupported, boolean isDataSupported) {
+        this.modemId = modemId;
+        this.rat = rat;
+        this.isVoiceSupported = isVoiceSupported;
+        this.isDataSupported = isDataSupported;
+    }
+
+    public ModemInfo(Parcel in) {
+        modemId = in.readInt();
+        rat = in.readInt();
+        isVoiceSupported = in.readBoolean();
+        isDataSupported = in.readBoolean();
+    }
+
+    @Override
+    public String toString() {
+        return "modemId=" + modemId + " rat=" + rat + " isVoiceSupported:" + isVoiceSupported
+                + " isDataSupported:" + isDataSupported;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(modemId, rat, isVoiceSupported, isDataSupported);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == null || !(o instanceof ModemInfo) || hashCode() != o.hashCode()) {
+            return false;
+        }
+
+        if (this == o) {
+            return true;
+        }
+
+        ModemInfo s = (ModemInfo) o;
+
+        return (modemId == s.modemId
+                && rat == s.rat
+                && isVoiceSupported == s.isVoiceSupported
+                && isDataSupported == s.isDataSupported);
+    }
+
+    /**
+     * {@link Parcelable#describeContents}
+     */
+    public @ContentsFlags int describeContents() {
+        return 0;
+    }
+
+    /**
+     * {@link Parcelable#writeToParcel}
+     */
+    public void writeToParcel(Parcel dest, @WriteFlags int flags) {
+        dest.writeInt(modemId);
+        dest.writeInt(rat);
+        dest.writeBoolean(isVoiceSupported);
+        dest.writeBoolean(isDataSupported);
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<ModemInfo> CREATOR = new Parcelable.Creator() {
+        public ModemInfo createFromParcel(Parcel in) {
+            return new ModemInfo(in);
+        }
+
+        public ModemInfo[] newArray(int size) {
+            return new ModemInfo[size];
+        }
+    };
+}
diff --git a/telephony/java/android/telephony/PhoneCapability.java b/telephony/java/android/telephony/PhoneCapability.java
index a537928..6571858 100644
--- a/telephony/java/android/telephony/PhoneCapability.java
+++ b/telephony/java/android/telephony/PhoneCapability.java
@@ -16,20 +16,12 @@
 
 package android.telephony;
 
-import android.annotation.LongDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.telephony.AccessNetworkConstants.AccessNetworkType;
-import android.telephony.AccessNetworkConstants.RadioAccessNetworkType;
-import android.telephony.TelephonyManager.NetworkTypeBitMask;
 
-import com.android.internal.telephony.util.TelephonyUtils;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
@@ -38,365 +30,69 @@
  * are shared between those modems defined by list of modem IDs.
  */
 public final class PhoneCapability implements Parcelable {
-    /** Modem feature indicating 3GPP2 capability. */
-    public static final long MODEM_FEATURE_3GPP2_REG = 1 << 0;
-    /** Modem feature indicating 3GPP capability. */
-    public static final long MODEM_FEATURE_3GPP_REG = 1 << 1;
-    /** Modem feature indicating CDMA 2000 with EHRPD capability. */
-    public static final long MODEM_FEATURE_CDMA2000_EHRPD_REG = 1 << 2;
-    /** Modem feature indicating GSM capability. */
-    public static final long MODEM_FEATURE_GERAN_REG = 1 << 3;
-    /** Modem feature indicating UMTS capability. */
-    public static final long MODEM_FEATURE_UTRAN_REG = 1 << 4;
-    /** Modem feature indicating LTE capability. */
-    public static final long MODEM_FEATURE_EUTRAN_REG = 1 << 5;
-    /** Modem feature indicating 5G capability.*/
-    public static final long MODEM_FEATURE_NGRAN_REG = 1 << 6;
-    /** Modem feature indicating EN-DC capability. */
-    public static final long MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG = 1 << 7;
-    /** Modem feature indicating VoLTE capability (IMS registered). */
-    public static final long MODEM_FEATURE_PS_VOICE_REG = 1 << 8;
-    /** Modem feature indicating CS voice call capability. */
-    public static final long MODEM_FEATURE_CS_VOICE_SESSION = 1 << 9;
-    /** Modem feature indicating Internet connection capability. */
-    public static final long MODEM_FEATURE_INTERACTIVE_DATA_SESSION = 1 << 10;
-    /**
-     * Modem feature indicating dedicated bearer capability.
-     * For services that require a high level QoS (eg. VoLTE), the network can create
-     * a dedicated bearer with the required QoS on top of an established default bearer.
-     * This will provide a dedicated tunnel for one or more specific traffic types.
-     */
-    public static final long MODEM_FEATURE_DEDICATED_BEARER = 1 << 11;
-    /** Modem feature indicating network scan capability. */
-    public static final long MODEM_FEATURE_NETWORK_SCAN = 1 << 12;
-    /** Modem feature indicating corresponding SIM has CDMA capability. */
-    public static final long MODEM_FEATURE_CSIM = 1 << 13;
-
+    // Hardcoded default DSDS capability.
     /** @hide */
-    @LongDef(flag = true, prefix = {"MODEM_FEATURE_" }, value = {
-            MODEM_FEATURE_3GPP2_REG,
-            MODEM_FEATURE_3GPP_REG,
-            MODEM_FEATURE_CDMA2000_EHRPD_REG,
-            MODEM_FEATURE_GERAN_REG,
-            MODEM_FEATURE_UTRAN_REG,
-            MODEM_FEATURE_EUTRAN_REG,
-            MODEM_FEATURE_NGRAN_REG,
-            MODEM_FEATURE_EUTRA_NR_DUAL_CONNECTIVITY_REG,
-            MODEM_FEATURE_PS_VOICE_REG,
-            MODEM_FEATURE_CS_VOICE_SESSION,
-            MODEM_FEATURE_INTERACTIVE_DATA_SESSION,
-            MODEM_FEATURE_DEDICATED_BEARER,
-            MODEM_FEATURE_NETWORK_SCAN,
-            MODEM_FEATURE_CSIM,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface ModemFeature {
-    }
-
-    /**
-     * Hardcoded default DSDS capability.
-     * @hide
-     */
     public static final PhoneCapability DEFAULT_DSDS_CAPABILITY;
-    /**
-     * Hardcoded default Single SIM single standby capability.
-     * @hide
-     */
+    // Hardcoded default Single SIM single standby capability.
+    /** @hide */
     public static final PhoneCapability DEFAULT_SSSS_CAPABILITY;
 
     static {
-        List<List<Long>> capabilities = new ArrayList<>();
-        List<Long> modem1 = new ArrayList<>();
-        List<Long> modem2 = new ArrayList<>();
-        modem1.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
-                | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_CS_VOICE_SESSION
-                | MODEM_FEATURE_INTERACTIVE_DATA_SESSION | MODEM_FEATURE_DEDICATED_BEARER);
-        modem2.add(MODEM_FEATURE_GERAN_REG | MODEM_FEATURE_UTRAN_REG | MODEM_FEATURE_EUTRAN_REG
-                | MODEM_FEATURE_PS_VOICE_REG | MODEM_FEATURE_INTERACTIVE_DATA_SESSION
-                | MODEM_FEATURE_DEDICATED_BEARER);
-        capabilities.add(modem1);
-        capabilities.add(modem2);
-        List<String> uuids = new ArrayList<>();
-        uuids.add("com.xxxx.lm0");
-        uuids.add("com.xxxx.lm1");
-        long rats = TelephonyManager.NETWORK_TYPE_BITMASK_GSM
-                | TelephonyManager.NETWORK_TYPE_BITMASK_GPRS
-                | TelephonyManager.NETWORK_TYPE_BITMASK_EDGE
-                | TelephonyManager.NETWORK_TYPE_BITMASK_UMTS
-                | TelephonyManager.NETWORK_TYPE_BITMASK_LTE;
-        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
-                uuids, null, capabilities);
+        ModemInfo modemInfo1 = new ModemInfo(0, 0, true, true);
+        ModemInfo modemInfo2 = new ModemInfo(1, 0, true, true);
 
-        capabilities = new ArrayList<>();
-        capabilities.add(modem1);
-        uuids = new ArrayList<>();
-        uuids.add("com.xxxx.lm0");
-        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(0, 0, 0, 0, 0, rats, null, null, null, null,
-                uuids, null, capabilities);
+        List<ModemInfo> logicalModemList = new ArrayList<>();
+        logicalModemList.add(modemInfo1);
+        logicalModemList.add(modemInfo2);
+        DEFAULT_DSDS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
+
+        logicalModemList = new ArrayList<>();
+        logicalModemList.add(modemInfo1);
+        DEFAULT_SSSS_CAPABILITY = new PhoneCapability(1, 1, 0, logicalModemList, false);
     }
 
-    private final int mUtranUeCategoryDl;
-    private final int mUtranUeCategoryUl;
-    private final int mEutranUeCategoryDl;
-    private final int mEutranUeCategoryUl;
-    private final long mPsDataConnectionLingerTimeMillis;
-    private final @NetworkTypeBitMask long mSupportedRats;
-    private final List<Integer> mGeranBands;
-    private final List<Integer> mUtranBands;
-    private final List<Integer> mEutranBands;
-    private final List<Integer> mNgranBands;
-    private final List<String> mLogicalModemUuids;
-    private final List<SimSlotCapability> mSimSlotCapabilities;
-    private final @ModemFeature List<List<Long>> mConcurrentFeaturesSupport;
+    /** @hide */
+    public final int maxActiveVoiceCalls;
+    /** @hide */
+    public final int maxActiveData;
+    /** @hide */
+    public final int max5G;
+    /** @hide */
+    public final boolean validationBeforeSwitchSupported;
+    /** @hide */
+    public final List<ModemInfo> logicalModemList;
 
-    /**
-     * Default constructor to create a PhoneCapability object.
-     * @param utranUeCategoryDl 3GPP UE category for UTRAN downlink.
-     * @param utranUeCategoryUl 3GPP UE category for UTRAN uplink.
-     * @param eutranUeCategoryDl 3GPP UE category for EUTRAN downlink.
-     * @param eutranUeCategoryUl 3GPP UE category for EUTRAN uplink.
-     * @param psDataConnectionLingerTimeMillis length of the grace period to allow a smooth
-     *                                         "handover" between data connections.
-     * @param supportedRats all radio access technologies this phone is capable of supporting.
-     * @param geranBands list of supported {@link AccessNetworkConstants.GeranBand}.
-     * @param utranBands list of supported {@link AccessNetworkConstants.UtranBand}.
-     * @param eutranBands list of supported {@link AccessNetworkConstants.EutranBand}.
-     * @param ngranBands list of supported {@link AccessNetworkConstants.NgranBands}.
-     * @param logicalModemUuids list of logical modem UUIDs, typically of the form
-     *                          "com.xxxx.lmX", where X is the logical modem ID.
-     * @param simSlotCapabilities list of {@link SimSlotCapability} for the device
-     * @param concurrentFeaturesSupport list of list of concurrently supportable modem feature sets.
-     * @hide
-     */
-    public PhoneCapability(int utranUeCategoryDl, int utranUeCategoryUl, int eutranUeCategoryDl,
-            int eutranUeCategoryUl, long psDataConnectionLingerTimeMillis,
-            @NetworkTypeBitMask long supportedRats, @Nullable List<Integer> geranBands,
-            @Nullable List<Integer> utranBands, @Nullable List<Integer> eutranBands,
-            @Nullable List<Integer> ngranBands, @Nullable List<String> logicalModemUuids,
-            @Nullable List<SimSlotCapability> simSlotCapabilities,
-            @Nullable @ModemFeature List<List<Long>> concurrentFeaturesSupport) {
-        this.mUtranUeCategoryDl = utranUeCategoryDl;
-        this.mUtranUeCategoryUl = utranUeCategoryUl;
-        this.mEutranUeCategoryDl = eutranUeCategoryDl;
-        this.mEutranUeCategoryUl = eutranUeCategoryUl;
-        this.mPsDataConnectionLingerTimeMillis = psDataConnectionLingerTimeMillis;
-        this.mSupportedRats = supportedRats;
-        this.mGeranBands = TelephonyUtils.emptyIfNull(geranBands);
-        this.mUtranBands = TelephonyUtils.emptyIfNull(utranBands);
-        this.mEutranBands = TelephonyUtils.emptyIfNull(eutranBands);
-        this.mNgranBands = TelephonyUtils.emptyIfNull(ngranBands);
-        this.mLogicalModemUuids = TelephonyUtils.emptyIfNull(logicalModemUuids);
-        this.mSimSlotCapabilities = TelephonyUtils.emptyIfNull(simSlotCapabilities);
-        this.mConcurrentFeaturesSupport = TelephonyUtils.emptyIfNull(concurrentFeaturesSupport);
-    }
-
-    private PhoneCapability(Parcel in) {
-        mUtranUeCategoryDl = in.readInt();
-        mUtranUeCategoryUl = in.readInt();
-        mEutranUeCategoryDl = in.readInt();
-        mEutranUeCategoryUl = in.readInt();
-        mPsDataConnectionLingerTimeMillis = in.readLong();
-        mSupportedRats = in.readLong();
-        mGeranBands = new ArrayList<>();
-        in.readList(mGeranBands, Integer.class.getClassLoader());
-        mUtranBands = new ArrayList<>();
-        in.readList(mUtranBands, Integer.class.getClassLoader());
-        mEutranBands = new ArrayList<>();
-        in.readList(mEutranBands, Integer.class.getClassLoader());
-        mNgranBands = new ArrayList<>();
-        in.readList(mNgranBands, Integer.class.getClassLoader());
-        mLogicalModemUuids = in.createStringArrayList();
-        mSimSlotCapabilities = in.createTypedArrayList(SimSlotCapability.CREATOR);
-        int length = in.readInt();
-        mConcurrentFeaturesSupport = new ArrayList<>();
-        for (int i = 0; i < length; i++) {
-            ArrayList<Long> feature = new ArrayList<>();
-            in.readList(feature, Long.class.getClassLoader());
-            mConcurrentFeaturesSupport.add(feature);
-        }
-    }
-
-    /**
-     * 3GPP UE category for a given Radio Access Network and direction.
-     *
-     * References are:
-     * TS 25.306 Table 4.1a     EUTRAN downlink
-     * TS 25.306 Table 5.1a-2   EUTRAN uplink
-     * TS 25.306 Table 5.1a     UTRAN downlink
-     * TS 25.306 Table 5.1g     UTRAN uplink
-     *
-     * @param uplink true for uplink direction and false for downlink direction.
-     * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
-     * @return the UE category, or -1 if it is not supported.
-     */
-    public int getUeCategory(boolean uplink, @RadioAccessNetworkType int accessNetworkType) {
-        if (uplink) {
-            switch (accessNetworkType) {
-                case AccessNetworkType.UTRAN: return mUtranUeCategoryUl;
-                case AccessNetworkType.EUTRAN: return mEutranUeCategoryUl;
-                default: return -1;
-            }
-        } else {
-            switch (accessNetworkType) {
-                case AccessNetworkType.UTRAN: return mUtranUeCategoryDl;
-                case AccessNetworkType.EUTRAN: return mEutranUeCategoryDl;
-                default: return -1;
-            }
-        }
-    }
-
-    /**
-     * In cellular devices that support a greater number of logical modems than
-     * Internet connections, some devices support a grace period to allow a smooth "handover"
-     * between those connections. If that feature is supported, then this API will provide
-     * the length of that grace period in milliseconds. If it is not supported, the default value
-     * for the grace period is 0.
-     * @return handover linger time in milliseconds, or 0 if it is not supported.
-     */
-    public long getPsDataConnectionLingerTimeMillis() {
-        return mPsDataConnectionLingerTimeMillis;
-    }
-
-    /**
-     * The radio access technologies this device is capable of supporting.
-     * @return a bitfield of all supported network types, defined in {@link TelephonyManager}
-     */
-    public @NetworkTypeBitMask long getSupportedRats() {
-        return mSupportedRats;
-    }
-
-    /**
-     * List of supported cellular bands for the given accessNetworkType.
-     * @param accessNetworkType accessNetworkType, defined in {@link AccessNetworkType}.
-     * @return a list of bands, or an empty list if the access network type is unsupported.
-     */
-    public @NonNull List<Integer> getBands(@RadioAccessNetworkType int accessNetworkType) {
-        switch (accessNetworkType) {
-            case AccessNetworkType.GERAN: return mGeranBands;
-            case AccessNetworkType.UTRAN: return mUtranBands;
-            case AccessNetworkType.EUTRAN: return mEutranBands;
-            case AccessNetworkType.NGRAN: return mNgranBands;
-            default: return new ArrayList<>();
-        }
-    }
-
-    /**
-     * List of logical modem UUIDs, each typically "com.xxxx.lmX", where X is the logical modem ID.
-     * @return a list of modem UUIDs, one for every logical modem the device has.
-     */
-    public @NonNull List<String> getLogicalModemUuids() {
-        return mLogicalModemUuids;
-    }
-
-    /**
-     * List of {@link SimSlotCapability} for the device. The order of SIMs corresponds to the
-     * order of modems in {@link #getLogicalModemUuids}.
-     * @return a list of SIM slot capabilities, one for every SIM slot the device has.
-     */
-    public @NonNull List<SimSlotCapability> getSimSlotCapabilities() {
-        return mSimSlotCapabilities;
-    }
-
-    /**
-     * A List of Lists of concurrently supportable modem feature sets.
-     *
-     * Each entry in the top-level list is an independent configuration across all modems
-     * that describes the capabilities of the device as a whole.
-     *
-     * Each entry in the second-level list is a bitfield of ModemFeatures that describes
-     * the capabilities for a single modem. In the second-level list, the order of the modems
-     * corresponds to order of the UUIDs in {@link #getLogicalModemUuids}.
-     *
-     * For symmetric capabilities that can only be active on one modem at a time, there will be
-     * multiple configurations (equal to the number of modems) that shows it active on each modem.
-     * For asymmetric capabilities that are only available on one of the modems, all configurations
-     * will have that capability on just that one modem.
-     *
-     * The example below shows the concurrentFeaturesSupport for a 3-modem device with
-     * theoretical capabilities SYMMETRIC (available on all modems, but only one at a time) and
-     * ASYMMETRIC (only available on the first modem):
-     * {
-     *      Configuration 1: ASYMMETRIC and SYMMETRIC on modem 1, modem 2 empty, modem 3 empty
-     *      {(ASYMMETRIC | SYMMETRIC), (), ()},
-     *
-     *      Configuration 2: ASYMMETRIC on modem 1, SYMMETRIC on modem 2, modem 3 empty
-     *      {(ASYMMETRIC), (SYMMETRIC), ()},
-     *
-     *      Configuration 3: ASYMMETRIC on modem 1, modem 2 empty, SYMMETRIC on modem 3
-     *      {(ASYMMETRIC), (), (SYMMETRIC)}
-     * }
-     *
-     * @return List of all concurrently supportable modem features.
-     */
-    public @NonNull @ModemFeature List<List<Long>> getConcurrentFeaturesSupport() {
-        return mConcurrentFeaturesSupport;
-    }
-
-    /**
-     * How many modems can simultaneously have PS attached.
-     * @return maximum number of active PS voice connections.
-     */
-    public int getMaxActivePsVoice() {
-        return countFeature(MODEM_FEATURE_PS_VOICE_REG);
-    }
-
-    /**
-     * How many modems can simultaneously support active data connections.
-     * For DSDS, this will be 1, and for DSDA this will be 2.
-     * @return maximum number of active Internet data sessions.
-     */
-    public int getMaxActiveInternetData() {
-        return countFeature(MODEM_FEATURE_INTERACTIVE_DATA_SESSION);
-    }
-
-    /**
-     * How many modems can simultaneously have dedicated bearer capability.
-     * @return maximum number of active dedicated bearers.
-     */
-    public int getMaxActiveDedicatedBearers() {
-        return countFeature(MODEM_FEATURE_DEDICATED_BEARER);
-    }
-
-    /**
-     * Whether the CBRS band 48 is supported or not.
-     * @return true if any RadioAccessNetwork supports CBRS and false if none do.
-     * @hide
-     */
-    public boolean isCbrsSupported() {
-        return mEutranBands.contains(AccessNetworkConstants.EutranBand.BAND_48)
-                || mNgranBands.contains(AccessNetworkConstants.NgranBands.BAND_48);
-    }
-
-    private int countFeature(@ModemFeature long feature) {
-        int count = 0;
-        for (long featureSet : mConcurrentFeaturesSupport.get(0)) {
-            if ((featureSet & feature) != 0) {
-                count++;
-            }
-        }
-        return count;
+    /** @hide */
+    public PhoneCapability(int maxActiveVoiceCalls, int maxActiveData, int max5G,
+            List<ModemInfo> logicalModemList, boolean validationBeforeSwitchSupported) {
+        this.maxActiveVoiceCalls = maxActiveVoiceCalls;
+        this.maxActiveData = maxActiveData;
+        this.max5G = max5G;
+        // Make sure it's not null.
+        this.logicalModemList = logicalModemList == null ? new ArrayList<>() : logicalModemList;
+        this.validationBeforeSwitchSupported = validationBeforeSwitchSupported;
     }
 
     @Override
     public String toString() {
-        return "utranUeCategoryDl=" + mUtranUeCategoryDl
-                + " utranUeCategoryUl=" + mUtranUeCategoryUl
-                + " eutranUeCategoryDl=" + mEutranUeCategoryDl
-                + " eutranUeCategoryUl=" + mEutranUeCategoryUl
-                + " psDataConnectionLingerTimeMillis=" + mPsDataConnectionLingerTimeMillis
-                + " supportedRats=" + mSupportedRats + " geranBands=" + mGeranBands
-                + " utranBands=" + mUtranBands + " eutranBands=" + mEutranBands
-                + " ngranBands=" + mNgranBands + " logicalModemUuids=" + mLogicalModemUuids
-                + " simSlotCapabilities=" + mSimSlotCapabilities
-                + " concurrentFeaturesSupport=" + mConcurrentFeaturesSupport;
+        return "maxActiveVoiceCalls=" + maxActiveVoiceCalls + " maxActiveData=" + maxActiveData
+                + " max5G=" + max5G + "logicalModemList:"
+                + Arrays.toString(logicalModemList.toArray());
+    }
+
+    private PhoneCapability(Parcel in) {
+        maxActiveVoiceCalls = in.readInt();
+        maxActiveData = in.readInt();
+        max5G = in.readInt();
+        validationBeforeSwitchSupported = in.readBoolean();
+        logicalModemList = new ArrayList<>();
+        in.readList(logicalModemList, ModemInfo.class.getClassLoader());
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(mUtranUeCategoryDl, mUtranUeCategoryUl, mEutranUeCategoryDl,
-                mEutranUeCategoryUl, mPsDataConnectionLingerTimeMillis, mSupportedRats, mGeranBands,
-                mUtranBands, mEutranBands, mNgranBands, mLogicalModemUuids, mSimSlotCapabilities,
-                mConcurrentFeaturesSupport);
+        return Objects.hash(maxActiveVoiceCalls, maxActiveData, max5G, logicalModemList,
+                validationBeforeSwitchSupported);
     }
 
     @Override
@@ -411,19 +107,11 @@
 
         PhoneCapability s = (PhoneCapability) o;
 
-        return (mUtranUeCategoryDl == s.mUtranUeCategoryDl
-                && mUtranUeCategoryUl == s.mUtranUeCategoryUl
-                && mEutranUeCategoryDl == s.mEutranUeCategoryDl
-                && mEutranUeCategoryUl == s.mEutranUeCategoryUl
-                && mPsDataConnectionLingerTimeMillis == s.mPsDataConnectionLingerTimeMillis
-                && mSupportedRats == s.mSupportedRats
-                && mGeranBands.equals(s.mGeranBands)
-                && mUtranBands.equals(s.mUtranBands)
-                && mEutranBands.equals(s.mEutranBands)
-                && mNgranBands.equals(s.mNgranBands)
-                && mLogicalModemUuids.equals(s.mLogicalModemUuids)
-                && mSimSlotCapabilities.equals(s.mSimSlotCapabilities)
-                && mConcurrentFeaturesSupport.equals(s.mConcurrentFeaturesSupport));
+        return (maxActiveVoiceCalls == s.maxActiveVoiceCalls
+                && maxActiveData == s.maxActiveData
+                && max5G == s.max5G
+                && validationBeforeSwitchSupported == s.validationBeforeSwitchSupported
+                && logicalModemList.equals(s.logicalModemList));
     }
 
     /**
@@ -436,33 +124,21 @@
     /**
      * {@link Parcelable#writeToParcel}
      */
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mUtranUeCategoryDl);
-        dest.writeInt(mUtranUeCategoryUl);
-        dest.writeInt(mEutranUeCategoryDl);
-        dest.writeInt(mEutranUeCategoryUl);
-        dest.writeLong(mPsDataConnectionLingerTimeMillis);
-        dest.writeLong(mSupportedRats);
-        dest.writeList(mGeranBands);
-        dest.writeList(mUtranBands);
-        dest.writeList(mEutranBands);
-        dest.writeList(mNgranBands);
-        dest.writeStringList(mLogicalModemUuids);
-        dest.writeTypedList(mSimSlotCapabilities);
-        dest.writeInt(mConcurrentFeaturesSupport.size());
-        for (List<Long> feature : mConcurrentFeaturesSupport) {
-            dest.writeList(feature);
-        }
+    public void writeToParcel(@NonNull Parcel dest, @Parcelable.WriteFlags int flags) {
+        dest.writeInt(maxActiveVoiceCalls);
+        dest.writeInt(maxActiveData);
+        dest.writeInt(max5G);
+        dest.writeBoolean(validationBeforeSwitchSupported);
+        dest.writeList(logicalModemList);
     }
 
-    public static final @NonNull Parcelable.Creator<PhoneCapability> CREATOR =
-            new Parcelable.Creator() {
-                public PhoneCapability createFromParcel(Parcel in) {
-                    return new PhoneCapability(in);
-                }
+    public static final @android.annotation.NonNull Parcelable.Creator<PhoneCapability> CREATOR = new Parcelable.Creator() {
+        public PhoneCapability createFromParcel(Parcel in) {
+            return new PhoneCapability(in);
+        }
 
-                public PhoneCapability[] newArray(int size) {
-                    return new PhoneCapability[size];
-                }
-            };
+        public PhoneCapability[] newArray(int size) {
+            return new PhoneCapability[size];
+        }
+    };
 }
diff --git a/telephony/java/android/telephony/PreciseDataConnectionState.java b/telephony/java/android/telephony/PreciseDataConnectionState.java
index 708adeb..e37a9b9 100644
--- a/telephony/java/android/telephony/PreciseDataConnectionState.java
+++ b/telephony/java/android/telephony/PreciseDataConnectionState.java
@@ -257,8 +257,7 @@
      * Return the cause code for the most recent change in {@link #getState}. In the event of an
      * error, this cause code will be non-zero.
      */
-    // FIXME(b144774287): some of these cause codes should have a prescribed meaning.
-    public int getLastCauseCode() {
+    public @DataFailureCause int getLastCauseCode() {
         return mFailCause;
     }
 
diff --git a/telephony/java/android/telephony/SimSlotCapability.java b/telephony/java/android/telephony/SimSlotCapability.java
deleted file mode 100644
index b4fef46..0000000
--- a/telephony/java/android/telephony/SimSlotCapability.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.telephony;
-
-import android.annotation.IntDef;
-import android.annotation.NonNull;
-import android.os.Parcel;
-import android.os.Parcelable;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.util.Objects;
-
-/**
- * Capabilities for a SIM Slot.
- */
-public final class SimSlotCapability implements Parcelable {
-    /** Slot type for UICC (removable SIM). */
-    public static final int SLOT_TYPE_UICC = 1;
-    /** Slot type for iUICC/iSIM (integrated SIM). */
-    public static final int SLOT_TYPE_IUICC = 2;
-    /** Slot type for eUICC/eSIM (embedded SIM). */
-    public static final int SLOT_TYPE_EUICC = 3;
-    /** Slot type for soft SIM (no physical SIM). */
-    public static final int SLOT_TYPE_SOFT_SIM = 4;
-
-    /** @hide */
-    @IntDef(prefix = {"SLOT_TYPE_" }, value = {
-            SLOT_TYPE_UICC,
-            SLOT_TYPE_IUICC,
-            SLOT_TYPE_EUICC,
-            SLOT_TYPE_SOFT_SIM,
-    })
-    @Retention(RetentionPolicy.SOURCE)
-    public @interface SlotType {
-    }
-
-    private final int mPhysicalSlotIndex;
-    private final int mSlotType;
-
-    /** @hide */
-    public SimSlotCapability(int physicalSlotId, int slotType) {
-        this.mPhysicalSlotIndex = physicalSlotId;
-        this.mSlotType = slotType;
-    }
-
-    private SimSlotCapability(Parcel in) {
-        mPhysicalSlotIndex = in.readInt();
-        mSlotType = in.readInt();
-    }
-
-    /**
-     * @return physical SIM slot index
-     */
-    public int getPhysicalSlotIndex() {
-        return mPhysicalSlotIndex;
-    }
-
-    /**
-     * @return type of SIM {@link SlotType}
-     */
-    public @SlotType int getSlotType() {
-        return mSlotType;
-    }
-
-    @Override
-    public String toString() {
-        return "mPhysicalSlotIndex=" + mPhysicalSlotIndex + " slotType=" + mSlotType;
-    }
-
-    @Override
-    public int hashCode() {
-        return Objects.hash(mPhysicalSlotIndex, mSlotType);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-        if (o == null || !(o instanceof SimSlotCapability) || hashCode() != o.hashCode()) {
-            return false;
-        }
-
-        if (this == o) {
-            return true;
-        }
-
-        SimSlotCapability s = (SimSlotCapability) o;
-
-        return (mPhysicalSlotIndex == s.mPhysicalSlotIndex && mSlotType == s.mSlotType);
-    }
-
-    /**
-     * {@link Parcelable#describeContents}
-     */
-    public int describeContents() {
-        return 0;
-    }
-
-    /**
-     * {@link Parcelable#writeToParcel}
-     */
-    public void writeToParcel(@NonNull Parcel dest, int flags) {
-        dest.writeInt(mPhysicalSlotIndex);
-        dest.writeInt(mSlotType);
-    }
-
-    public static final @NonNull Parcelable.Creator<SimSlotCapability> CREATOR =
-            new Parcelable.Creator() {
-                public SimSlotCapability createFromParcel(Parcel in) {
-                    return new SimSlotCapability(in);
-                }
-
-                public SimSlotCapability[] newArray(int size) {
-                    return new SimSlotCapability[size];
-                }
-            };
-}
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 6c920f1..8479db6 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -2094,8 +2094,12 @@
 
     /**
      * Gets the total capacity of SMS storage on RUIM and SIM cards
+     * <p>
+     * This is the number of 176 byte EF-SMS records which can be stored on the RUIM or SIM card.
+     * <p>
+     * See 3GPP TS 31.102 - 4.2.25 - EF-SMS for more information
      *
-     * @return the total capacity count of SMS on RUIM and SIM cards
+     * @return the total number of SMS records which can be stored on the RUIM or SIM cards.
      * @hide
      */
     @SystemApi
diff --git a/telephony/java/android/telephony/SubscriptionInfo.java b/telephony/java/android/telephony/SubscriptionInfo.java
index 832771d..336aa0e 100644
--- a/telephony/java/android/telephony/SubscriptionInfo.java
+++ b/telephony/java/android/telephony/SubscriptionInfo.java
@@ -217,6 +217,20 @@
     private boolean mAreUiccApplicationsEnabled = true;
 
     /**
+     * Public copy constructor.
+     * @hide
+     */
+    public SubscriptionInfo(SubscriptionInfo info) {
+        this(info.mId, info.mIccId, info.mSimSlotIndex, info.mDisplayName, info.mCarrierName,
+                info.mNameSource, info.mIconTint, info.mNumber, info.mDataRoaming, info.mIconBitmap,
+                info.mMcc, info.mMnc, info.mCountryIso, info.mIsEmbedded, info.mNativeAccessRules,
+                info.mCardString, info.mCardId, info.mIsOpportunistic,
+                info.mGroupUUID == null ? null : info.mGroupUUID.toString(), info.mIsGroupDisabled,
+                info.mCarrierId, info.mProfileClass, info.mSubscriptionType, info.mGroupOwner,
+                info.mCarrierConfigAccessRules, info.mAreUiccApplicationsEnabled);
+    }
+
+    /**
      * @hide
      */
     public SubscriptionInfo(int id, String iccId, int simSlotIndex, CharSequence displayName,
@@ -291,13 +305,27 @@
     }
 
     /**
-     * @return the ICC ID.
+     * Returns the ICC ID if the calling app has been granted the READ_PRIVILEGED_PHONE_STATE
+     * permission, has carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}), or
+     * is a device owner or profile owner that has been granted the READ_PHONE_STATE permission.
+     * The profile owner is an app that owns a managed profile on the device; for more details see
+     * <a href="https://developer.android.com/work/managed-profiles">Work profiles</a>. Profile
+     * owner access is deprecated and will be removed in a future release.
+     *
+     * @return the ICC ID, or an empty string if one of these requirements is not met
      */
     public String getIccId() {
         return this.mIccId;
     }
 
     /**
+     * @hide
+     */
+    public void clearIccId() {
+        this.mIccId = "";
+    }
+
+    /**
      * @return the slot index of this Subscription's SIM card.
      */
     public int getSimSlotIndex() {
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 68b6683..0660776 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -47,7 +47,6 @@
 import android.content.Intent;
 import android.database.Cursor;
 import android.net.ConnectivityManager;
-import android.net.NetworkStats;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Binder;
@@ -1877,24 +1876,6 @@
     //
 
     /**
-     * Returns the {@link PhoneCapability} for the device or null if it is not available.
-     * <p>
-     * Requires Permission: READ_PHONE_STATE or that the calling app has
-     * carrier privileges (see {@link #hasCarrierPrivileges}).
-     */
-    @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
-    @Nullable
-    public PhoneCapability getPhoneCapability() {
-        try {
-            ITelephony telephony = getITelephony();
-            return telephony == null ? null :
-                    telephony.getPhoneCapability(getSubId(), getOpPackageName(), getFeatureId());
-        } catch (RemoteException ex) {
-            return null;
-        }
-    }
-
-    /**
      * Returns the software version number for the device, for example,
      * the IMEI/SV for GSM phones. Return null if the software version is
      * not available.
@@ -6180,9 +6161,11 @@
      * @param AID Application id. See ETSI 102.221 and 101.220.
      * @param p2 P2 parameter (described in ISO 7816-4).
      * @return an IccOpenLogicalChannelResponse object.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openLogicalChannel(byte[], byte)}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(String AID, int p2) {
         return iccOpenLogicalChannel(getSubId(), AID, p2);
@@ -6214,9 +6197,11 @@
      * @param p2 P2 parameter (described in ISO 7816-4).
      * @return an IccOpenLogicalChannelResponse object.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openLogicalChannel(byte[], byte)}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public IccOpenLogicalChannelResponse iccOpenLogicalChannel(int subId, String AID, int p2) {
         try {
@@ -6245,9 +6230,9 @@
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#close()}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
@@ -6275,9 +6260,9 @@
      * @param channel is the channel id to be closed as returned by a successful
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#close()}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public boolean iccCloseLogicalChannel(int channel) {
         return iccCloseLogicalChannel(getSubId(), channel);
@@ -6297,9 +6282,9 @@
      *            iccOpenLogicalChannel.
      * @return true if the channel was closed successfully.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#close()}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public boolean iccCloseLogicalChannel(int subId, int channel) {
         try {
@@ -6336,9 +6321,9 @@
      * @return The APDU response from the ICC card with the status appended at the end, or null if
      * there is an issue connecting to the Telephony service.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
@@ -6377,9 +6362,9 @@
      * @param data Data to be sent with the APDU.
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String iccTransmitApduLogicalChannel(int channel, int cla,
             int instruction, int p1, int p2, int p3, String data) {
@@ -6409,9 +6394,9 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String iccTransmitApduLogicalChannel(int subId, int channel, int cla,
             int instruction, int p1, int p2, int p3, String data) {
@@ -6448,9 +6433,12 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
     @SystemApi
@@ -6487,9 +6475,12 @@
      * @param data Data to be sent with the APDU.
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String iccTransmitApduBasicChannel(int cla,
             int instruction, int p1, int p2, int p3, String data) {
@@ -6517,9 +6508,12 @@
      * @return The APDU response from the ICC card with the status appended at
      *            the end.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String iccTransmitApduBasicChannel(int subId, int cla,
             int instruction, int p1, int p2, int p3, String data) {
@@ -6548,9 +6542,12 @@
      * @param p3 P3 value of the APDU command.
      * @param filePath
      * @return The APDU response.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public byte[] iccExchangeSimIO(int fileID, int command, int p1, int p2, int p3,
             String filePath) {
@@ -6573,9 +6570,12 @@
      * @param filePath
      * @return The APDU response.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public byte[] iccExchangeSimIO(int subId, int fileID, int command, int p1, int p2,
             int p3, String filePath) {
@@ -6602,9 +6602,12 @@
      * @return The APDU response from the ICC card in hexadecimal format
      *         with the last 4 bytes being the status word. If the command fails,
      *         returns an empty string.
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String sendEnvelopeWithStatus(String content) {
         return sendEnvelopeWithStatus(getSubId(), content);
@@ -6625,9 +6628,12 @@
      *         with the last 4 bytes being the status word. If the command fails,
      *         returns an empty string.
      * @hide
-     * @deprecated Use {@link android.se.omapi.SEService} APIs instead.
+     * @deprecated Use {@link android.se.omapi.SEService} APIs instead. See
+     *             {@link android.se.omapi.SEService#getUiccReader(int)},
+     *             {@link android.se.omapi.Reader#openSession()},
+     *             {@link android.se.omapi.Session#openBasicChannel(byte[], byte)},
+     *             {@link android.se.omapi.Channel#transmit(byte[])}.
      */
-    // TODO(b/147153909): Update Javadoc to link to specific SEService API once integrated.
     @Deprecated
     public String sendEnvelopeWithStatus(int subId, String content) {
         try {
@@ -11082,28 +11088,6 @@
     }
 
     /**
-     * Get aggregated video call data usage since boot.
-     * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
-     *
-     * @param how one of the NetworkStats.STATS_PER_* constants depending on whether the request is
-     * for data usage per uid or overall usage.
-     * @return Snapshot of video call data usage
-     * @hide
-     */
-    public NetworkStats getVtDataUsage(int how) {
-        boolean perUidStats = (how == NetworkStats.STATS_PER_UID);
-        try {
-            ITelephony service = getITelephony();
-            if (service != null) {
-                return service.getVtDataUsage(getSubId(), perUidStats);
-            }
-        } catch (RemoteException e) {
-            Log.e(TAG, "Error calling ITelephony#getVtDataUsage", e);
-        }
-        return null;
-    }
-
-    /**
      * Policy control of data connection. Usually used when data limit is passed.
      * @param enabled True if enabling the data, otherwise disabling.
      * @hide
diff --git a/telephony/java/android/telephony/ims/ImsCallSession.java b/telephony/java/android/telephony/ims/ImsCallSession.java
old mode 100644
new mode 100755
index 1b583fd..80c38cb
--- a/telephony/java/android/telephony/ims/ImsCallSession.java
+++ b/telephony/java/android/telephony/ims/ImsCallSession.java
@@ -16,6 +16,8 @@
 
 package android.telephony.ims;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.os.Message;
 import android.os.RemoteException;
 import android.telephony.CallQuality;
@@ -451,6 +453,21 @@
         }
 
         /**
+         * Received success response for call transfer request.
+         */
+        public void callSessionTransferred(@NonNull ImsCallSession session) {
+            // no-op
+        }
+
+        /**
+         * Received failure response for call transfer request.
+         */
+        public void callSessionTransferFailed(@NonNull ImsCallSession session,
+                @Nullable ImsReasonInfo reasonInfo) {
+            // no-op
+        }
+
+        /**
          * Called when the IMS service reports a change to the call quality.
          */
         public void callQualityChanged(CallQuality callQuality) {
@@ -795,6 +812,41 @@
     }
 
     /**
+     * Transfers an ongoing call.
+     *
+     * @param number number to be transferred to.
+     * @param isConfirmationRequired indicates blind or assured transfer.
+     */
+    public void transfer(@NonNull String number, boolean isConfirmationRequired) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            miSession.transfer(number, isConfirmationRequired);
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
+     * Transfers a call to another ongoing call.
+     *
+     * @param transferToSession the other ImsCallSession to which this session will be transferred.
+     */
+    public void transfer(@NonNull ImsCallSession transferToSession) {
+        if (mClosed) {
+            return;
+        }
+
+        try {
+            if (transferToSession != null) {
+                miSession.consultativeTransfer(transferToSession.getSession());
+            }
+        } catch (RemoteException e) {
+        }
+    }
+
+    /**
      * Terminates a call.
      *
      * @see Listener#callSessionTerminated
@@ -1410,6 +1462,20 @@
             }
         }
 
+        @Override
+        public void callSessionTransferred() {
+            if (mListener != null) {
+                mListener.callSessionTransferred(ImsCallSession.this);
+            }
+        }
+
+        @Override
+        public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo) {
+            if (mListener != null) {
+                mListener.callSessionTransferFailed(ImsCallSession.this, reasonInfo);
+            }
+        }
+
         /**
          * Call quality updated
          */
diff --git a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
index cc2ebb9..36d2067 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsCallSessionListener.aidl
@@ -148,6 +148,12 @@
     void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile);
 
     /**
+     * Notifies the result of transfer request.
+     */
+    void callSessionTransferred();
+    void callSessionTransferFailed(in ImsReasonInfo reasonInfo);
+
+    /**
      * Notifies of a change to the call quality.
      * @param callQuality then updated call quality
      */
diff --git a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
old mode 100644
new mode 100755
index 75bd6a7..06aa642
--- a/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/compat/stub/ImsCallSessionImplBase.java
@@ -16,6 +16,8 @@
 
 package android.telephony.ims.compat.stub;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.os.Message;
 import android.os.RemoteException;
@@ -197,6 +199,29 @@
     }
 
     /**
+     * Transfer an established call to given number, disconnecting the ongoing call
+     * when the transfer is complete.
+     *
+     * @param number number to transfer the call
+     * @param isConfirmationRequired when {@code true}, then the {@link ImsCallSessionImplBase}
+     * should wait until the transfer has successfully completed before disconnecting the current
+     * {@link ImsCallSessionImplBase}. When {@code false}, the {@link ImsCallSessionImplBase}
+     * should signal the network to perform the transfer, but should immediately disconnect the
+     * call regardless of the outcome of the transfer.
+     */
+    @Override
+    public void transfer(@NonNull String number, boolean isConfirmationRequired) {
+    }
+
+    /**
+     * Transfer an established call to an existing ongoing session.
+     * When the transfer is complete, the current call gets disconnected locally.
+     */
+    @Override
+    public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
+    }
+
+    /**
      * Rejects an incoming call or session update.
      *
      * @param reason reason code to reject an incoming call, defined in {@link ImsReasonInfo}.
@@ -610,6 +635,17 @@
         }
 
         @Override
+        public void callSessionTransferred() throws RemoteException {
+            mNewListener.callSessionTransferred();
+        }
+
+        @Override
+        public void callSessionTransferFailed(@Nullable ImsReasonInfo reasonInfo)
+                throws RemoteException {
+            mNewListener.callSessionTransferFailed(reasonInfo);
+        }
+
+        @Override
         public void callQualityChanged(CallQuality callQuality) throws RemoteException {
             mNewListener.callQualityChanged(callQuality);
         }
diff --git a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
index e8f69ea..73ba0e3 100644
--- a/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsCallSessionImplBase.java
@@ -16,6 +16,7 @@
 
 package android.telephony.ims.stub;
 
+import android.annotation.NonNull;
 import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.os.Message;
@@ -183,6 +184,18 @@
         }
 
         @Override
+        public void transfer(@NonNull String number, boolean isConfirmationRequired) {
+            ImsCallSessionImplBase.this.transfer(number, isConfirmationRequired);
+        }
+
+        @Override
+        public void consultativeTransfer(@NonNull IImsCallSession transferToSession) {
+            ImsCallSessionImplBase otherSession = new ImsCallSessionImplBase();
+            otherSession.setServiceImpl(transferToSession);
+            ImsCallSessionImplBase.this.transfer(otherSession);
+        }
+
+        @Override
         public void terminate(int reason) {
             ImsCallSessionImplBase.this.terminate(reason);
         }
@@ -423,6 +436,26 @@
     }
 
     /**
+     * Transfer an established call to given number
+     *
+     * @param number number to transfer the call
+     * @param isConfirmationRequired if {@code True}, indicates Assured transfer,
+     * if {@code False} it indicates Blind transfer.
+     * @hide
+     */
+    public void transfer(@NonNull String number, boolean isConfirmationRequired) {
+    }
+
+    /**
+     * Transfer an established call to another call session
+     *
+     * @param otherSession The other ImsCallSession to transfer the ongoing session to.
+     * @hide
+     */
+    public void transfer(@NonNull ImsCallSessionImplBase otherSession) {
+    }
+
+    /**
      * Terminates a call.
      *
      * @param reason reason code to terminate a call, defined in {@link ImsReasonInfo}.
diff --git a/telephony/java/com/android/ims/internal/IImsCallSession.aidl b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
index 15234e5..0466efc 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSession.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSession.aidl
@@ -18,7 +18,6 @@
 
 import android.os.Message;
 import android.telephony.ims.aidl.IImsCallSessionListener;
-
 import android.telephony.ims.ImsCallProfile;
 import android.telephony.ims.ImsStreamMediaProfile;
 import com.android.ims.internal.IImsVideoCallProvider;
@@ -151,6 +150,22 @@
     void reject(int reason);
 
     /**
+     * Transfer an established call to given number
+     *
+     * @param number number to transfer the call
+     * @param isConfirmationRequired if {@code True}, indicates Assured transfer,
+     * if {@code False} it indicates Blind transfer.
+     */
+    void transfer(String number, boolean isConfirmationRequired);
+
+    /**
+     * Transfer an established call to another call session
+     *
+     * @param transferToSession The other ImsCallSession to transfer the ongoing session to.
+     */
+    void consultativeTransfer(in IImsCallSession transferToSession);
+
+    /**
      * Terminates a call.
      *
      * @see Listener#callSessionTerminated
diff --git a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
index b33a9f1..1c62cc4 100644
--- a/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsCallSessionListener.aidl
@@ -184,6 +184,12 @@
     void callSessionRttAudioIndicatorChanged(in ImsStreamMediaProfile profile);
 
     /**
+     * Notifies about the response for call transfer request.
+     */
+    void callSessionTransferred();
+
+    void callSessionTransferFailed(in ImsReasonInfo reasonInfo);
+    /**
      * Notifies of a change to the call quality.
      * @param callQuality then updated call quality
      */
diff --git a/telephony/java/com/android/internal/telephony/DctConstants.java b/telephony/java/com/android/internal/telephony/DctConstants.java
index 1449a62..f61d4e1 100644
--- a/telephony/java/com/android/internal/telephony/DctConstants.java
+++ b/telephony/java/com/android/internal/telephony/DctConstants.java
@@ -114,6 +114,7 @@
     public static final int EVENT_SERVICE_STATE_CHANGED = BASE + 52;
     public static final int EVENT_5G_TIMER_HYSTERESIS = BASE + 53;
     public static final int EVENT_5G_TIMER_WATCHDOG = BASE + 54;
+    public static final int EVENT_UPDATE_CARRIER_CONFIGS = BASE + 55;
 
     /***** Constants *****/
 
@@ -123,4 +124,6 @@
 
     public static final String APN_TYPE_KEY = "apnType";
     public static final String PROVISIONING_URL_KEY = "provisioningUrl";
+    public static final String BANDWIDTH_SOURCE_MODEM_KEY = "modem";
+    public static final String BANDWIDTH_SOURCE_CARRIER_CONFIG_KEY = "carrier_config";
 }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 168c8b6..861925f 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -39,7 +39,6 @@
 import android.telephony.ModemActivityInfo;
 import android.telephony.NeighboringCellInfo;
 import android.telephony.NetworkScanRequest;
-import android.telephony.PhoneCapability;
 import android.telephony.PhoneNumberRange;
 import android.telephony.RadioAccessFamily;
 import android.telephony.RadioAccessSpecifier;
@@ -1624,16 +1623,6 @@
     void carrierActionResetAll(int subId);
 
     /**
-     * Get aggregated video call data usage since boot.
-     * Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
-     *
-     * @param perUidStats True if requesting data usage per uid, otherwise overall usage.
-     * @return Snapshot of video call data usage
-     * @hide
-     */
-    NetworkStats getVtDataUsage(int subId, boolean perUidStats);
-
-    /**
      * Gets the voice call forwarding info {@link CallForwardingInfo}, given the call forward
      * reason.
      *
@@ -1899,17 +1888,12 @@
     /**
      * Return the network selection mode on the subscription with id {@code subId}.
      */
-    int getNetworkSelectionMode(int subId);
+     int getNetworkSelectionMode(int subId);
 
-    /**
-     * Return the PhoneCapability for the device.
-     */
-    PhoneCapability getPhoneCapability(int subId, String callingPackage, String callingFeatureId);
-
-    /**
+     /**
      * Return true if the device is in emergency sms mode, false otherwise.
      */
-    boolean isInEmergencySmsMode();
+     boolean isInEmergencySmsMode();
 
     /**
      * Return the modem radio power state for slot index.
diff --git a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
index 6dc1e0e..c074e6e 100644
--- a/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/sms/BearerData.java
@@ -248,10 +248,10 @@
         public int hour;
         public int monthDay;
 
-        /** Month [0-11] */
-        public int month;
+        /** Month in the range 1(Jan) - 12(Dec). */
+        public int monthOrdinal;
 
-        /** Full year. For example, 1970. */
+        /** Full year in the range 1996 - 2095. */
         public int year;
 
         private ZoneId mZoneId;
@@ -269,7 +269,7 @@
             ts.year = year >= 96 ? year + 1900 : year + 2000;
             int month = IccUtils.cdmaBcdByteToInt(data[1]);
             if (month < 1 || month > 12) return null;
-            ts.month = month - 1;
+            ts.monthOrdinal = month;
             int day = IccUtils.cdmaBcdByteToInt(data[2]);
             if (day < 1 || day > 31) return null;
             ts.monthDay = day;
@@ -292,7 +292,7 @@
             int year = localDateTime.getYear();
             if (year < 1996 || year > 2095) return null;
             ts.year = year;
-            ts.month = localDateTime.getMonthValue();
+            ts.monthOrdinal = localDateTime.getMonthValue();
             ts.monthDay = localDateTime.getDayOfMonth();
             ts.hour = localDateTime.getHour();
             ts.minute = localDateTime.getMinute();
@@ -304,7 +304,7 @@
             int year = this.year % 100; // 00 - 99
             ByteArrayOutputStream outStream = new ByteArrayOutputStream(6);
             outStream.write((((year / 10) & 0x0F) << 4) | ((year % 10) & 0x0F));
-            outStream.write((((month / 10) << 4) & 0xF0) | ((month % 10) & 0x0F));
+            outStream.write((((monthOrdinal / 10) << 4) & 0xF0) | ((monthOrdinal % 10) & 0x0F));
             outStream.write((((monthDay / 10) << 4) & 0xF0) | ((monthDay % 10) & 0x0F));
             outStream.write((((hour / 10) << 4) & 0xF0) | ((hour % 10) & 0x0F));
             outStream.write((((minute / 10) << 4) & 0xF0) | ((minute % 10) & 0x0F));
@@ -314,7 +314,7 @@
 
         public long toMillis() {
             LocalDateTime localDateTime =
-                    LocalDateTime.of(year, month + 1, monthDay, hour, minute, second);
+                    LocalDateTime.of(year, monthOrdinal, monthDay, hour, minute, second);
             Instant instant = localDateTime.toInstant(mZoneId.getRules().getOffset(localDateTime));
             return instant.toEpochMilli();
         }
@@ -325,7 +325,7 @@
             StringBuilder builder = new StringBuilder();
             builder.append("TimeStamp ");
             builder.append("{ year=" + year);
-            builder.append(", month=" + month);
+            builder.append(", month=" + monthOrdinal);
             builder.append(", day=" + monthDay);
             builder.append(", hour=" + hour);
             builder.append(", minute=" + minute);
diff --git a/test-mock/src/android/test/mock/MockContentProvider.java b/test-mock/src/android/test/mock/MockContentProvider.java
index f7ec11c..d1d64d3 100644
--- a/test-mock/src/android/test/mock/MockContentProvider.java
+++ b/test-mock/src/android/test/mock/MockContentProvider.java
@@ -156,6 +156,12 @@
         }
 
         @Override
+        public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+                RemoteCallback callback) {
+            MockContentProvider.this.canonicalizeAsync(uri, callback);
+        }
+
+        @Override
         public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
                 throws RemoteException {
             return MockContentProvider.this.uncanonicalize(uri);
@@ -292,6 +298,18 @@
     /**
      * @hide
      */
+    @SuppressWarnings("deprecation")
+    public void canonicalizeAsync(Uri uri, RemoteCallback callback) {
+        AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+            final Bundle bundle = new Bundle();
+            bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT, canonicalize(uri));
+            callback.sendResult(bundle);
+        });
+    }
+
+    /**
+     * @hide
+     */
     public boolean refresh(Uri url, Bundle args) {
         throw new UnsupportedOperationException("unimplemented mock method call");
     }
diff --git a/test-mock/src/android/test/mock/MockContext.java b/test-mock/src/android/test/mock/MockContext.java
index 359c448..2c66047 100644
--- a/test-mock/src/android/test/mock/MockContext.java
+++ b/test-mock/src/android/test/mock/MockContext.java
@@ -834,6 +834,12 @@
 
     /** @hide */
     @Override
+    public Display getDisplayNoVerify() {
+        throw new UnsupportedOperationException();
+    }
+
+    /** @hide */
+    @Override
     public int getDisplayId() {
         throw new UnsupportedOperationException();
     }
diff --git a/test-mock/src/android/test/mock/MockIContentProvider.java b/test-mock/src/android/test/mock/MockIContentProvider.java
index 1831bcd..223bcc5 100644
--- a/test-mock/src/android/test/mock/MockIContentProvider.java
+++ b/test-mock/src/android/test/mock/MockIContentProvider.java
@@ -145,12 +145,23 @@
     }
 
     @Override
-    public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri)
-            throws RemoteException {
+    public Uri canonicalize(String callingPkg, @Nullable String featureId, Uri uri) {
         throw new UnsupportedOperationException("unimplemented mock method");
     }
 
     @Override
+    @SuppressWarnings("deprecation")
+    public void canonicalizeAsync(String callingPkg, String featureId, Uri uri,
+            RemoteCallback remoteCallback) {
+        AsyncTask.SERIAL_EXECUTOR.execute(() -> {
+            final Bundle bundle = new Bundle();
+            bundle.putParcelable(ContentResolver.REMOTE_CALLBACK_RESULT,
+                    canonicalize(callingPkg, featureId, uri));
+            remoteCallback.sendResult(bundle);
+        });
+    }
+
+    @Override
     public Uri uncanonicalize(String callingPkg, @Nullable String featureId, Uri uri)
             throws RemoteException {
         throw new UnsupportedOperationException("unimplemented mock method");
diff --git a/tests/BootImageProfileTest/TEST_MAPPING b/tests/BootImageProfileTest/DISABLED_TEST_MAPPING
similarity index 100%
rename from tests/BootImageProfileTest/TEST_MAPPING
rename to tests/BootImageProfileTest/DISABLED_TEST_MAPPING
diff --git a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
index 52f6eba..e616ac4 100644
--- a/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
+++ b/tests/RollbackTest/MultiUserRollbackTest/src/com/android/tests/rollback/host/MultiUserRollbackTest.java
@@ -27,6 +27,8 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.TimeUnit;
+
 /**
  * Runs rollback tests for multiple users.
  */
@@ -41,7 +43,6 @@
 
     @After
     public void tearDown() throws Exception {
-        getDevice().switchUser(mOriginalUserId);
         getDevice().executeShellCommand("pm uninstall com.android.cts.install.lib.testapp.A");
         removeSecondaryUserIfNecessary();
     }
@@ -49,9 +50,9 @@
     @Before
     public void setup() throws Exception {
         mOriginalUserId = getDevice().getCurrentUser();
-        installPackageAsUser("RollbackTest.apk", true, mOriginalUserId);
-        createAndSwitchToSecondaryUserIfNecessary();
-        installPackageAsUser("RollbackTest.apk", true, mSecondaryUserId);
+        createAndStartSecondaryUser();
+        // TODO(b/149733368): Remove the '-g' workaround when the bug is fixed.
+        installPackage("RollbackTest.apk", "-g --user all");
     }
 
     @Test
@@ -64,7 +65,6 @@
         runPhaseForUsers("testMultipleUsersInstallV1", mOriginalUserId, mSecondaryUserId);
         runPhaseForUsers("testMultipleUsersUpgradeToV2", mOriginalUserId);
         runPhaseForUsers("testMultipleUsersUpdateUserData", mOriginalUserId, mSecondaryUserId);
-        switchToUser(mOriginalUserId);
         getDevice().executeShellCommand("pm rollback-app com.android.cts.install.lib.testapp.A");
         runPhaseForUsers("testMultipleUsersVerifyUserdataRollback", mOriginalUserId,
                 mSecondaryUserId);
@@ -74,11 +74,11 @@
      * Run the phase for the given user ids, in the order they are given.
      */
     private void runPhaseForUsers(String phase, int... userIds) throws Exception {
+        final long timeout = TimeUnit.MINUTES.toMillis(10);
         for (int userId: userIds) {
-            switchToUser(userId);
-            assertTrue(runDeviceTests("com.android.tests.rollback",
+            assertTrue(runDeviceTests(getDevice(), "com.android.tests.rollback",
                     "com.android.tests.rollback.MultiUserRollbackTest",
-                    phase));
+                    phase, userId, timeout));
         }
     }
 
@@ -89,21 +89,7 @@
         }
     }
 
-    private void createAndSwitchToSecondaryUserIfNecessary() throws Exception {
-        if (mSecondaryUserId == -1) {
-            mOriginalUserId = getDevice().getCurrentUser();
-            mSecondaryUserId = getDevice().createUser("MultiUserRollbackTest_User"
-                    + System.currentTimeMillis());
-            switchToUser(mSecondaryUserId);
-        }
-    }
-
-    private void switchToUser(int userId) throws Exception {
-        if (getDevice().getCurrentUser() == userId) {
-            return;
-        }
-
-        assertTrue(getDevice().switchUser(userId));
+    private void awaitUserUnlocked(int userId) throws Exception {
         for (int i = 0; i < SWITCH_USER_COMPLETED_NUMBER_OF_POLLS; ++i) {
             String userState = getDevice().executeShellCommand("am get-started-user-state "
                     + userId);
@@ -112,6 +98,14 @@
             }
             Thread.sleep(SWITCH_USER_COMPLETED_POLL_INTERVAL_IN_MILLIS);
         }
-        fail("User switch to user " + userId + " timed out");
+        fail("Timed out in unlocking user: " + userId);
+    }
+
+    private void createAndStartSecondaryUser() throws Exception {
+        String name = "MultiUserRollbackTest_User" + System.currentTimeMillis();
+        mSecondaryUserId = getDevice().createUser(name);
+        getDevice().startUser(mSecondaryUserId);
+        // Note we can't install apps on a locked user
+        awaitUserUnlocked(mSecondaryUserId);
     }
 }
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
index 0ffe041..400bb04 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/MultiUserRollbackTest.java
@@ -17,13 +17,11 @@
 package com.android.tests.rollback;
 
 import static com.android.cts.rollback.lib.RollbackInfoSubject.assertThat;
-import static com.android.cts.rollback.lib.RollbackUtils.getUniqueRollbackInfoForPackage;
 
 import static com.google.common.truth.Truth.assertThat;
 
 import android.Manifest;
 import android.content.rollback.RollbackInfo;
-import android.content.rollback.RollbackManager;
 
 import com.android.cts.install.lib.Install;
 import com.android.cts.install.lib.InstallUtils;
@@ -77,13 +75,10 @@
      */
     @Test
     public void testMultipleUsersUpgradeToV2() throws Exception {
-        RollbackManager rm = RollbackUtils.getRollbackManager();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1);
         Install.single(TestApp.A2).setEnableRollback().commit();
         assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
-        RollbackInfo rollback = getUniqueRollbackInfoForPackage(
-                rm.getAvailableRollbacks(), TestApp.A);
-        assertThat(rollback).isNotNull();
+        RollbackInfo rollback = RollbackUtils.waitForAvailableRollback(TestApp.A);
         assertThat(rollback).packagesContainsExactly(
                 Rollback.from(TestApp.A2).to(TestApp.A1));
     }
diff --git a/tests/net/AndroidManifest.xml b/tests/net/AndroidManifest.xml
index 638b6d1..480b12b 100644
--- a/tests/net/AndroidManifest.xml
+++ b/tests/net/AndroidManifest.xml
@@ -50,6 +50,7 @@
 
     <application>
         <uses-library android:name="android.test.runner" />
+        <uses-library android:name="android.net.ipsec.ike" />
     </application>
 
     <instrumentation
diff --git a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
index 490c467..23caf49 100644
--- a/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
+++ b/tests/net/integration/src/com/android/server/net/integrationtests/TestNetworkStackService.kt
@@ -26,6 +26,7 @@
 import android.os.IBinder
 import com.android.networkstack.metrics.DataStallStatsUtils
 import com.android.networkstack.netlink.TcpSocketTracker
+import com.android.server.NetworkStackService
 import com.android.server.NetworkStackService.NetworkMonitorConnector
 import com.android.server.NetworkStackService.NetworkStackConnector
 import com.android.server.connectivity.NetworkMonitor
@@ -88,6 +89,7 @@
             val nm = NetworkMonitor(this@TestNetworkStackService, cb,
                     this.network,
                     mock(IpConnectivityLog::class.java), mock(SharedLog::class.java),
+                    mock(NetworkStackService.NetworkStackServiceManager::class.java),
                     NetworkMonitorDeps(privateDnsBypassNetwork),
                     mock(DataStallStatsUtils::class.java),
                     mock(TcpSocketTracker::class.java))
diff --git a/tests/net/java/android/net/Ikev2VpnProfileTest.java b/tests/net/java/android/net/Ikev2VpnProfileTest.java
index d6a2176..2273bc6 100644
--- a/tests/net/java/android/net/Ikev2VpnProfileTest.java
+++ b/tests/net/java/android/net/Ikev2VpnProfileTest.java
@@ -22,7 +22,6 @@
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-import static org.mockito.Mockito.mock;
 
 import android.test.mock.MockContext;
 
@@ -232,10 +231,12 @@
         builder.setAuthDigitalSignature(mUserCert, mPrivateKey, mServerRootCa);
         final VpnProfile profile = builder.build().toVpnProfile();
 
+        final String expectedSecret = Ikev2VpnProfile.PREFIX_INLINE
+                + Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded());
         verifyVpnProfileCommon(profile);
         assertEquals(Ikev2VpnProfile.certificateToPemString(mUserCert), profile.ipsecUserCert);
         assertEquals(
-                Ikev2VpnProfile.encodeForIpsecSecret(mPrivateKey.getEncoded()),
+                expectedSecret,
                 profile.ipsecSecret);
         assertEquals(Ikev2VpnProfile.certificateToPemString(mServerRootCa), profile.ipsecCaCert);
 
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 957683e..6d4a1b2 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -204,6 +204,7 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
+import android.security.KeyStore;
 import android.system.Os;
 import android.test.mock.MockContentResolver;
 import android.text.TextUtils;
@@ -1019,7 +1020,7 @@
 
         public MockVpn(int userId) {
             super(startHandlerThreadAndReturnLooper(), mServiceContext, mNetworkManagementService,
-                    userId);
+                    userId, mock(KeyStore.class));
         }
 
         public void setNetworkAgent(TestNetworkAgentWrapper agent) {
@@ -1179,6 +1180,10 @@
                 Arrays.asList(new UserInfo[] {
                         new UserInfo(VPN_USER, "", 0),
                 }));
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
+        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
+                .thenReturn(applicationInfo);
 
         // InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
         // http://b/25897652 .
@@ -2053,14 +2058,15 @@
         assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
-        // Bring up wifi with a score of 70.
+        // Bring up validated wifi.
         // Cell is lingered because it would not satisfy any request, even if it validated.
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.adjustScore(50);
-        mWiFiNetworkAgent.connect(false);   // Score: 70
+        mWiFiNetworkAgent.connect(true);   // Score: 60
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        // TODO: Investigate sending validated before losing.
         callback.expectCallback(CallbackEntry.LOSING, mCellNetworkAgent);
-        defaultCallback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        defaultCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         assertEquals(defaultCallback.getLastAvailableNetwork(), mCm.getActiveNetwork());
 
@@ -3040,7 +3046,7 @@
             networkCapabilities.addTransportType(TRANSPORT_WIFI)
                     .setNetworkSpecifier(new MatchAllNetworkSpecifier());
             mService.requestNetwork(networkCapabilities, null, 0, null,
-                    ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME);
+                    ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
         });
 
         class NonParcelableSpecifier extends NetworkSpecifier {
@@ -5844,7 +5850,7 @@
 
         mWiFiNetworkAgent = new TestNetworkAgentWrapper(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
-        trustedCallback.expectAvailableDoubleValidatedCallbacks(mWiFiNetworkAgent);
+        trustedCallback.expectAvailableThenValidatedCallbacks(mWiFiNetworkAgent);
         verify(mNetworkManagementService).setDefaultNetId(eq(mWiFiNetworkAgent.getNetwork().netId));
         reset(mNetworkManagementService);
 
@@ -6437,17 +6443,89 @@
         assertEquals(wifiLp, mService.getActiveLinkProperties());
     }
 
+    private void setupLocationPermissions(
+            int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
+        final ApplicationInfo applicationInfo = new ApplicationInfo();
+        applicationInfo.targetSdkVersion = targetSdk;
+        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
+                .thenReturn(applicationInfo);
+
+        when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
+
+        if (op != null) {
+            when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
+                .thenReturn(AppOpsManager.MODE_ALLOWED);
+        }
+
+        if (perm != null) {
+            mServiceContext.setPermission(perm, PERMISSION_GRANTED);
+        }
+    }
+
+    private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
+        final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
+
+        return mService
+                .maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
+                .getOwnerUid();
+    }
+
     @Test
-    public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
-        int callerUid = Process.myUid();
-        final NetworkCapabilities originalNc = new NetworkCapabilities();
-        originalNc.setOwnerUid(callerUid);
+    public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
 
-        final NetworkCapabilities newNc =
-                mService.networkCapabilitiesRestrictedForCallerPermissions(
-                        originalNc, Process.myPid(), callerUid);
+        final int myUid = Process.myUid();
+        assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+    }
 
-        assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
+    @Test
+    public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
+        setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
+                Manifest.permission.ACCESS_COARSE_LOCATION);
+
+        final int myUid = Process.myUid();
+        assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+    }
+
+    @Test
+    public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception {
+        // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
+        setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
+
+        final int myUid = Process.myUid();
+        assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+    }
+
+    @Test
+    public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception {
+        // Test that even with fine location permission, not being the owner leads to sanitization.
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
+                Manifest.permission.ACCESS_FINE_LOCATION);
+
+        final int myUid = Process.myUid();
+        assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
+    }
+
+    @Test
+    public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
+        // Test that not having fine location permission leads to sanitization.
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
+                Manifest.permission.ACCESS_COARSE_LOCATION);
+
+        // Test that without the location permission, the owner field is sanitized.
+        final int myUid = Process.myUid();
+        assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
+    }
+
+    @Test
+    public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
+        setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
+
+        // Test that without the location permission, the owner field is sanitized.
+        final int myUid = Process.myUid();
+        assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
     }
 
     private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)
@@ -6733,21 +6811,6 @@
                         mContext.getOpPackageName()));
     }
 
-    private void setupLocationPermissions(
-            int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
-        final ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.targetSdkVersion = targetSdk;
-        when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
-                .thenReturn(applicationInfo);
-
-        when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
-
-        when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
-                .thenReturn(AppOpsManager.MODE_ALLOWED);
-
-        mServiceContext.setPermission(perm, PERMISSION_GRANTED);
-    }
-
     private void setUpConnectivityDiagnosticsCallback() throws Exception {
         final NetworkRequest request = new NetworkRequest.Builder().build();
         when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);
diff --git a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt
index a6b371a..d2532c2 100644
--- a/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt
+++ b/tests/net/java/com/android/server/connectivity/NetworkRankerTest.kt
@@ -16,14 +16,18 @@
 
 package com.android.server.connectivity
 
+import android.net.ConnectivityManager.TYPE_WIFI
+import android.net.LinkProperties
+import android.net.Network
+import android.net.NetworkAgentConfig
 import android.net.NetworkCapabilities
+import android.net.NetworkInfo
 import android.net.NetworkRequest
+import android.net.NetworkScore
 import androidx.test.filters.SmallTest
 import androidx.test.runner.AndroidJUnit4
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.any
-import org.mockito.Mockito.doReturn
 import org.mockito.Mockito.mock
 import kotlin.test.assertEquals
 import kotlin.test.assertNull
@@ -33,10 +37,24 @@
 class NetworkRankerTest {
     private val ranker = NetworkRanker()
 
-    private fun makeNai(satisfy: Boolean, score: Int) = mock(NetworkAgentInfo::class.java).also {
-        doReturn(satisfy).`when`(it).satisfies(any())
-        doReturn(score).`when`(it).currentScore
-        it.networkCapabilities = NetworkCapabilities()
+    private fun makeNai(satisfy: Boolean, score: Int) = object : NetworkAgentInfo(
+            null /* messenger */,
+            null /* asyncChannel*/,
+            Network(100),
+            NetworkInfo(TYPE_WIFI, 0 /* subtype */, "" /* typename */, "" /* subtypename */),
+            LinkProperties(),
+            NetworkCapabilities(),
+            NetworkScore.Builder().setLegacyScore(score).build(),
+            null /* context */,
+            null /* handler */,
+            NetworkAgentConfig(),
+            null /* connectivityService */,
+            null /* netd */,
+            null /* dnsResolver */,
+            null /* networkManagementService */,
+            0 /* factorySerialNumber */) {
+        override fun satisfies(request: NetworkRequest?): Boolean = satisfy
+        override fun getCurrentScore(): Int = score
     }
 
     @Test
diff --git a/tests/net/java/com/android/server/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index ac1c518..1994d1f 100644
--- a/tests/net/java/com/android/server/connectivity/VpnTest.java
+++ b/tests/net/java/com/android/server/connectivity/VpnTest.java
@@ -59,9 +59,15 @@
 import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.net.ConnectivityManager;
+import android.net.Ikev2VpnProfile;
+import android.net.InetAddresses;
+import android.net.IpPrefix;
+import android.net.IpSecManager;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.net.NetworkCapabilities;
 import android.net.NetworkInfo.DetailedState;
+import android.net.RouteInfo;
 import android.net.UidRange;
 import android.net.VpnManager;
 import android.net.VpnService;
@@ -72,6 +78,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.Settings;
 import android.security.Credentials;
 import android.security.KeyStore;
 import android.util.ArrayMap;
@@ -83,6 +90,7 @@
 import com.android.internal.R;
 import com.android.internal.net.VpnConfig;
 import com.android.internal.net.VpnProfile;
+import com.android.server.IpSecService;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -92,6 +100,7 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.net.Inet4Address;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -124,6 +133,9 @@
     }
 
     static final String TEST_VPN_PKG = "com.dummy.vpn";
+    private static final String TEST_VPN_SERVER = "1.2.3.4";
+    private static final String TEST_VPN_IDENTITY = "identity";
+    private static final byte[] TEST_VPN_PSK = "psk".getBytes();
 
     /**
      * Names and UIDs for some fake packages. Important points:
@@ -150,23 +162,39 @@
     @Mock private Vpn.SystemServices mSystemServices;
     @Mock private Vpn.Ikev2SessionCreator mIkev2SessionCreator;
     @Mock private ConnectivityManager mConnectivityManager;
+    @Mock private IpSecService mIpSecService;
     @Mock private KeyStore mKeyStore;
-    private final VpnProfile mVpnProfile = new VpnProfile("key");
+    private final VpnProfile mVpnProfile;
+
+    private IpSecManager mIpSecManager;
+
+    public VpnTest() throws Exception {
+        // Build an actual VPN profile that is capable of being converted to and from an
+        // Ikev2VpnProfile
+        final Ikev2VpnProfile.Builder builder =
+                new Ikev2VpnProfile.Builder(TEST_VPN_SERVER, TEST_VPN_IDENTITY);
+        builder.setAuthPsk(TEST_VPN_PSK);
+        mVpnProfile = builder.build().toVpnProfile();
+    }
 
     @Before
     public void setUp() throws Exception {
         MockitoAnnotations.initMocks(this);
 
+        mIpSecManager = new IpSecManager(mContext, mIpSecService);
+
         when(mContext.getPackageManager()).thenReturn(mPackageManager);
         setMockedPackages(mPackages);
 
-        when(mContext.getPackageName()).thenReturn(Vpn.class.getPackage().getName());
+        when(mContext.getPackageName()).thenReturn(TEST_VPN_PKG);
+        when(mContext.getOpPackageName()).thenReturn(TEST_VPN_PKG);
         when(mContext.getSystemService(eq(Context.USER_SERVICE))).thenReturn(mUserManager);
         when(mContext.getSystemService(eq(Context.APP_OPS_SERVICE))).thenReturn(mAppOps);
         when(mContext.getSystemService(eq(Context.NOTIFICATION_SERVICE)))
                 .thenReturn(mNotificationManager);
         when(mContext.getSystemService(eq(Context.CONNECTIVITY_SERVICE)))
                 .thenReturn(mConnectivityManager);
+        when(mContext.getSystemService(eq(Context.IPSEC_SERVICE))).thenReturn(mIpSecManager);
         when(mContext.getString(R.string.config_customVpnAlwaysOnDisconnectedDialogComponent))
                 .thenReturn(Resources.getSystem().getString(
                         R.string.config_customVpnAlwaysOnDisconnectedDialogComponent));
@@ -260,17 +288,17 @@
         assertFalse(vpn.getLockdown());
 
         // Set always-on without lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList()));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, Collections.emptyList(), mKeyStore));
         assertTrue(vpn.getAlwaysOn());
         assertFalse(vpn.getLockdown());
 
         // Set always-on with lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList()));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.emptyList(), mKeyStore));
         assertTrue(vpn.getAlwaysOn());
         assertTrue(vpn.getLockdown());
 
         // Remove always-on configuration.
-        assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList()));
+        assertTrue(vpn.setAlwaysOnPackage(null, false, Collections.emptyList(), mKeyStore));
         assertFalse(vpn.getAlwaysOn());
         assertFalse(vpn.getLockdown());
     }
@@ -284,11 +312,11 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on without lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], false, null, mKeyStore));
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1], user.start + PKG_UIDS[2], user.start + PKG_UIDS[3]);
 
         // Set always-on with lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, null, mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
             new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
             new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
@@ -297,7 +325,7 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[1]);
 
         // Switch to another app.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
             new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
             new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
@@ -316,7 +344,8 @@
         final UidRange user = UidRange.createForUser(primaryUser.id);
 
         // Set always-on with lockdown and whitelist app PKGS[2] from lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[2])));
+        assertTrue(vpn.setAlwaysOnPackage(
+                PKGS[1], true, Collections.singletonList(PKGS[2]), mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
                 new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
                 new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
@@ -325,7 +354,8 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[2]);
 
         // Change whitelisted app to PKGS[3].
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[1], true, Collections.singletonList(PKGS[3])));
+        assertTrue(vpn.setAlwaysOnPackage(
+                PKGS[1], true, Collections.singletonList(PKGS[3]), mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
                 new UidRange(user.start + PKG_UIDS[2] + 1, user.stop)
         }));
@@ -337,7 +367,8 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[1], user.start + PKG_UIDS[3]);
 
         // Change the VPN app.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[3])));
+        assertTrue(vpn.setAlwaysOnPackage(
+                PKGS[0], true, Collections.singletonList(PKGS[3]), mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
                 new UidRange(user.start, user.start + PKG_UIDS[1] - 1),
                 new UidRange(user.start + PKG_UIDS[1] + 1, user.start + PKG_UIDS[3] - 1)
@@ -350,7 +381,7 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[3]);
 
         // Remove the whitelist.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, null, mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
                 new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[3] - 1),
                 new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
@@ -363,7 +394,8 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[0]);
 
         // Add the whitelist.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList(PKGS[1])));
+        assertTrue(vpn.setAlwaysOnPackage(
+                PKGS[0], true, Collections.singletonList(PKGS[1]), mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[] {
                 new UidRange(user.start + PKG_UIDS[0] + 1, user.stop)
         }));
@@ -375,12 +407,13 @@
         assertUnblocked(vpn, user.start + PKG_UIDS[0], user.start + PKG_UIDS[1]);
 
         // Try whitelisting a package with a comma, should be rejected.
-        assertFalse(vpn.setAlwaysOnPackage(PKGS[0], true, Collections.singletonList("a.b,c.d")));
+        assertFalse(vpn.setAlwaysOnPackage(
+                PKGS[0], true, Collections.singletonList("a.b,c.d"), mKeyStore));
 
         // Pass a non-existent packages in the whitelist, they (and only they) should be ignored.
         // Whitelisted package should change from PGKS[1] to PKGS[2].
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[0], true,
-                Arrays.asList("com.foo.app", PKGS[2], "com.bar.app")));
+        assertTrue(vpn.setAlwaysOnPackage(
+                PKGS[0], true, Arrays.asList("com.foo.app", PKGS[2], "com.bar.app"), mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(false), aryEq(new UidRange[]{
                 new UidRange(user.start + PKG_UIDS[0] + 1, user.start + PKG_UIDS[1] - 1),
                 new UidRange(user.start + PKG_UIDS[1] + 1, user.stop)
@@ -405,7 +438,7 @@
         final UidRange profile = UidRange.createForUser(tempProfile.id);
 
         // Set lockdown.
-        assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null));
+        assertTrue(vpn.setAlwaysOnPackage(PKGS[3], true, null, mKeyStore));
         verify(mNetService).setAllowOnlyVpnForUids(eq(true), aryEq(new UidRange[] {
             new UidRange(user.start, user.start + PKG_UIDS[3] - 1),
             new UidRange(user.start + PKG_UIDS[3] + 1, user.stop)
@@ -499,22 +532,22 @@
                 .thenReturn(Collections.singletonList(resInfo));
 
         // null package name should return false
-        assertFalse(vpn.isAlwaysOnPackageSupported(null));
+        assertFalse(vpn.isAlwaysOnPackageSupported(null, mKeyStore));
 
         // Pre-N apps are not supported
         appInfo.targetSdkVersion = VERSION_CODES.M;
-        assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+        assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
 
         // N+ apps are supported by default
         appInfo.targetSdkVersion = VERSION_CODES.N;
-        assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+        assertTrue(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
 
         // Apps that opt out explicitly are not supported
         appInfo.targetSdkVersion = VERSION_CODES.CUR_DEVELOPMENT;
         Bundle metaData = new Bundle();
         metaData.putBoolean(VpnService.SERVICE_META_DATA_SUPPORTS_ALWAYS_ON, false);
         svcInfo.metaData = metaData;
-        assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0]));
+        assertFalse(vpn.isAlwaysOnPackageSupported(PKGS[0], mKeyStore));
     }
 
     @Test
@@ -531,7 +564,7 @@
                 .cancelAsUser(anyString(), anyInt(), eq(userHandle));
 
         // Start showing a notification for disconnected once always-on.
-        vpn.setAlwaysOnPackage(PKGS[0], false, null);
+        vpn.setAlwaysOnPackage(PKGS[0], false, null, mKeyStore);
         order.verify(mNotificationManager)
                 .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
 
@@ -545,7 +578,7 @@
                 .notifyAsUser(anyString(), anyInt(), any(), eq(userHandle));
 
         // Notification should be cleared after unsetting always-on package.
-        vpn.setAlwaysOnPackage(null, false, null);
+        vpn.setAlwaysOnPackage(null, false, null, mKeyStore);
         order.verify(mNotificationManager).cancelAsUser(anyString(), anyInt(), eq(userHandle));
     }
 
@@ -920,12 +953,68 @@
                         eq(AppOpsManager.MODE_IGNORED));
     }
 
+    private void setAndVerifyAlwaysOnPackage(Vpn vpn, int uid, boolean lockdownEnabled) {
+        assertTrue(vpn.setAlwaysOnPackage(TEST_VPN_PKG, lockdownEnabled, null, mKeyStore));
+
+        verify(mKeyStore).get(eq(vpn.getProfileNameForPackage(TEST_VPN_PKG)));
+        verify(mAppOps).setMode(
+                eq(AppOpsManager.OP_ACTIVATE_PLATFORM_VPN), eq(uid), eq(TEST_VPN_PKG),
+                eq(AppOpsManager.MODE_ALLOWED));
+
+        verify(mSystemServices).settingsSecurePutStringForUser(
+                eq(Settings.Secure.ALWAYS_ON_VPN_APP), eq(TEST_VPN_PKG), eq(primaryUser.id));
+        verify(mSystemServices).settingsSecurePutIntForUser(
+                eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN), eq(lockdownEnabled ? 1 : 0),
+                eq(primaryUser.id));
+        verify(mSystemServices).settingsSecurePutStringForUser(
+                eq(Settings.Secure.ALWAYS_ON_VPN_LOCKDOWN_WHITELIST), eq(""), eq(primaryUser.id));
+    }
+
+    @Test
+    public void testSetAndStartAlwaysOnVpn() throws Exception {
+        final Vpn vpn = createVpn(primaryUser.id);
+        setMockedUsers(primaryUser);
+
+        // UID checks must return a different UID; otherwise it'll be treated as already prepared.
+        final int uid = Process.myUid() + 1;
+        when(mPackageManager.getPackageUidAsUser(eq(TEST_VPN_PKG), anyInt()))
+                .thenReturn(uid);
+        when(mKeyStore.get(vpn.getProfileNameForPackage(TEST_VPN_PKG)))
+                .thenReturn(mVpnProfile.encode());
+
+        setAndVerifyAlwaysOnPackage(vpn, uid, false);
+        assertTrue(vpn.startAlwaysOnVpn(mKeyStore));
+
+        // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
+        // a subsequent CL.
+    }
+
+    @Test
+    public void testStartLegacyVpn() throws Exception {
+        final Vpn vpn = createVpn(primaryUser.id);
+        setMockedUsers(primaryUser);
+
+        // Dummy egress interface
+        final String egressIface = "DUMMY0";
+        final LinkProperties lp = new LinkProperties();
+        lp.setInterfaceName(egressIface);
+
+        final RouteInfo defaultRoute = new RouteInfo(new IpPrefix(Inet4Address.ANY, 0),
+                        InetAddresses.parseNumericAddress("192.0.2.0"), egressIface);
+        lp.addRoute(defaultRoute);
+
+        vpn.startLegacyVpn(mVpnProfile, mKeyStore, lp);
+
+        // TODO: Test the Ikev2VpnRunner started up properly. Relies on utility methods added in
+        // a subsequent CL.
+    }
+
     /**
      * Mock some methods of vpn object.
      */
     private Vpn createVpn(@UserIdInt int userId) {
         return new Vpn(Looper.myLooper(), mContext, mNetService,
-                userId, mSystemServices, mIkev2SessionCreator);
+                userId, mKeyStore, mSystemServices, mIkev2SessionCreator);
     }
 
     private static void assertBlocked(Vpn vpn, int... uids) {
diff --git a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
index 957216e..26916bc 100644
--- a/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
+++ b/tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java
@@ -38,6 +38,7 @@
             "android.app.activity.ActivityThreadClientTest",
             // Test specifications for FrameworksCoreTests.
             "android.app.servertransaction.", // all tests under the package.
+            "android.view.CutoutSpecificationTest",
             "android.view.DisplayCutoutTest",
             "android.view.InsetsAnimationControlImplTest",
             "android.view.InsetsControllerTest",
diff --git a/tools/hiddenapi/merge_csv.py b/tools/hiddenapi/merge_csv.py
index 9661927..6a5b0e1 100755
--- a/tools/hiddenapi/merge_csv.py
+++ b/tools/hiddenapi/merge_csv.py
@@ -14,26 +14,56 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 """
-Merge mutliple CSV files, possibly with different columns, writing to stdout.
+Merge multiple CSV files, possibly with different columns.
 """
 
+import argparse
 import csv
-import sys
+import io
 
-csv_readers = [
-    csv.DictReader(open(csv_file, 'r'), delimiter=',', quotechar='|')
-    for csv_file in sys.argv[1:]
-]
+from zipfile import ZipFile
 
-# Build union of all columns from source files:
+args_parser = argparse.ArgumentParser(description='Merge given CSV files into a single one.')
+args_parser.add_argument('--header', help='Comma separated field names; '
+                                          'if missing determines the header from input files.')
+args_parser.add_argument('--zip_input', help='ZIP archive with all CSV files to merge.')
+args_parser.add_argument('--output', help='Output file for merged CSV.',
+                         default='-', type=argparse.FileType('w'))
+args_parser.add_argument('files', nargs=argparse.REMAINDER)
+args = args_parser.parse_args()
+
+
+def dict_reader(input):
+    return csv.DictReader(input, delimiter=',', quotechar='|')
+
+
+if args.zip_input and len(args.files) > 0:
+    raise ValueError('Expecting either a single ZIP with CSV files'
+                     ' or a list of CSV files as input; not both.')
+
+csv_readers = []
+if len(args.files) > 0:
+    for file in args.files:
+        csv_readers.append(dict_reader(open(file, 'r')))
+elif args.zip_input:
+    with ZipFile(args.zip_input) as zip:
+        for entry in zip.namelist():
+            if entry.endswith('.uau'):
+                csv_readers.append(dict_reader(io.TextIOWrapper(zip.open(entry, 'r'))))
+
 headers = set()
-for reader in csv_readers:
-    headers = headers.union(reader.fieldnames)
+if args.header:
+    fieldnames = args.header.split(',')
+else:
+    # Build union of all columns from source files:
+    for reader in csv_readers:
+        headers = headers.union(reader.fieldnames)
+    fieldnames = sorted(headers)
 
 # Concatenate all files to output:
-out = csv.DictWriter(sys.stdout, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL,
-                     dialect='unix', fieldnames=sorted(headers))
-out.writeheader()
+writer = csv.DictWriter(args.output, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL,
+                        dialect='unix', fieldnames=fieldnames)
+writer.writeheader()
 for reader in csv_readers:
     for row in reader:
-        out.writerow(row)
+        writer.writerow(row)
diff --git a/tools/stats_log_api_gen/Android.bp b/tools/stats_log_api_gen/Android.bp
index a251c05..d5031d7 100644
--- a/tools/stats_log_api_gen/Android.bp
+++ b/tools/stats_log_api_gen/Android.bp
@@ -121,7 +121,13 @@
     shared_libs: [
         "liblog",
         "libcutils",
+        "libstatssocket",
     ],
-    static_libs: ["libstatssocket"],
+    apex_available: [
+        "//apex_available:platform",
+        //TODO(b/149781190): Remove this once statsd no longer depends on libstatslog
+        "com.android.os.statsd",
+        "test_com.android.os.statsd",
+    ],
 }
 
diff --git a/wifi/Android.bp b/wifi/Android.bp
index 9f26203..5c9fb4e 100644
--- a/wifi/Android.bp
+++ b/wifi/Android.bp
@@ -86,7 +86,6 @@
         // TODO(b/146757305): should be unnecessary once
         // sdk_version="module_lib_current"
         "android_system_stubs_current",
-        "framework_mediaprovider_annotation", // for android.annotation.CurrentTimeMillisLong
     ],
     srcs: [
         ":framework-wifi-updatable-sources",
diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl
index 1c330e2..3025caf 100644
--- a/wifi/java/android/net/wifi/IWifiManager.aidl
+++ b/wifi/java/android/net/wifi/IWifiManager.aidl
@@ -125,6 +125,8 @@
 
     DhcpInfo getDhcpInfo();
 
+    void setScanAlwaysAvailable(boolean isAvailable);
+
     boolean isScanAlwaysAvailable();
 
     boolean acquireWifiLock(IBinder lock, int lockType, String tag, in WorkSource ws);
diff --git a/wifi/java/android/net/wifi/SoftApConfiguration.java b/wifi/java/android/net/wifi/SoftApConfiguration.java
index 0db3313..ae5bf7d 100644
--- a/wifi/java/android/net/wifi/SoftApConfiguration.java
+++ b/wifi/java/android/net/wifi/SoftApConfiguration.java
@@ -17,6 +17,7 @@
 package android.net.wifi;
 
 import android.annotation.IntDef;
+import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
@@ -202,6 +203,11 @@
     private final List<MacAddress> mAllowedClientList;
 
     /**
+     * Whether auto shutdown of soft AP is enabled or not.
+     */
+    private final boolean mAutoShutdownEnabled;
+
+    /**
      * Delay in milliseconds before shutting down soft AP when
      * there are no connected devices.
      */
@@ -240,9 +246,9 @@
     /** Private constructor for Builder and Parcelable implementation. */
     private SoftApConfiguration(@Nullable String ssid, @Nullable MacAddress bssid,
             @Nullable String passphrase, boolean hiddenSsid, @BandType int band, int channel,
-            @SecurityType int securityType, int maxNumberOfClients, int shutdownTimeoutMillis,
-            boolean clientControlByUser, @NonNull List<MacAddress> blockedList,
-            @NonNull List<MacAddress> allowedList) {
+            @SecurityType int securityType, int maxNumberOfClients, boolean shutdownTimeoutEnabled,
+            int shutdownTimeoutMillis, boolean clientControlByUser,
+            @NonNull List<MacAddress> blockedList, @NonNull List<MacAddress> allowedList) {
         mSsid = ssid;
         mBssid = bssid;
         mPassphrase = passphrase;
@@ -251,6 +257,7 @@
         mChannel = channel;
         mSecurityType = securityType;
         mMaxNumberOfClients = maxNumberOfClients;
+        mAutoShutdownEnabled = shutdownTimeoutEnabled;
         mShutdownTimeoutMillis = shutdownTimeoutMillis;
         mClientControlByUser = clientControlByUser;
         mBlockedClientList = new ArrayList<>(blockedList);
@@ -274,6 +281,7 @@
                 && mChannel == other.mChannel
                 && mSecurityType == other.mSecurityType
                 && mMaxNumberOfClients == other.mMaxNumberOfClients
+                && mAutoShutdownEnabled == other.mAutoShutdownEnabled
                 && mShutdownTimeoutMillis == other.mShutdownTimeoutMillis
                 && mClientControlByUser == other.mClientControlByUser
                 && Objects.equals(mBlockedClientList, other.mBlockedClientList)
@@ -283,8 +291,9 @@
     @Override
     public int hashCode() {
         return Objects.hash(mSsid, mBssid, mPassphrase, mHiddenSsid,
-                mBand, mChannel, mSecurityType, mMaxNumberOfClients, mShutdownTimeoutMillis,
-                mClientControlByUser, mBlockedClientList, mAllowedClientList);
+                mBand, mChannel, mSecurityType, mMaxNumberOfClients, mAutoShutdownEnabled,
+                mShutdownTimeoutMillis, mClientControlByUser, mBlockedClientList,
+                mAllowedClientList);
     }
 
     @Override
@@ -299,6 +308,7 @@
         sbuf.append(" \n Channel =").append(mChannel);
         sbuf.append(" \n SecurityType=").append(getSecurityType());
         sbuf.append(" \n MaxClient=").append(mMaxNumberOfClients);
+        sbuf.append(" \n AutoShutdownEnabled=").append(mAutoShutdownEnabled);
         sbuf.append(" \n ShutdownTimeoutMillis=").append(mShutdownTimeoutMillis);
         sbuf.append(" \n ClientControlByUser=").append(mClientControlByUser);
         sbuf.append(" \n BlockedClientList=").append(mBlockedClientList);
@@ -316,6 +326,7 @@
         dest.writeInt(mChannel);
         dest.writeInt(mSecurityType);
         dest.writeInt(mMaxNumberOfClients);
+        dest.writeBoolean(mAutoShutdownEnabled);
         dest.writeInt(mShutdownTimeoutMillis);
         dest.writeBoolean(mClientControlByUser);
         dest.writeTypedList(mBlockedClientList);
@@ -335,7 +346,7 @@
                     in.readString(),
                     in.readParcelable(MacAddress.class.getClassLoader()),
                     in.readString(), in.readBoolean(), in.readInt(), in.readInt(), in.readInt(),
-                    in.readInt(), in.readInt(), in.readBoolean(),
+                    in.readInt(), in.readBoolean(), in.readInt(), in.readBoolean(),
                     in.createTypedArrayList(MacAddress.CREATOR),
                     in.createTypedArrayList(MacAddress.CREATOR));
         }
@@ -429,6 +440,18 @@
     }
 
     /**
+     * Returns whether auto shutdown is enabled or not.
+     * The Soft AP will shutdown when there are no devices associated to it for
+     * the timeout duration. See {@link Builder#setAutoShutdownEnabled(boolean)}.
+     *
+     * @hide
+     */
+    @SystemApi
+    public boolean isAutoShutdownEnabled() {
+        return mAutoShutdownEnabled;
+    }
+
+    /**
      * Returns the shutdown timeout in milliseconds.
      * The Soft AP will shutdown when there are no devices associated to it for
      * the timeout duration. See {@link Builder#setShutdownTimeoutMillis(int)}.
@@ -551,6 +574,7 @@
         private int mChannel;
         private int mMaxNumberOfClients;
         private int mSecurityType;
+        private boolean mAutoShutdownEnabled;
         private int mShutdownTimeoutMillis;
         private boolean mClientControlByUser;
         private List<MacAddress> mBlockedClientList;
@@ -568,6 +592,7 @@
             mChannel = 0;
             mMaxNumberOfClients = 0;
             mSecurityType = SECURITY_TYPE_OPEN;
+            mAutoShutdownEnabled = true; // enabled by default.
             mShutdownTimeoutMillis = 0;
             mClientControlByUser = false;
             mBlockedClientList = new ArrayList<>();
@@ -588,6 +613,7 @@
             mChannel = other.mChannel;
             mMaxNumberOfClients = other.mMaxNumberOfClients;
             mSecurityType = other.mSecurityType;
+            mAutoShutdownEnabled = other.mAutoShutdownEnabled;
             mShutdownTimeoutMillis = other.mShutdownTimeoutMillis;
             mClientControlByUser = other.mClientControlByUser;
             mBlockedClientList = new ArrayList<>(other.mBlockedClientList);
@@ -603,8 +629,8 @@
         public SoftApConfiguration build() {
             return new SoftApConfiguration(mSsid, mBssid, mPassphrase,
                     mHiddenSsid, mBand, mChannel, mSecurityType, mMaxNumberOfClients,
-                    mShutdownTimeoutMillis, mClientControlByUser, mBlockedClientList,
-                    mAllowedClientList);
+                    mAutoShutdownEnabled, mShutdownTimeoutMillis, mClientControlByUser,
+                    mBlockedClientList, mAllowedClientList);
         }
 
         /**
@@ -789,7 +815,7 @@
          * @return Builder for chaining.
          */
         @NonNull
-        public Builder setMaxNumberOfClients(int maxNumberOfClients) {
+        public Builder setMaxNumberOfClients(@IntRange(from = 0) int maxNumberOfClients) {
             if (maxNumberOfClients < 0) {
                 throw new IllegalArgumentException("maxNumberOfClients should be not negative");
             }
@@ -798,6 +824,25 @@
         }
 
         /**
+         * Specifies whether auto shutdown is enabled or not.
+         * The Soft AP will shut down when there are no devices connected to it for
+         * the timeout duration.
+         *
+         * <p>
+         * <li>If not set, defaults to true</li>
+         *
+         * @param enable true to enable, false to disable.
+         * @return Builder for chaining.
+         *
+         * @see #setShutdownTimeoutMillis(int)
+         */
+        @NonNull
+        public Builder setAutoShutdownEnabled(boolean enable) {
+            mAutoShutdownEnabled = enable;
+            return this;
+        }
+
+        /**
          * Specifies the shutdown timeout in milliseconds.
          * The Soft AP will shut down when there are no devices connected to it for
          * the timeout duration.
@@ -807,14 +852,16 @@
          *
          * <p>
          * <li>If not set, defaults to 0</li>
-         * <li>The shut down timout will apply when
-         * {@link Settings.Global.SOFT_AP_TIMEOUT_ENABLED} is true</li>
+         * <li>The shut down timeout will apply when {@link #setAutoShutdownEnabled(boolean)} is
+         * set to true</li>
          *
          * @param timeoutMillis milliseconds of the timeout delay.
          * @return Builder for chaining.
+         *
+         * @see #setAutoShutdownEnabled(boolean)
          */
         @NonNull
-        public Builder setShutdownTimeoutMillis(int timeoutMillis) {
+        public Builder setShutdownTimeoutMillis(@IntRange(from = 0) int timeoutMillis) {
             if (timeoutMillis < 0) {
                 throw new IllegalArgumentException("Invalid timeout value");
             }
diff --git a/wifi/java/android/net/wifi/WifiConfiguration.java b/wifi/java/android/net/wifi/WifiConfiguration.java
index e1450cb..1a12af3 100644
--- a/wifi/java/android/net/wifi/WifiConfiguration.java
+++ b/wifi/java/android/net/wifi/WifiConfiguration.java
@@ -2167,6 +2167,7 @@
         sbuf.append("ID: ").append(this.networkId).append(" SSID: ").append(this.SSID).
                 append(" PROVIDER-NAME: ").append(this.providerFriendlyName).
                 append(" BSSID: ").append(this.BSSID).append(" FQDN: ").append(this.FQDN)
+                .append(" HOME-PROVIDER-NETWORK: ").append(this.isHomeProviderNetwork)
                 .append(" PRIO: ").append(this.priority)
                 .append(" HIDDEN: ").append(this.hiddenSSID)
                 .append(" PMF: ").append(this.requirePmf)
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index f693315..bab9a9e 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -46,6 +46,7 @@
 import android.net.wifi.hotspot2.PasspointConfiguration;
 import android.net.wifi.hotspot2.ProvisioningCallback;
 import android.os.Binder;
+import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerExecutor;
 import android.os.IBinder;
@@ -2755,6 +2756,26 @@
     }
 
     /**
+     * Set if scanning is always available.
+     *
+     * If set to {@code true}, apps can issue {@link #startScan} and fetch scan results
+     * even when Wi-Fi is turned off.
+     *
+     * @param isAvailable true to enable, false to disable.
+     * @hide
+     * @see #isScanAlwaysAvailable()
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
+    public void setScanAlwaysAvailable(boolean isAvailable) {
+        try {
+            mService.setScanAlwaysAvailable(isAvailable);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /**
      * Check if scanning is always available.
      *
      * If this return {@code true}, apps can issue {@link #startScan} and fetch scan results
@@ -4900,7 +4921,10 @@
     }
 
     /** @hide */
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(
+            maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@code #setVerboseLoggingEnabled(boolean)} instead."
+    )
     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
     public void enableVerboseLogging (int verbose) {
         try {
@@ -4928,7 +4952,10 @@
 
     /** @hide */
     // TODO(b/145484145): remove once SUW stops calling this via reflection
-    @UnsupportedAppUsage
+    @UnsupportedAppUsage(
+            maxTargetSdk = Build.VERSION_CODES.Q,
+            publicAlternatives = "Use {@code #isVerboseLoggingEnabled()} instead."
+    )
     public int getVerboseLoggingLevel() {
         try {
             return mService.getVerboseLoggingLevel();
diff --git a/wifi/java/android/net/wifi/WifiOemMigrationHook.java b/wifi/java/android/net/wifi/WifiOemMigrationHook.java
index 22d7786..5301dd0 100755
--- a/wifi/java/android/net/wifi/WifiOemMigrationHook.java
+++ b/wifi/java/android/net/wifi/WifiOemMigrationHook.java
@@ -21,8 +21,10 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.content.Context;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.provider.Settings;
 
 import java.util.List;
 
@@ -33,6 +35,9 @@
  */
 @SystemApi
 public final class WifiOemMigrationHook {
+
+    private WifiOemMigrationHook() { }
+
     /**
      * Container for all the wifi config data to migrate.
      */
@@ -152,8 +157,6 @@
         }
     }
 
-    private WifiOemMigrationHook() { }
-
     /**
      * Load data from OEM's config store.
      * <p>
@@ -178,4 +181,263 @@
         // Note: OEM's should add code to parse data from their config store format here!
         return null;
     }
+
+    /**
+     * Container for all the wifi settings data to migrate.
+     */
+    public static final class SettingsMigrationData implements Parcelable {
+        private final boolean mScanAlwaysAvailable;
+        private final boolean mP2pFactoryResetPending;
+        private final String mP2pDeviceName;
+        private final boolean mSoftApTimeoutEnabled;
+        private final boolean mWakeupEnabled;
+        private final boolean mScanThrottleEnabled;
+        private final boolean mVerboseLoggingEnabled;
+
+        private SettingsMigrationData(boolean scanAlwaysAvailable, boolean p2pFactoryResetPending,
+                @Nullable String p2pDeviceName, boolean softApTimeoutEnabled, boolean wakeupEnabled,
+                boolean scanThrottleEnabled, boolean verboseLoggingEnabled) {
+            mScanAlwaysAvailable = scanAlwaysAvailable;
+            mP2pFactoryResetPending = p2pFactoryResetPending;
+            mP2pDeviceName = p2pDeviceName;
+            mSoftApTimeoutEnabled = softApTimeoutEnabled;
+            mWakeupEnabled = wakeupEnabled;
+            mScanThrottleEnabled = scanThrottleEnabled;
+            mVerboseLoggingEnabled = verboseLoggingEnabled;
+        }
+
+        public static final @NonNull Parcelable.Creator<SettingsMigrationData> CREATOR =
+                new Parcelable.Creator<SettingsMigrationData>() {
+                    @Override
+                    public SettingsMigrationData createFromParcel(Parcel in) {
+                        boolean scanAlwaysAvailable = in.readBoolean();
+                        boolean p2pFactoryResetPending = in.readBoolean();
+                        String p2pDeviceName = in.readString();
+                        boolean softApTimeoutEnabled = in.readBoolean();
+                        boolean wakeupEnabled = in.readBoolean();
+                        boolean scanThrottleEnabled = in.readBoolean();
+                        boolean verboseLoggingEnabled = in.readBoolean();
+                        return new SettingsMigrationData(
+                                scanAlwaysAvailable, p2pFactoryResetPending,
+                                p2pDeviceName, softApTimeoutEnabled, wakeupEnabled,
+                                scanThrottleEnabled, verboseLoggingEnabled);
+                    }
+
+                    @Override
+                    public SettingsMigrationData[] newArray(int size) {
+                        return new SettingsMigrationData[size];
+                    }
+                };
+
+        @Override
+        public int describeContents() {
+            return 0;
+        }
+
+        @Override
+        public void writeToParcel(@NonNull Parcel dest, int flags) {
+            dest.writeBoolean(mScanAlwaysAvailable);
+            dest.writeBoolean(mP2pFactoryResetPending);
+            dest.writeString(mP2pDeviceName);
+            dest.writeBoolean(mSoftApTimeoutEnabled);
+            dest.writeBoolean(mWakeupEnabled);
+            dest.writeBoolean(mScanThrottleEnabled);
+            dest.writeBoolean(mVerboseLoggingEnabled);
+        }
+
+        /**
+         * @return True if scans are allowed even when wifi is toggled off, false otherwise.
+         */
+        public boolean isScanAlwaysAvailable() {
+            return mScanAlwaysAvailable;
+        }
+
+        /**
+         * @return indicate whether factory reset request is pending.
+         */
+        public boolean isP2pFactoryResetPending() {
+            return mP2pFactoryResetPending;
+        }
+
+        /**
+         * @return the Wi-Fi peer-to-peer device name
+         */
+        public @Nullable String getP2pDeviceName() {
+            return mP2pDeviceName;
+        }
+
+        /**
+         * @return Whether soft AP will shut down after a timeout period when no devices are
+         * connected.
+         */
+        public boolean isSoftApTimeoutEnabled() {
+            return mSoftApTimeoutEnabled;
+        }
+
+        /**
+         * @return whether Wi-Fi Wakeup feature is enabled.
+         */
+        public boolean isWakeUpEnabled() {
+            return mWakeupEnabled;
+        }
+
+        /**
+         * @return Whether wifi scan throttle is enabled or not.
+         */
+        public boolean isScanThrottleEnabled() {
+            return mScanThrottleEnabled;
+        }
+
+        /**
+         * @return Whether to enable verbose logging in Wi-Fi.
+         */
+        public boolean isVerboseLoggingEnabled() {
+            return mVerboseLoggingEnabled;
+        }
+
+        /**
+         * Builder to create instance of {@link SettingsMigrationData}.
+         */
+        public static final class Builder {
+            private boolean mScanAlwaysAvailable;
+            private boolean mP2pFactoryResetPending;
+            private String mP2pDeviceName;
+            private boolean mSoftApTimeoutEnabled;
+            private boolean mWakeupEnabled;
+            private boolean mScanThrottleEnabled;
+            private boolean mVerboseLoggingEnabled;
+
+            public Builder() {
+            }
+
+            /**
+             * Setting to allow scans even when wifi is toggled off.
+             *
+             * @param available true if available, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setScanAlwaysAvailable(boolean available) {
+                mScanAlwaysAvailable = available;
+                return this;
+            }
+
+            /**
+             * Indicate whether factory reset request is pending.
+             *
+             * @param pending true if pending, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setP2pFactoryResetPending(boolean pending) {
+                mP2pFactoryResetPending = pending;
+                return this;
+            }
+
+            /**
+             * The Wi-Fi peer-to-peer device name
+             *
+             * @param name Name if set, null otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setP2pDeviceName(@Nullable String name) {
+                mP2pDeviceName = name;
+                return this;
+            }
+
+            /**
+             * Whether soft AP will shut down after a timeout period when no devices are connected.
+             *
+             * @param enabled true if enabled, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setSoftApTimeoutEnabled(boolean enabled) {
+                mSoftApTimeoutEnabled = enabled;
+                return this;
+            }
+
+            /**
+             * Value to specify if Wi-Fi Wakeup feature is enabled.
+             *
+             * @param enabled true if enabled, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setWakeUpEnabled(boolean enabled) {
+                mWakeupEnabled = enabled;
+                return this;
+            }
+
+            /**
+             * Whether wifi scan throttle is enabled or not.
+             *
+             * @param enabled true if enabled, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setScanThrottleEnabled(boolean enabled) {
+                mScanThrottleEnabled = enabled;
+                return this;
+            }
+
+            /**
+             * Setting to enable verbose logging in Wi-Fi.
+             *
+             * @param enabled true if enabled, false otherwise.
+             * @return Instance of {@link Builder} to enable chaining of the builder method.
+             */
+            public @NonNull Builder setVerboseLoggingEnabled(boolean enabled) {
+                mVerboseLoggingEnabled = enabled;
+                return this;
+            }
+
+            /**
+             * Build an instance of {@link SettingsMigrationData}.
+             *
+             * @return Instance of {@link SettingsMigrationData}.
+             */
+            public @NonNull SettingsMigrationData build() {
+                return new SettingsMigrationData(mScanAlwaysAvailable, mP2pFactoryResetPending,
+                        mP2pDeviceName, mSoftApTimeoutEnabled, mWakeupEnabled, mScanThrottleEnabled,
+                        mVerboseLoggingEnabled);
+            }
+        }
+    }
+
+    /**
+     * Load data from Settings.Global values.
+     *
+     * <p>
+     * Note:
+     * <li> This is method is invoked once on the first bootup. OEM can safely delete these settings
+     * once the migration is complete. The first & only relevant invocation of
+     * {@link #loadFromSettings(Context)} ()} occurs when a previously released
+     * device upgrades to the wifi mainline module from an OEM implementation of the wifi stack.
+     * </li>
+     *
+     * @param context Context to use for loading the settings provider.
+     * @return Instance of {@link SettingsMigrationData} for migrating data.
+     */
+    @NonNull
+    public static SettingsMigrationData loadFromSettings(@NonNull Context context) {
+        return new SettingsMigrationData.Builder()
+                .setScanAlwaysAvailable(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.WIFI_SCAN_ALWAYS_AVAILABLE, 0) == 1)
+                .setP2pFactoryResetPending(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.WIFI_P2P_PENDING_FACTORY_RESET, 0) == 1)
+                .setP2pDeviceName(
+                        Settings.Global.getString(context.getContentResolver(),
+                                Settings.Global.WIFI_P2P_DEVICE_NAME))
+                .setSoftApTimeoutEnabled(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.SOFT_AP_TIMEOUT_ENABLED, 1) == 1)
+                .setWakeUpEnabled(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.WIFI_WAKEUP_ENABLED, 0) == 1)
+                .setScanThrottleEnabled(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.WIFI_SCAN_THROTTLE_ENABLED, 1) == 1)
+                .setVerboseLoggingEnabled(
+                        Settings.Global.getInt(context.getContentResolver(),
+                                Settings.Global.WIFI_VERBOSE_LOGGING_ENABLED, 0) == 1)
+                .build();
+    }
 }
diff --git a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
index 7d9bdba..4507cc2 100644
--- a/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
+++ b/wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
@@ -900,12 +900,15 @@
     }
 
     /**
-     * Get a unique identifier for a PasspointConfiguration object.
+     * Get a unique identifier for a PasspointConfiguration object. The identifier depends on the
+     * configuration that identify the service provider under the HomeSp subtree, and on the
+     * credential configuration under the Credential subtree.
+     * The method throws an {@link IllegalStateException} if the configuration under HomeSp subtree
+     * or the configuration under Credential subtree are not initialized.
      *
      * @return A unique identifier
-     * @throws IllegalStateException if Credential or HomeSP nodes are not initialized
      */
-    public @NonNull String getUniqueId() throws IllegalStateException {
+    public @NonNull String getUniqueId() {
         if (mCredential == null || mHomeSp == null || TextUtils.isEmpty(mHomeSp.getFqdn())) {
             throw new IllegalStateException("Credential or HomeSP are not initialized");
         }
diff --git a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
index d958488..060ddf0 100644
--- a/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/SoftApConfigurationTest.java
@@ -125,6 +125,7 @@
                 .setChannel(149, SoftApConfiguration.BAND_5GHZ)
                 .setHiddenSsid(true)
                 .setMaxNumberOfClients(10)
+                .setAutoShutdownEnabled(true)
                 .setShutdownTimeoutMillis(500000)
                 .enableClientControlByUser(true)
                 .setClientList(testBlockedClientList, testAllowedClientList)
@@ -136,6 +137,7 @@
         assertThat(original.getChannel()).isEqualTo(149);
         assertThat(original.isHiddenSsid()).isEqualTo(true);
         assertThat(original.getMaxNumberOfClients()).isEqualTo(10);
+        assertThat(original.isAutoShutdownEnabled()).isEqualTo(true);
         assertThat(original.getShutdownTimeoutMillis()).isEqualTo(500000);
         assertThat(original.isClientControlByUserEnabled()).isEqualTo(true);
         assertThat(original.getBlockedClientList()).isEqualTo(testBlockedClientList);
diff --git a/wifi/tests/src/android/net/wifi/WifiManagerTest.java b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
index 853212a..234d929 100644
--- a/wifi/tests/src/android/net/wifi/WifiManagerTest.java
+++ b/wifi/tests/src/android/net/wifi/WifiManagerTest.java
@@ -2401,4 +2401,15 @@
         assertFalse(mWifiManager.isAutoWakeupEnabled());
         verify(mWifiService).isAutoWakeupEnabled();
     }
+
+
+    @Test
+    public void testScanAvailable() throws Exception {
+        mWifiManager.setScanAlwaysAvailable(true);
+        verify(mWifiService).setScanAlwaysAvailable(true);
+
+        when(mWifiService.isScanAlwaysAvailable()).thenReturn(false);
+        assertFalse(mWifiManager.isScanAlwaysAvailable());
+        verify(mWifiService).isScanAlwaysAvailable();
+    }
 }
diff --git a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
index 8f6beb1..638efb9 100644
--- a/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
+++ b/wifi/tests/src/android/net/wifi/hotspot2/PasspointConfigurationTest.java
@@ -426,17 +426,11 @@
      *
      * @throws Exception
      */
-    @Test
+    @Test (expected = IllegalStateException.class)
     public void validateUniqueIdExceptionWithEmptyHomeSp() throws Exception {
         PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setHomeSp(null);
-        boolean exceptionCaught = false;
-        try {
-            String uniqueId = config.getUniqueId();
-        } catch (IllegalStateException e) {
-            exceptionCaught = true;
-        }
-        assertTrue(exceptionCaught);
+        String uniqueId = config.getUniqueId();
     }
 
     /**
@@ -445,16 +439,10 @@
      *
      * @throws Exception
      */
-    @Test
+    @Test (expected = IllegalStateException.class)
     public void validateUniqueIdExceptionWithEmptyCredential() throws Exception {
         PasspointConfiguration config = PasspointTestUtils.createConfig();
         config.setCredential(null);
-        boolean exceptionCaught = false;
-        try {
-            String uniqueId = config.getUniqueId();
-        } catch (IllegalStateException e) {
-            exceptionCaught = true;
-        }
-        assertTrue(exceptionCaught);
+        String uniqueId = config.getUniqueId();
     }
 }