Merge "Add libstatspull and libstatssocket to the apex"
diff --git a/Android.bp b/Android.bp
index 2534140..68efd59 100644
--- a/Android.bp
+++ b/Android.bp
@@ -393,7 +393,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",
@@ -597,7 +597,7 @@
     installable: true,
     libs: ["app-compat-annotations"],
     srcs: [
-        "core/java/android/content/pm/parsing/library/AndroidTestBaseUpdater.java",
+        "core/java/android/content/pm/AndroidTestBaseUpdater.java",
     ],
 }
 
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 1cc1c5f..aae33d7 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,
@@ -392,7 +423,7 @@
                 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);
                     }
@@ -491,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();
@@ -580,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();
@@ -704,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);
                 }
             }
@@ -724,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);
                 }
             }
@@ -747,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());
                 }
             }
 
@@ -757,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) {
@@ -777,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);
                     }
@@ -812,7 +849,7 @@
 
                 if (shouldRemove) {
                     blobMetadata.getBlobFile().delete();
-                    mKnownBlobIds.remove(blobMetadata.getBlobId());
+                    mActiveBlobIds.remove(blobMetadata.getBlobId());
                     deletedBlobIds.add(blobMetadata.getBlobId());
                 }
                 return shouldRemove;
@@ -842,7 +879,7 @@
 
                 if (shouldRemove) {
                     blobStoreSession.getSessionFile().delete();
-                    mKnownBlobIds.remove(blobStoreSession.getSessionId());
+                    mActiveBlobIds.remove(blobStoreSession.getSessionId());
                     indicesToRemove.add(j);
                     deletedBlobIds.add(blobStoreSession.getSessionId());
                 }
@@ -889,7 +926,7 @@
             }
             blobMetadata.getBlobFile().delete();
             userBlobs.remove(blobHandle);
-            mKnownBlobIds.remove(blobMetadata.getBlobId());
+            mActiveBlobIds.remove(blobMetadata.getBlobId());
             writeBlobsInfoAsync();
         }
     }
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 bf61eb4..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;
@@ -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/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/statsd/Android.bp b/apex/statsd/Android.bp
index 86a3a7d..2f3e2ac 100644
--- a/apex/statsd/Android.bp
+++ b/apex/statsd/Android.bp
@@ -24,13 +24,13 @@
         "libstatspull",
         "libstatssocket",
     ],
-    // binaries: ["vold"],
+    binaries: ["statsd"],
     java_libs: [
         "framework-statsd",
         "service-statsd",
     ],
     compile_multilib: "both",
-    // prebuilts: ["my_prebuilt"],
+    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",
@@ -49,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 {
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 702744d..b6f1f28 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2983,7 +2983,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();
@@ -2992,6 +2991,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.pm.PackageManager);
     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);
@@ -23175,7 +23175,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();
@@ -46550,8 +46550,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";
@@ -47065,6 +47065,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();
@@ -47227,32 +47571,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 {
@@ -47442,18 +47762,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);
@@ -47810,7 +48118,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();
@@ -56419,7 +56726,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;
   }
@@ -56427,7 +56734,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);
   }
 
 }
diff --git a/api/system-current.txt b/api/system-current.txt
index 202a939..330d03f 100755
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -137,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";
@@ -1959,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();
@@ -3776,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";
@@ -10212,6 +10222,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";
   }
@@ -11389,347 +11400,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 957794c..8a0be69 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -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();
@@ -3145,6 +3150,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/statsd/Android.bp b/cmds/statsd/Android.bp
index 4991a95..73a8f66 100644
--- a/cmds/statsd/Android.bp
+++ b/cmds/statsd/Android.bp
@@ -217,7 +217,10 @@
 
     shared_libs: ["libgtest_prod"],
 
-    init_rc: ["statsd.rc"],
+    apex_available: [
+        "com.android.os.statsd",
+        "test_com.android.os.statsd",
+    ],
 }
 
 // ==============
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index a4e8fdc..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 //
 //////////////////////////////////////////////////////////////////////
diff --git a/core/java/android/accessibilityservice/AccessibilityServiceInfo.java b/core/java/android/accessibilityservice/AccessibilityServiceInfo.java
index c1e2195..c373284 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,33 @@
      *    {@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 PackageManager packageManager)  {
+        if (mAnimatedImageRes == /* invalid */ 0) {
+            return null;
+        }
+
+        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..d537ce1 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,31 @@
      * 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 PackageManager packageManager) {
+        if (mAnimatedImageRes == /* invalid */ 0) {
+            return null;
+        }
+
+        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/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/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/pm/AndroidTestBaseUpdater.java b/core/java/android/content/pm/AndroidTestBaseUpdater.java
new file mode 100644
index 0000000..1cbbdca
--- /dev/null
+++ b/core/java/android/content/pm/AndroidTestBaseUpdater.java
@@ -0,0 +1,26 @@
+/*
+ * 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;
+
+/**
+ * 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
+ */
+public class AndroidTestBaseUpdater {
+}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index b89901a..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.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 168679e..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;
 
@@ -1054,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
@@ -1082,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
@@ -1284,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);
@@ -1346,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 {
@@ -1695,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;
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/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/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 2003ce2..0000000
--- a/core/java/android/content/pm/parsing/AndroidPackage.java
+++ /dev/null
@@ -1,497 +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
-
-    @Nullable
-    Set<String> getMimeGroups();
-
-    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 9087f42..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 {
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 6852a8c..0000000
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ /dev/null
@@ -1,3793 +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_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) {
-                        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 d06865b..0000000
--- a/core/java/android/content/pm/parsing/PackageImpl.java
+++ /dev/null
@@ -1,3379 +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.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.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.ParsedComponent;
-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;
-
-    @Nullable
-    private ArraySet<String> mimeGroups;
-
-    @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);
-        addMimeGroupsFromComponent(parsedActivity);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addReceiver(ParsedActivity parsedReceiver) {
-        this.receivers = ArrayUtils.add(this.receivers, parsedReceiver);
-        addMimeGroupsFromComponent(parsedReceiver);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addService(ParsedService parsedService) {
-        this.services = ArrayUtils.add(this.services, parsedService);
-        addMimeGroupsFromComponent(parsedService);
-        return this;
-    }
-
-    @Override
-    public ParsingPackage addProvider(ParsedProvider parsedProvider) {
-        this.providers = ArrayUtils.add(this.providers, parsedProvider);
-        addMimeGroupsFromComponent(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;
-    }
-
-    private void addMimeGroupsFromComponent(ParsedComponent<?> component) {
-        for (int i = component.intents.size() - 1; i >= 0; i--) {
-            IntentFilter filter = component.intents.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;
-    }
-
-    @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);
-        dest.writeArraySet(this.mimeGroups);
-    }
-
-    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();
-        this.mimeGroups = (ArraySet<String>) in.readArraySet(boot);
-    }
-
-    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/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/debug/AdbTransportType.aidl b/core/java/android/debug/AdbTransportType.aidl
new file mode 100644
index 0000000..6904615
--- /dev/null
+++ b/core/java/android/debug/AdbTransportType.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.debug;
+
+/** @hide */
+@Backing(type="byte")
+enum AdbTransportType {
+    USB,
+    WIFI,
+}
+
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/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/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/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/provider/Settings.java b/core/java/android/provider/Settings.java
index 9511152..b9abdf8 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -11509,6 +11509,7 @@
          * exempted_sync_duration           (long)
          * system_interaction_duration      (long)
          * initial_foreground_service_start_duration (long)
+         * cross_profile_apps_share_standby_buckets  (boolean)
          * </pre>
          *
          * <p>
@@ -14325,7 +14326,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/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index deff79d5..73707ca 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -1586,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 4c7307e..11ab572 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13442,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;
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..1e6abd9 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;
@@ -1430,10 +1403,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 +1795,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 9de1222..22af9af 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;
@@ -394,6 +395,19 @@
     // 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.
@@ -440,8 +454,6 @@
     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);
         float aspectRatio = AppGlobals.getFloatCoreSetting(
@@ -454,13 +466,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 +4921,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 +5136,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 {
diff --git a/core/java/android/widget/Magnifier.java b/core/java/android/widget/Magnifier.java
index 47ea1cb..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() {
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/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
index f699eb8..ffa347c 100644
--- a/core/java/com/android/internal/content/om/OverlayConfig.java
+++ b/core/java/com/android/internal/content/om/OverlayConfig.java
@@ -19,7 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.pm.PackagePartitions;
-import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.ParsingPackageRead;
 import android.os.Build;
 import android.os.Process;
 import android.os.Trace;
@@ -36,7 +36,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Comparator;
-import java.util.function.Consumer;
+import java.util.function.BiConsumer;
 import java.util.function.Supplier;
 
 /**
@@ -71,10 +71,10 @@
      * Interface for providing information on scanned packages.
      * TODO(147840005): Remove this when android:isStatic and android:priority are fully deprecated
      */
-    public interface AndroidPackageProvider {
+    public interface PackageProvider {
 
         /** Performs the given action for each package. */
-        void forEachPackage(Consumer<AndroidPackage> p);
+        void forEachPackage(BiConsumer<ParsingPackageRead, Boolean> p);
     }
 
     private static final Comparator<ParsedConfiguration> sStaticOverlayComparator = (c1, c2) -> {
@@ -100,7 +100,7 @@
     @VisibleForTesting
     public OverlayConfig(@Nullable File rootDirectory,
             @Nullable Supplier<OverlayScanner> scannerFactory,
-            @Nullable AndroidPackageProvider packageProvider) {
+            @Nullable PackageProvider packageProvider) {
         Preconditions.checkArgument((scannerFactory == null) != (packageProvider == null),
                 "scannerFactory and packageProvider cannot be both null or both non-null");
 
@@ -208,7 +208,7 @@
      * {@link #getSystemInstance()} will return the initialized instance.
      */
     @NonNull
-    public static OverlayConfig initializeSystemInstance(AndroidPackageProvider packageProvider) {
+    public static OverlayConfig initializeSystemInstance(PackageProvider packageProvider) {
         if (Process.myUid() != Process.SYSTEM_UID) {
             throw new IllegalStateException("Can only be invoked in the system process");
         }
@@ -221,7 +221,7 @@
 
     /**
      * Retrieves the singleton instance initialized by
-     * {@link #initializeSystemInstance(AndroidPackageProvider)}.
+     * {@link #initializeSystemInstance(PackageProvider)}.
      */
     @NonNull
     public static OverlayConfig getSystemInstance() {
@@ -291,10 +291,10 @@
 
     @NonNull
     private static ArrayList<ParsedOverlayInfo> getOverlayPackageInfos(
-            @NonNull AndroidPackageProvider packageManager) {
+            @NonNull PackageProvider packageManager) {
         final ArrayList<ParsedOverlayInfo> overlays = new ArrayList<>();
-        packageManager.forEachPackage((AndroidPackage p) -> {
-            if (p.getOverlayTarget() != null && p.isSystem()) {
+        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())));
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/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/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/InlineSuggestionsRequestInfo.aidl b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.aidl
new file mode 100644
index 0000000..8125c0d
--- /dev/null
+++ b/core/java/com/android/internal/view/InlineSuggestionsRequestInfo.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+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/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/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 62e57e4..ddfc4b8 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" />
@@ -2771,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"/>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index c15b794..6ca5081 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -3532,6 +3532,8 @@
      mode -->
     <string-array translatable="false" name="config_priorityOnlyDndExemptPackages">
         <item>com.android.dialer</item>
+        <item>com.android.systemui</item>
+        <item>android</item>
     </string-array>
 
     <!-- The default value for transition animation scale found in developer settings.
diff --git a/core/tests/coretests/Android.bp b/core/tests/coretests/Android.bp
index 8e4e684..33fead6 100644
--- a/core/tests/coretests/Android.bp
+++ b/core/tests/coretests/Android.bp
@@ -83,21 +83,13 @@
         ":FrameworksCoreTests_install_bad_dex",
         ":FrameworksCoreTests_install_complete_package_info",
         ":FrameworksCoreTests_install_decl_perm",
-        ":FrameworksCoreTests_install_intent_filters",
         ":FrameworksCoreTests_install_jni_lib_open_from_apk",
         ":FrameworksCoreTests_install_loc_auto",
         ":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",
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_intent_filters/Android.bp b/core/tests/coretests/apks/install_intent_filters/Android.bp
deleted file mode 100644
index 6cc5eba..0000000
--- a/core/tests/coretests/apks/install_intent_filters/Android.bp
+++ /dev/null
@@ -1,7 +0,0 @@
-android_test_helper_app {
-    name: "FrameworksCoreTests_install_intent_filters",
-    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/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java b/core/tests/coretests/src/android/accessibilityservice/AccessibilityShortcutInfoTest.java
index 82a7b2c..9f0af60 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(mPackageManager));
+    }
+
+    @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/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/com/android/internal/content/OverlayConfigIterationRule.java b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
index 23655a0..fbf75df 100644
--- a/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
+++ b/core/tests/coretests/src/com/android/internal/content/OverlayConfigIterationRule.java
@@ -21,11 +21,11 @@
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.when;
 
-import android.content.pm.parsing.AndroidPackage;
+import android.content.pm.parsing.ParsingPackageRead;
 import android.os.Build;
 import android.util.ArrayMap;
 
-import com.android.internal.content.om.OverlayConfig.AndroidPackageProvider;
+import com.android.internal.content.om.OverlayConfig.PackageProvider;
 import com.android.internal.content.om.OverlayScanner;
 import com.android.internal.content.om.OverlayScanner.ParsedOverlayInfo;
 
@@ -39,14 +39,14 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Map;
-import java.util.function.Consumer;
+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 AndroidPackageProvider} as if the system server is parsing configuration files.
+ * {@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.
@@ -60,7 +60,7 @@
 
     private final ArrayMap<File, ParsedOverlayInfo> mOverlayStubResults = new ArrayMap<>();
     private Supplier<OverlayScanner> mOverlayScanner;
-    private AndroidPackageProvider mAndroidPackageProvider;
+    private PackageProvider mPkgProvider;
     private Iteration mIteration;
 
     /**
@@ -96,9 +96,9 @@
         return mOverlayScanner;
     }
 
-    /** Retrieves the {@link AndroidPackageProvider} for the current run of the test. */
-    AndroidPackageProvider getPackageProvider() {
-        return mAndroidPackageProvider;
+    /** Retrieves the {@link PackageProvider} for the current run of the test. */
+    PackageProvider getPackageProvider() {
+        return mPkgProvider;
     }
 
     /** Retrieves the current iteration of the test. */
@@ -123,7 +123,7 @@
                     }
                     return scanner;
                 };
-                mAndroidPackageProvider = null;
+                mPkgProvider = null;
                 mIteration = Iteration.ZYGOTE;
                 base.evaluate();
 
@@ -131,14 +131,15 @@
                 // the system server is parsing the configuration files and using PackageManager to
                 // retrieving information of overlays.
                 mOverlayScanner = null;
-                mAndroidPackageProvider = Mockito.mock(AndroidPackageProvider.class);
+                mPkgProvider = Mockito.mock(PackageProvider.class);
                 mIteration = Iteration.SYSTEM_SERVER;
                 doAnswer((InvocationOnMock invocation) -> {
                     final Object[] args = invocation.getArguments();
-                    final Consumer<AndroidPackage> f =  (Consumer<AndroidPackage>) args[0];
+                    final BiConsumer<ParsingPackageRead, Boolean> f =
+                            (BiConsumer<ParsingPackageRead, Boolean>) args[0];
                     for (Map.Entry<File, ParsedOverlayInfo> overlay :
                             mOverlayStubResults.entrySet()) {
-                        final AndroidPackage a = Mockito.mock(AndroidPackage.class);
+                        final ParsingPackageRead a = Mockito.mock(ParsingPackageRead.class);
                         final ParsedOverlayInfo info = overlay.getValue();
                         when(a.getPackageName()).thenReturn(info.packageName);
                         when(a.getOverlayTarget()).thenReturn(info.targetPackageName);
@@ -146,12 +147,10 @@
                         when(a.isOverlayIsStatic()).thenReturn(info.isStatic);
                         when(a.getOverlayPriority()).thenReturn(info.priority);
                         when(a.getBaseCodePath()).thenReturn(info.path.getPath());
-                        when(a.isSystem()).thenReturn(
-                                !info.path.getPath().contains("data/overlay"));
-                        f.accept(a);
+                        f.accept(a, !info.path.getPath().contains("data/overlay"));
                     }
                     return null;
-                }).when(mAndroidPackageProvider).forEachPackage(any());
+                }).when(mPkgProvider).forEachPackage(any());
 
                 base.evaluate();
             }
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/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/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..25b7fc1 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>
 
diff --git a/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java b/packages/DynamicSystemInstallationService/src/com/android/dynsystem/DynamicSystemInstallationService.java
index 9bae223..7affe88 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);
@@ -463,7 +469,12 @@
 
             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/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 59881e7..2813640 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>
 
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/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/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/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/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/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/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/statusbar/notification/collection/NotificationRankingManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotificationRankingManagerTest.kt
index 8e330c6..45c51d4 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
@@ -42,6 +42,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 +53,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)
         )
@@ -146,39 +149,42 @@
 
     @Test
     fun testSort_importantPeople() {
+        whenever(sectionsManager.isFilteringEnabled()).thenReturn(true)
         val aN = Notification.Builder(mContext, "test")
                 .setStyle(Notification.MessagingStyle(""))
                 .build()
-        val aC = NotificationChannel("test", "", IMPORTANCE_DEFAULT)
-        aC.setConversationId("parent", "convo")
         val a = NotificationEntryBuilder()
                 .setImportance(IMPORTANCE_HIGH)
                 .setPkg("pkg")
                 .setOpPkg("pkg")
                 .setTag("tag")
                 .setNotification(aN)
-                .setChannel(aC)
+                .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 bC = NotificationChannel("test", "", IMPORTANCE_DEFAULT)
-        bC.setConversationId("parent", "convo")
-        bC.setImportantConversation(true)
         val b = NotificationEntryBuilder()
                 .setImportance(IMPORTANCE_HIGH)
                 .setPkg("pkg2")
                 .setOpPkg("pkg2")
                 .setTag("tag")
                 .setNotification(bN)
-                .setChannel(bC)
+                .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),
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/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/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/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
index 0b8658c..7e7441f 100644
--- a/services/api/lint-baseline.txt
+++ b/services/api/lint-baseline.txt
@@ -19,17 +19,3 @@
     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)}
-
-
-UserHandleName: com.android.permission.persistence.RuntimePermissionsPersistence#delete(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `delete`
-UserHandleName: com.android.permission.persistence.RuntimePermissionsPersistence#read(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `read`
-UserHandleName: com.android.permission.persistence.RuntimePermissionsPersistence#write(com.android.permission.persistence.RuntimePermissionsState, android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `write`
-UserHandleName: com.android.role.persistence.RolesPersistence#delete(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `delete`
-UserHandleName: com.android.role.persistence.RolesPersistence#read(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `read`
-UserHandleName: com.android.role.persistence.RolesPersistence#write(com.android.role.persistence.RolesState, android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `write`
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/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 76f6ef6..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;
@@ -586,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
@@ -625,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);
@@ -677,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);
@@ -763,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.
      */
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/IntentResolver.java b/services/core/java/com/android/server/IntentResolver.java
index 05820d2..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<>();
                     }
@@ -195,21 +197,22 @@
     }
 
     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;
         }
@@ -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 {
@@ -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/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/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..f2a8615 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,60 @@
         }
     }
 
-    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
+            mContentResolver.registerContentObserver(
+                    Settings.Global.getUriFor(Settings.Global.ADB_ENABLED),
+                    false, new AdbSettingsObserver());
+        } 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);
+
         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));
+            }
+            // TODO(joshuaduong): Add condition for WIFI transport
         }
     }
 
     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,10 +182,10 @@
 
     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 AdbService(Context context) {
@@ -204,8 +198,7 @@
             mDebuggingManager = new AdbDebuggingManager(context);
         }
 
-        mHandler = new AdbHandler(FgThread.get().getLooper());
-
+        initAdbState();
         LocalServices.addService(AdbManagerInternal.class, new AdbManagerInternalImpl());
     }
 
@@ -219,7 +212,7 @@
         // 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);
         } 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 +224,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 +281,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/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 9082807..6bf5aa3 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];
         }
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/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 40acfe1..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;
 
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 3138639..e484ca0 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -690,13 +690,14 @@
             // Prefer VPN profiles, if any exist.
             VpnProfile profile = getVpnProfilePrivileged(alwaysOnPackage, keyStore);
             if (profile != null) {
-                startVpnProfilePrivileged(profile, alwaysOnPackage);
+                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 permanantly fail, and is resiliant to temporary failures. It
+                // 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;
             }
@@ -818,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 {
@@ -1943,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,
@@ -2949,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;
 
@@ -2974,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:
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/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..d7cb192 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;
@@ -1812,16 +1812,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();
@@ -3972,13 +3970,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 +4547,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 +4618,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/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/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/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 a1250cb..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;
@@ -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 0dacadc..85810e3 100644
--- a/services/core/java/com/android/server/pm/ComponentResolver.java
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -22,12 +22,12 @@
 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;
@@ -37,15 +37,12 @@
 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.ParsedIntentInfo;
-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;
@@ -58,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;
@@ -191,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,
@@ -299,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;
                 }
@@ -329,7 +331,7 @@
                 return null;
             }
             return PackageInfoUtils.generateProviderInfo(pkg, p, flags,
-                    ps.readUserState(userId), userId);
+                    ps.readUserState(userId), userId, ps);
         }
     }
 
@@ -354,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;
                 }
@@ -415,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);
@@ -428,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);
         }
     }
 
@@ -459,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
@@ -472,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
@@ -486,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);
@@ -540,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());
@@ -575,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) {
@@ -606,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++) {
@@ -671,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);
                     }
                 }
@@ -736,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
@@ -748,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
@@ -773,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();
@@ -793,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;
                 }
             }
@@ -821,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);
@@ -858,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;
@@ -871,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
@@ -884,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);
@@ -898,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);
@@ -928,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();
@@ -939,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);
@@ -957,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);
@@ -974,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);
@@ -993,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);
@@ -1011,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);
@@ -1146,31 +1127,34 @@
         }
     }
 
-    private abstract static class MimeGroupsAwareIntentResolver<F extends ParsedIntentInfo, R>
+    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, f.mimeGroupsIterator(), mMimeGroupToFilter,
+                register_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
                         "      MimeGroup: ");
             }
         }
 
         @Override
         protected void removeFilterInternal(F f) {
+            IntentFilter intentFilter = getIntentFilter(f);
             if (!mIsUpdatingMimeGroup) {
-                unregister_intent_filter(f, f.mimeGroupsIterator(), mMimeGroupToFilter,
+                unregister_intent_filter(f, intentFilter.mimeGroupsIterator(), mMimeGroupToFilter,
                         "      MimeGroup: ");
             }
 
             super.removeFilterInternal(f);
-            f.clearDynamicDataTypes();
+            intentFilter.clearDynamicDataTypes();
         }
 
         /**
@@ -1197,10 +1181,11 @@
             return hasChanges;
         }
 
-        private boolean updateFilter(F filter) {
+        private boolean updateFilter(F f) {
+            IntentFilter filter = getIntentFilter(f);
             List<String> oldTypes = filter.dataTypes();
-            removeFilter(filter);
-            addFilter(filter);
+            removeFilter(f);
+            addFilter(f);
             List<String> newTypes = filter.dataTypes();
             return !equalLists(oldTypes, newTypes);
         }
@@ -1221,12 +1206,12 @@
             return first.equals(second);
         }
 
-        private void applyMimeGroups(F filter) {
-            String packageName = filter.getPackageName();
+        private void applyMimeGroups(F f) {
+            IntentFilter filter = getIntentFilter(f);
 
             for (int i = filter.countMimeGroups() - 1; i >= 0; i--) {
-                List<String> mimeTypes = sPackageManagerInternal.getMimeGroup(packageName,
-                        filter.getMimeGroup(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);
@@ -1244,7 +1229,7 @@
     }
 
     private static class ActivityIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedActivityIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedActivity, ParsedIntentInfo>, ResolveInfo> {
 
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
@@ -1277,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);
                 }
             }
@@ -1293,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:");
@@ -1317,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;
                 }
             }
@@ -1354,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: "
@@ -1396,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);
@@ -1405,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="
@@ -1435,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);
@@ -1443,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,
@@ -1502,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;
@@ -1527,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();
         }
@@ -1585,7 +1539,7 @@
     }
 
     private static final class ProviderIntentResolver
-            extends MimeGroupsAwareIntentResolver<ParsedProviderIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedProvider, ParsedIntentInfo>, ResolveInfo> {
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                 boolean defaultOnly, int userId) {
@@ -1617,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);
                 }
             }
@@ -1640,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), "      ");
@@ -1658,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;
                 }
             }
@@ -1696,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;
             }
 
@@ -1757,7 +1684,7 @@
             }
 
             PackageSetting ps = (PackageSetting) sPackageManagerInternal.getPackageSetting(
-                    filter.getPackageName());
+                    provider.getPackageName());
             if (ps == null) {
                 return null;
             }
@@ -1779,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;
             }
@@ -1790,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;
         }
@@ -1807,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);
@@ -1846,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 MimeGroupsAwareIntentResolver<ParsedServiceIntentInfo, ResolveInfo> {
+            extends MimeGroupsAwareIntentResolver<Pair<ParsedService, ParsedIntentInfo>, ResolveInfo> {
         @Override
         public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
                 boolean defaultOnly, int userId) {
@@ -1877,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);
                 }
             }
@@ -1895,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), "      ");
@@ -1911,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;
                 }
             }
@@ -1948,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;
             }
 
@@ -2005,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;
             }
@@ -2038,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;
         }
@@ -2055,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();
@@ -2081,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;
@@ -2183,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;
         }
     }
@@ -2195,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();
         }
     }
@@ -2203,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();
         }
     }
@@ -2211,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();
         }
     }
@@ -2219,7 +2154,7 @@
     /** 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();
         }
     }
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/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 09e3feb..261caba 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -50,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;
@@ -75,6 +74,7 @@
 import com.android.internal.util.ArrayUtils;
 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;
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 2a3f7ed..a464ca7 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -209,20 +209,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;
@@ -341,6 +338,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;
@@ -1011,13 +1015,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<>();
@@ -1080,7 +1084,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;
 
@@ -1141,7 +1145,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<>();
@@ -1166,11 +1170,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) {
@@ -1222,14 +1226,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()
@@ -1342,7 +1346,7 @@
 
         @Override
         public boolean addOneIntentFilterVerification(int verifierUid, int userId, int verificationId,
-                ParsedActivityIntentInfo filter, String packageName) {
+                ParsedIntentInfo filter, String packageName) {
             if (!hasValidDomains(filter)) {
                 return false;
             }
@@ -1371,7 +1375,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));
@@ -2033,7 +2037,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.
@@ -2083,7 +2087,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);
 
@@ -2147,7 +2151,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) {
@@ -2159,14 +2163,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(
@@ -2499,15 +2503,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) {
@@ -2517,10 +2524,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);
                         }
                     }
@@ -2859,12 +2866,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
@@ -2902,7 +2905,9 @@
 
             // Parse overlay configuration files to set default enable state, mutability, and
             // priority of system overlays.
-            mOverlayConfig = OverlayConfig.initializeSystemInstance(mPmInternal::forEachPackage);
+            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<>();
@@ -3044,7 +3049,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: "
@@ -3149,7 +3154,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
@@ -3177,7 +3182,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,
@@ -3476,7 +3481,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) {
@@ -3487,7 +3493,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);
@@ -4010,15 +4016,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());
                         }
                     }
                 }
@@ -4146,7 +4150,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;
@@ -4208,7 +4212,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!");
             }
         }
@@ -4289,7 +4293,7 @@
             }
 
             AndroidPackage p = mPackages.get(packageName);
-            if (matchFactoryOnly && p != null && !isSystemApp(p)) {
+            if (matchFactoryOnly && p != null && !p.isSystem()) {
                 return null;
             }
             if (DEBUG_PACKAGE_INFO)
@@ -4344,9 +4348,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);
@@ -4354,20 +4358,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);
         }
@@ -4574,7 +4576,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;
@@ -4604,7 +4606,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;
@@ -4656,7 +4658,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);
             }
@@ -4708,7 +4710,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);
                 }
@@ -5092,7 +5094,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(
@@ -5140,8 +5142,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;
                 }
@@ -5179,7 +5181,7 @@
                     return null;
                 }
                 return PackageInfoUtils.generateActivityInfo(pkg,
-                        a, flags, ps.readUserState(userId), userId);
+                        a, flags, ps.readUserState(userId), userId, ps);
             }
         }
         return null;
@@ -5400,7 +5402,7 @@
                     return null;
                 }
                 return PackageInfoUtils.generateServiceInfo(pkg,
-                        s, flags, ps.readUserState(userId), userId);
+                        s, flags, ps.readUserState(userId), userId, ps);
             }
         }
         return null;
@@ -5434,7 +5436,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;
@@ -8272,7 +8274,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);
                         }
@@ -8298,7 +8300,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);
@@ -8451,13 +8453,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);
                         }
@@ -8563,7 +8565,7 @@
                 return null;
             }
             final ParsedInstrumentation i = mInstrumentation.get(component);
-            return PackageInfoUtils.generateInstrumentationInfo(i, pkg, flags);
+            return PackageInfoUtils.generateInstrumentationInfo(i, pkg, flags, callingUserId, ps);
         }
     }
 
@@ -8576,11 +8578,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
@@ -8590,10 +8593,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);
                         }
@@ -8606,7 +8611,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);
@@ -8616,7 +8621,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);
@@ -8720,7 +8725,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 {
@@ -8774,16 +8780,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 {
@@ -8869,18 +8872,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);
@@ -8933,8 +8924,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) {
@@ -9068,7 +9059,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;
@@ -9208,9 +9199,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();
@@ -9255,7 +9252,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));
@@ -9409,16 +9406,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) {
@@ -9426,7 +9423,7 @@
                 + loadingPackageName + ", user=" + userId);
             return;
         }
-        mDexManager.notifyDexLoad(ai, classLoaderNames, classPaths, loaderIsa, userId);
+        mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId);
     }
 
     @Override
@@ -9541,19 +9538,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);
@@ -9573,7 +9572,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.
@@ -9588,9 +9587,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(),
@@ -9598,12 +9598,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);
@@ -9612,7 +9614,8 @@
                 }
             }
         }
-        return pdo.performDexOpt(p, instructionSets,
+
+        return pdo.performDexOpt(p, pkgSetting, instructionSets,
                 getOrCreateCompilerPackageStats(p),
                 mDexManager.getPackageUseInfoOrDefault(p.getPackageName()), options);
     }
@@ -9655,11 +9658,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;
@@ -9682,15 +9685,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);
                     }
                 }
             }
@@ -9762,7 +9766,7 @@
     }
 
     public void shutdown() {
-        mPackageUsage.writeNow(mPackages);
+        mPackageUsage.writeNow(mSettings.mPackages);
         mCompilerStats.writeNow();
         mDexManager.writePackageDexUsageNow();
         PackageWatchdog.getInstance(mContext).writeNow();
@@ -9808,9 +9812,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);
             }
         }
@@ -9820,8 +9826,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));
@@ -9957,7 +9962,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());
@@ -9978,40 +9983,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,
@@ -10026,18 +10035,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);
@@ -10046,25 +10055,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());
         }
     }
 
@@ -10180,27 +10191,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) {
@@ -10214,19 +10230,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,
@@ -10242,10 +10259,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);
         }
@@ -10320,6 +10338,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,
@@ -10331,7 +10352,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;
@@ -10344,6 +10366,7 @@
             this.scanFlags = scanFlags;
             this.isPlatformPackage = isPlatformPackage;
             this.user = user;
+            this.cpuAbiOverride = cpuAbiOverride;
         }
     }
 
@@ -10451,7 +10474,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());
@@ -10472,7 +10495,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;
@@ -10492,7 +10521,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);
         }
     }
@@ -10594,7 +10624,8 @@
         }
 
         if (reconciledPkg.collectedSharedLibraryInfos != null) {
-            executeSharedLibrariesUpdateLPr(pkg, null, reconciledPkg.collectedSharedLibraryInfos);
+            executeSharedLibrariesUpdateLPr(pkg, pkgSetting, null, null,
+                    reconciledPkg.collectedSharedLibraryInfos);
         }
 
         final KeySetManagerService ksms = mSettings.mKeySetManagerService;
@@ -10607,7 +10638,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--) {
@@ -10661,8 +10692,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);
     }
 
     /**
@@ -10714,8 +10744,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;
         }
@@ -10744,19 +10773,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);
                 }
             }
         }
@@ -10766,6 +10797,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()
@@ -10776,7 +10809,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);
             }
@@ -10784,7 +10817,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);
             }
@@ -10792,7 +10825,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);
             }
@@ -10800,7 +10833,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);
             }
@@ -10848,8 +10881,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.
@@ -10878,10 +10911,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;
@@ -10890,16 +10926,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.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.
             //
@@ -10908,8 +10946,10 @@
             // 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(),
                     parsedPackage.getMimeGroups());
@@ -10938,35 +10978,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);
@@ -10975,14 +11008,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);
                 }
@@ -10994,13 +11029,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 {
@@ -11017,7 +11055,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);
         }
 
@@ -11035,20 +11074,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="
@@ -11061,8 +11096,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) {
@@ -11104,13 +11139,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" : "")
@@ -11122,14 +11157,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));
             }
         }
 
@@ -11167,7 +11203,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");
@@ -11193,7 +11229,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
@@ -11202,7 +11239,7 @@
                 parsedPackage.setAllComponentsDirectBootAware(true);
             }
             if (compressedFileExists(parsedPackage.getCodePath())) {
-                parsedPackage.setIsStub(true);
+                parsedPackage.setStub(true);
             }
         } else {
             parsedPackage
@@ -11237,14 +11274,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)
@@ -11255,19 +11292,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");
@@ -11291,8 +11328,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");
@@ -11375,49 +11411,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");
                 }
@@ -11479,12 +11515,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.");
                         }
@@ -11506,8 +11541,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,
@@ -11761,14 +11796,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);
                 }
             }
         }
@@ -11793,7 +11830,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");
             }
         }
@@ -11807,7 +11844,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);
             }
@@ -11855,7 +11892,7 @@
                 if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Instrumentation: " + r);
             }
 
-            if (pkg.getProtectedBroadcasts() != null) {
+            if (!pkg.getProtectedBroadcasts().isEmpty()) {
                 synchronized (mProtectedBroadcasts) {
                     mProtectedBroadcasts.addAll(pkg.getProtectedBroadcasts());
                 }
@@ -11887,8 +11924,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;
@@ -12006,21 +12043,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);
                     }
                 }
             }
@@ -12431,18 +12466,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);
         }
     }
 
@@ -13464,15 +13493,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);
                 }
             };
@@ -13657,9 +13686,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
@@ -13727,7 +13755,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.");
@@ -13755,8 +13783,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;
 
@@ -13780,6 +13807,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);
@@ -13815,7 +13843,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]) {
@@ -14200,7 +14228,7 @@
 
                 if (dataOwnerPkg != null) {
                     if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
-                            dataOwnerPkg.getFlags())) {
+                            dataOwnerPkg.isDebuggable())) {
                         try {
                             checkDowngrade(dataOwnerPkg, pkgLite);
                         } catch (PackageManagerException e) {
@@ -14213,7 +14241,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
@@ -14224,7 +14252,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;
@@ -15000,14 +15028,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;
         }
 
@@ -15117,14 +15137,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;
         }
 
@@ -15320,7 +15332,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);
                     }
@@ -15349,8 +15361,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
@@ -15822,13 +15834,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
@@ -15925,10 +15937,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;
                     }
@@ -15947,14 +15962,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);
                     }
 
@@ -16061,7 +16076,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,
@@ -16194,7 +16209,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) {
@@ -16214,7 +16229,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),
@@ -16331,16 +16346,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 {
@@ -16375,16 +16388,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");
             }
@@ -16396,7 +16401,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);
@@ -16418,8 +16424,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
@@ -16454,7 +16459,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. "
@@ -16509,7 +16514,7 @@
                 }
 
                 if (ps.pkg != null) {
-                    systemApp = (ps.pkg.getFlags() & ApplicationInfo.FLAG_SYSTEM) != 0;
+                    systemApp = ps.pkg.isSystem();
                 }
                 res.origUsers = ps.queryInstalledUsers(mUserManager.getUserIds(), true);
             }
@@ -16521,12 +16526,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
@@ -16587,14 +16592,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());
                             }
                         }
                     }
@@ -16637,12 +16642,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) {
@@ -16817,14 +16832,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
@@ -16839,7 +16854,7 @@
                                 + ", old=" + oldPackage);
                     }
                     res.setReturnCode(PackageManager.INSTALL_SUCCEEDED);
-                    parsedPackage.setUpdatedSystemApp(true);
+                    ps.getPkgState().setUpdatedSystemApp(true);
                     targetParseFlags = systemParseFlags;
                     targetScanFlags = systemScanFlags;
                 } else { // non system replace
@@ -17006,7 +17021,7 @@
         Message msg = mHandler.obtainMessage(START_INTENT_FILTER_VERIFICATIONS);
         msg.obj = new IFVerificationParams(
                 pkg.getPackageName(),
-                hasDomainURLs(pkg),
+                pkg.isHasDomainUrls(),
                 pkg.getActivities(),
                 replacing,
                 userId,
@@ -17058,11 +17073,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");
@@ -17082,8 +17098,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(
@@ -17118,9 +17135,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) {
@@ -17139,47 +17154,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;
     }
@@ -17189,7 +17167,7 @@
     }
 
     private VersionInfo getSettingsVersionForPackage(AndroidPackage pkg) {
-        if (isExternal(pkg)) {
+        if (pkg.isExternalStorage()) {
             if (TextUtils.isEmpty(pkg.getVolumeUuid())) {
                 return mSettings.getExternalVersion();
             } else {
@@ -17649,10 +17627,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");
                     }
@@ -17663,7 +17642,7 @@
                         Slog.i(TAG, "Enabling system stub after removal; pkg: "
                                 + stubPkg.getPackageName());
                     }
-                    enableCompressedPackage(stubPkg);
+                    enableCompressedPackage(stubPkg, stubPs);
                 }
             }
         }
@@ -18046,9 +18025,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());
         }
@@ -18479,10 +18461,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;
                 }
@@ -18509,7 +18492,7 @@
         } else {
             flags = 0;
         }
-        prepareAppDataContentsLIF(pkg, userId, flags);
+        prepareAppDataContentsLIF(pkg, ps, userId, flags);
 
         return true;
     }
@@ -19966,7 +19949,7 @@
             if (isSystemStub
                     && (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
                             || newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
-                if (!enableCompressedPackage(deletedPkg)) {
+                if (!enableCompressedPackage(deletedPkg, pkgSetting)) {
                     return;
                 }
             }
@@ -19983,7 +19966,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) {
@@ -21216,24 +21199,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();
         }
     }
@@ -21339,7 +21325,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,
@@ -21803,16 +21789,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);
@@ -21857,18 +21844,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();
 
@@ -21876,7 +21865,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,
@@ -22065,7 +22055,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");
             }
@@ -22091,7 +22081,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");
             }
@@ -22101,12 +22091,12 @@
                         "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");
@@ -22281,15 +22271,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,
@@ -23013,7 +23003,7 @@
         }
 
         @Override
-        public Object getDisabledSystemPackage(@NonNull String packageName) {
+        public PackageSetting getDisabledSystemPackage(@NonNull String packageName) {
             synchronized (mLock) {
                 return mSettings.getDisabledSystemPkgLPr(packageName);
             }
@@ -23363,7 +23353,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);
@@ -23455,11 +23445,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();
             }
         }
 
@@ -23690,6 +23676,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);
@@ -24185,15 +24180,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());
@@ -24208,13 +24206,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) {
@@ -24241,8 +24242,8 @@
                 if (PackageManagerServiceUtils
                         .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis,
                                 downgradeTimeThresholdMillis, packageUseInfo,
-                                pkg.getLatestPackageUseTimeInMills(),
-                                pkg.getLatestForegroundPackageUseTimeInMills())) {
+                                ps.getPkgState().getLatestPackageUseTimeInMills(),
+                                ps.getPkgState().getLatestForegroundPackageUseTimeInMills())) {
                     unusedPackages.add(pkg.getPackageName());
                 }
             }
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 d83e6f4..2bd1a26 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -16,18 +16,19 @@
 
 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;
@@ -39,8 +40,7 @@
 /**
  * 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;
@@ -65,6 +65,9 @@
     @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,
@@ -223,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;
@@ -324,9 +323,8 @@
         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 60c8b94..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;
@@ -479,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
@@ -506,10 +511,7 @@
             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,
@@ -2673,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.
@@ -2712,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]);
@@ -3154,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);
                 }
             }
         }
@@ -4129,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) {
@@ -4140,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();
             }
         }
@@ -4281,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;
@@ -4596,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;
@@ -4669,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("    ");
@@ -4689,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("    ");
@@ -4699,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);
                         }
                     }
                 }
@@ -4751,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++) {
@@ -4762,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();
@@ -5403,7 +5407,7 @@
                         packagePermissions, sharedUserPermissions);
             }
 
-            mPersistence.write(runtimePermissions, UserHandle.of(userId));
+            mPersistence.writeAsUser(runtimePermissions, UserHandle.of(userId));
         }
 
         @NonNull
@@ -5457,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/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/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/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 ec8e1a0..139c844 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -39,7 +39,6 @@
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.PackageListObserver;
 import android.content.pm.PermissionInfo;
-import android.content.pm.parsing.AndroidPackage;
 import android.os.Build;
 import android.os.Process;
 import android.os.RemoteException;
@@ -65,6 +64,7 @@
 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;
 
@@ -163,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);
@@ -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;
@@ -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,7 +613,7 @@
             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;
@@ -639,19 +641,23 @@
          * @param pkgName The package to add for later processing.
          */
         void addPackage(@NonNull String pkgName) {
-            final PackageInfo pkg;
+            PackageManagerInternal pmInternal =
+                    LocalServices.getService(PackageManagerInternal.class);
+            final PackageInfo pkgInfo;
+            final AndroidPackage pkg;
             try {
-                pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
+                pkgInfo = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
+                pkg = pmInternal.getPackage(pkgName);
             } catch (NameNotFoundException e) {
                 return;
             }
 
-            if (pkg.requestedPermissions == null) {
+            if (pkgInfo == null || pkg == null || pkgInfo.requestedPermissions == null) {
                 return;
             }
 
-            for (String permission : pkg.requestedPermissions) {
-                addAppOps(pkg, permission);
+            for (String permission : pkgInfo.requestedPermissions) {
+                addAppOps(pkgInfo, pkg, permission);
             }
         }
 
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/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/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index b239b684..421bfa4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -180,7 +180,6 @@
 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;
@@ -290,6 +289,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;
@@ -448,7 +448,7 @@
      *  System property whose value is either "true" or "false", indicating whether
      *  device owner is present.
      */
-    private static final String PROPERTY_DEVICE_OWNER_PRESENT = "ro.device_owner";
+    private static final String PROPERTY_DEVICE_OWNER_PRESENT = "ro.organization_owned";
 
     private static final int STATUS_BAR_DISABLE_MASK =
             StatusBarManager.DISABLE_EXPAND |
@@ -2754,11 +2754,11 @@
         }
 
         if (!mInjector.systemPropertiesGet(PROPERTY_DEVICE_OWNER_PRESENT, "").isEmpty()) {
-            Slog.w(LOG_TAG, "Trying to set ro.device_owner, but it has already been set?");
+            Slog.w(LOG_TAG, "Trying to set ro.organization_owned, 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);
+            Slog.i(LOG_TAG, "Set ro.organization_owned property to " + value);
         }
     }
 
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/ConversationStore.java b/services/people/java/com/android/server/people/data/ConversationStore.java
index 3afb209..62e9da8 100644
--- a/services/people/java/com/android/server/people/data/ConversationStore.java
+++ b/services/people/java/com/android/server/people/data/ConversationStore.java
@@ -23,7 +23,6 @@
 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 +49,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<>();
@@ -92,7 +89,7 @@
      */
     @MainThread
     void loadConversationsFromDisk() {
-        mScheduledExecutorService.submit(() -> {
+        mScheduledExecutorService.execute(() -> {
             synchronized (this) {
                 ConversationInfosProtoDiskReadWriter conversationInfosProtoDiskReadWriter =
                         getConversationInfosProtoDiskReadWriter();
@@ -194,6 +191,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,8 +245,7 @@
         }
         if (mConversationInfosProtoDiskReadWriter == null) {
             mConversationInfosProtoDiskReadWriter = new ConversationInfosProtoDiskReadWriter(
-                    mPackageDir, CONVERSATIONS_FILE_NAME, DISK_WRITE_DELAY,
-                    mScheduledExecutorService);
+                    mPackageDir, CONVERSATIONS_FILE_NAME, mScheduledExecutorService);
         }
         return mConversationInfosProtoDiskReadWriter;
     }
@@ -264,16 +269,16 @@
         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 +333,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 6b97c98..7eb2176 100644
--- a/services/people/java/com/android/server/people/data/DataManager.java
+++ b/services/people/java/com/android/server/people/data/DataManager.java
@@ -319,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);
             }
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..d47e2cc 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;
@@ -63,22 +65,50 @@
         mUserId = userId;
 
         mPackageDataDir = new File(perUserPeopleDataDir, mPackageName);
+        mPackageDataDir.mkdirs();
+
         mConversationStore = new ConversationStore(mPackageDataDir, scheduledExecutorService,
                 helper);
-        mEventStore = new EventStore();
+        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,
+            @NonNull ContactsQueryHelper helper) {
+        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, helper);
+            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 +252,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..d3cecce 100644
--- a/services/people/java/com/android/server/people/data/UserData.java
+++ b/services/people/java/com/android/server/people/data/UserData.java
@@ -73,9 +73,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, mHelper));
     }
 
     void setUserStopped() {
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/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/core/tests/coretests/apks/install_intent_filters/AndroidManifest.xml b/services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml
similarity index 87%
rename from core/tests/coretests/apks/install_intent_filters/AndroidManifest.xml
rename to services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml
index d7ee76e..fc7134d2 100644
--- a/core/tests/coretests/apks/install_intent_filters/AndroidManifest.xml
+++ b/services/tests/servicestests/apks/install_intent_filters/AndroidManifest.xml
@@ -16,7 +16,7 @@
   -->
 <manifest
     xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.frameworks.coretests.install_intent_filters">
+    package="com.android.frameworks.servicestests.install_intent_filters">
 
 <!--
      This manifest declares an activity for testing intent filters.
@@ -24,7 +24,7 @@
 -->
 
     <uses-feature
-        android:name="com.android.frameworks.coretests.nonexistent" />
+        android:name="com.android.frameworks.servicestests.nonexistent" />
     <uses-configuration
         android:reqFiveWayNav="false" />
 
@@ -41,7 +41,7 @@
     <application
         android:hasCode="true">
         <activity
-            android:name="com.android.frameworks.coretests.TestActivity">
+            android:name="com.android.frameworks.servicestests.TestActivity">
             <intent-filter>
                 <action android:name="action1"/>
                 <data android:mimeGroup="mime_group_1"/>
diff --git a/core/tests/coretests/apks/install_intent_filters/src/com/android/frameworks/coretests/TestActivity.java b/services/tests/servicestests/apks/install_intent_filters/src/com/android/frameworks/servicestests/TestActivity.java
similarity index 100%
rename from core/tests/coretests/apks/install_intent_filters/src/com/android/frameworks/coretests/TestActivity.java
rename to services/tests/servicestests/apks/install_intent_filters/src/com/android/frameworks/servicestests/TestActivity.java
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/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/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/DataManagerTest.java b/services/tests/servicestests/src/com/android/server/people/data/DataManagerTest.java
index 5e104a5..f73a4b5 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
@@ -56,7 +56,6 @@
 import android.content.pm.ShortcutInfo;
 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;
@@ -73,6 +72,7 @@
 import com.android.internal.app.ChooserActivity;
 import com.android.internal.content.PackageMonitor;
 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/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/UsageStatsQueryHelperTest.java b/services/tests/servicestests/src/com/android/server/people/data/UsageStatsQueryHelperTest.java
index d444466..418067f 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;
@@ -233,7 +236,7 @@
     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,
@@ -244,6 +247,7 @@
                     scheduledExecutorService, rootDir, helper);
             mConversationStore = new TestConversationStore(rootDir, scheduledExecutorService,
                     helper);
+            mEventStore = new TestEventStore(rootDir, scheduledExecutorService);
         }
 
         @Override
@@ -261,8 +265,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 +307,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/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/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 841cea2..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,11 @@
 
 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;
 
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/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 91%
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 46e992e..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,21 +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.util.Log;
+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;
@@ -47,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";
@@ -87,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.
@@ -339,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();
@@ -350,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());
     }
 
     /**
@@ -406,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(
@@ -426,7 +445,7 @@
 
         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(),
@@ -448,7 +467,7 @@
         // 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(
+            if (p.getActivities().get(i).getClassName().equals(
                     PackageManager.APP_DETAILS_ACTIVITY_CLASS_NAME)) {
                 foundAppDetailsActivity = true;
                 p.getActivities().remove(i);
@@ -466,7 +485,7 @@
     @Test
     public void testPackageWithIntentFilters_cached() throws Exception {
         checkPackageWithIntentFilters(p ->
-                PackageParser.fromCacheEntryStatic(PackageParser.toCacheEntryStatic(p)));
+                PackageCacher.fromCacheEntryStatic(PackageCacher.toCacheEntryStatic(p)));
     }
 
     private void checkPackageWithIntentFilters(
@@ -474,20 +493,19 @@
         ParsedPackage p = parsePackage(
                 "install_intent_filters.apk", R.raw.install_intent_filters,
                 converter);
-        String packageName = "com.android.frameworks.coretests.install_intent_filters";
+        String packageName = "com.android.frameworks.servicestests.install_intent_filters";
 
         assertEquals(packageName, p.getPackageName());
 
         findAndRemoveAppDetailsActivity(p);
 
-        Log.e("ParserTest", "" + p.getActivities());
         assertEquals("Expected exactly one activity", 1, p.getActivities().size());
         assertEquals("Expected exactly one intent filter",
-                1, p.getActivities().get(0).intents.size());
+                1, p.getActivities().get(0).getIntents().size());
         assertEquals("Expected exactly one mime group in intent filter",
-                1, p.getActivities().get(0).intents.get(0).countMimeGroups());
+                1, p.getActivities().get(0).getIntents().get(0).countMimeGroups());
         assertTrue("Did not find expected mime group 'mime_group_1'",
-                p.getActivities().get(0).intents.get(0).hasMimeGroup("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/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/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/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..3564add
--- 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:
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 9924839c..846f025 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -838,7 +838,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 =
@@ -1987,6 +1988,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>
@@ -2016,10 +2024,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
@@ -2967,6 +2980,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
@@ -3038,11 +3078,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
@@ -3505,6 +3540,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);
@@ -3801,7 +3837,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);
@@ -3932,6 +3968,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);
@@ -3950,8 +3991,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);
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/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/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/connectivity/VpnTest.java b/tests/net/java/com/android/server/connectivity/VpnTest.java
index 0e3b797..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;
@@ -84,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;
@@ -93,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;
@@ -125,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:
@@ -151,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));
@@ -962,6 +989,26 @@
         // 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.
      */
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index af2f246..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;
@@ -4920,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 {
@@ -4948,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();