Merge changes from topic "MarkAPKInUpdateApexAsUpdatedSystemApp" into rvc-dev

* changes:
  Do not verify APKs out of updated APEXs
  Caches parsed package info for APEX
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java
index c37ea8b..c97f33b 100644
--- a/services/core/java/com/android/server/pm/ApexManager.java
+++ b/services/core/java/com/android/server/pm/ApexManager.java
@@ -16,22 +16,22 @@
 
 package com.android.server.pm;
 
+import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+
 import android.annotation.IntDef;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.apex.ApexInfo;
 import android.apex.ApexInfoList;
 import android.apex.ApexSessionInfo;
 import android.apex.ApexSessionParams;
 import android.apex.IApexService;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInstaller;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
+import android.content.pm.parsing.PackageInfoWithoutStateUtils;
 import android.os.Environment;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -44,8 +44,9 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
+import com.android.internal.util.Preconditions;
+import com.android.server.pm.parsing.PackageParser2;
 import com.android.server.pm.parsing.pkg.AndroidPackage;
 import com.android.server.utils.TimingsTraceAndSlog;
 
@@ -61,7 +62,9 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.concurrent.ExecutorService;
 import java.util.stream.Collectors;
 
 /**
@@ -72,7 +75,7 @@
 
     private static final String TAG = "ApexManager";
 
-    static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
+    public static final int MATCH_ACTIVE_PACKAGE = 1 << 0;
     static final int MATCH_FACTORY_PACKAGE = 1 << 1;
 
     private static final Singleton<ApexManager> sApexManagerSingleton =
@@ -139,7 +142,14 @@
      */
     public abstract List<ActiveApexInfo> getActiveApexInfos();
 
-    abstract void systemReady(Context context);
+    /**
+     * Called by package manager service to scan apex package files when device boots up.
+     *
+     * @param packageParser The package parser which supports caches.
+     * @param executorService An executor to support parallel package parsing.
+     */
+    abstract void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
+            @NonNull ExecutorService executorService);
 
     /**
      * Retrieves information about an APEX package.
@@ -154,7 +164,7 @@
      *         is not found.
      */
     @Nullable
-    abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
+    public abstract PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags);
 
     /**
      * Retrieves information about all active APEX packages.
@@ -189,6 +199,27 @@
     abstract boolean isApexPackage(String packageName);
 
     /**
+     * Whether the APEX package is pre-installed or not.
+     *
+     * @param packageInfo the package to check
+     * @return {@code true} if this package is pre-installed, {@code false} otherwise.
+     */
+    public static boolean isFactory(@NonNull PackageInfo packageInfo) {
+        return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
+    }
+
+    /**
+     * Returns the active apex package's name that contains the (apk) package.
+     *
+     * @param containedPackage The (apk) package that might be in a apex
+     * @return the apex package's name of {@code null} if the {@code containedPackage} is not inside
+     *         any apex.
+     */
+    @Nullable
+    public abstract String getActiveApexPackageNameContainingPackage(
+            @NonNull AndroidPackage containedPackage);
+
+    /**
      * Retrieves information about an apexd staged session i.e. the internal state used by apexd to
      * track the different states of a session.
      *
@@ -342,7 +373,7 @@
          * difference between {@code packageName} and {@code apexModuleName}.
          */
         @GuardedBy("mLock")
-        private Map<String, List<String>> mApksInApex = new ArrayMap<>();
+        private ArrayMap<String, List<String>> mApksInApex = new ArrayMap<>();
 
         @GuardedBy("mLock")
         private List<PackageInfo> mAllPackagesCache;
@@ -357,7 +388,7 @@
          * the apk container to {@code apexModuleName} of the apex-payload inside.
          */
         @GuardedBy("mLock")
-        private Map<String, String> mPackageNameToApexModuleName;
+        private ArrayMap<String, String> mPackageNameToApexModuleName;
 
         ApexManagerImpl(IApexService apexService) {
             mApexService = apexService;
@@ -373,16 +404,6 @@
             return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_INSTALLED) != 0;
         }
 
-        /**
-         * Whether the APEX package is pre-installed or not.
-         *
-         * @param packageInfo the package to check
-         * @return {@code true} if this package is pre-installed, {@code false} otherwise.
-         */
-        private static boolean isFactory(PackageInfo packageInfo) {
-            return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
-        }
-
         @Override
         public List<ActiveApexInfo> getActiveApexInfos() {
             final TimingsTraceAndSlog t = new TimingsTraceAndSlog(TAG + "Timing",
@@ -411,104 +432,94 @@
         }
 
         @Override
-        void systemReady(Context context) {
-            context.registerReceiver(new BroadcastReceiver() {
-                @Override
-                public void onReceive(Context context, Intent intent) {
-                    // Post populateAllPackagesCacheIfNeeded to a background thread, since it's
-                    // expensive to run it in broadcast handler thread.
-                    BackgroundThread.getHandler().post(() -> populateAllPackagesCacheIfNeeded());
-                    context.unregisterReceiver(this);
+        void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
+                @NonNull ExecutorService executorService) {
+            Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanApexPackagesTraced");
+            try {
+                synchronized (mLock) {
+                    scanApexPackagesInternalLocked(packageParser, executorService);
                 }
-            }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
-        }
-
-        private void populatePackageNameToApexModuleNameIfNeeded() {
-            synchronized (mLock) {
-                if (mPackageNameToApexModuleName != null) {
-                    return;
-                }
-                try {
-                    mPackageNameToApexModuleName = new ArrayMap<>();
-                    final ApexInfo[] allPkgs = mApexService.getAllPackages();
-                    for (int i = 0; i < allPkgs.length; i++) {
-                        ApexInfo ai = allPkgs[i];
-                        PackageParser.PackageLite pkgLite;
-                        try {
-                            File apexFile = new File(ai.modulePath);
-                            pkgLite = PackageParser.parsePackageLite(apexFile, 0);
-                        } catch (PackageParser.PackageParserException pe) {
-                            throw new IllegalStateException("Unable to parse: "
-                                    + ai.modulePath, pe);
-                        }
-                        mPackageNameToApexModuleName.put(pkgLite.packageName, ai.moduleName);
-                    }
-                } catch (RemoteException re) {
-                    Slog.e(TAG, "Unable to retrieve packages from apexservice: ", re);
-                    throw new RuntimeException(re);
-                }
+            } finally {
+                Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
             }
         }
 
-        private void populateAllPackagesCacheIfNeeded() {
-            synchronized (mLock) {
-                if (mAllPackagesCache != null) {
-                    return;
-                }
-                try {
-                    mAllPackagesCache = new ArrayList<>();
-                    HashSet<String> activePackagesSet = new HashSet<>();
-                    HashSet<String> factoryPackagesSet = new HashSet<>();
-                    final ApexInfo[] allPkgs = mApexService.getAllPackages();
-                    for (ApexInfo ai : allPkgs) {
-                        // If the device is using flattened APEX, don't report any APEX
-                        // packages since they won't be managed or updated by PackageManager.
-                        if ((new File(ai.modulePath)).isDirectory()) {
-                            break;
-                        }
-                        int flags = PackageManager.GET_META_DATA
-                                | PackageManager.GET_SIGNING_CERTIFICATES
-                                | PackageManager.GET_SIGNATURES;
-                        PackageParser.Package pkg;
-                        try {
-                            File apexFile = new File(ai.modulePath);
-                            PackageParser pp = new PackageParser();
-                            pkg = pp.parsePackage(apexFile, flags, false);
-                            PackageParser.collectCertificates(pkg, false);
-                        } catch (PackageParser.PackageParserException pe) {
-                            throw new IllegalStateException("Unable to parse: " + ai, pe);
-                        }
+        @GuardedBy("mLock")
+        private void scanApexPackagesInternalLocked(PackageParser2 packageParser,
+                ExecutorService executorService) {
+            final ApexInfo[] allPkgs;
+            try {
+                mAllPackagesCache = new ArrayList<>();
+                mPackageNameToApexModuleName = new ArrayMap<>();
+                allPkgs = mApexService.getAllPackages();
+            } catch (RemoteException re) {
+                Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
+                throw new RuntimeException(re);
+            }
+            if (allPkgs.length == 0) {
+                return;
+            }
+            int flags = PackageManager.GET_META_DATA
+                    | PackageManager.GET_SIGNING_CERTIFICATES
+                    | PackageManager.GET_SIGNATURES;
+            ArrayMap<File, ApexInfo> parsingApexInfo = new ArrayMap<>();
+            ParallelPackageParser parallelPackageParser =
+                    new ParallelPackageParser(packageParser, executorService);
 
-                        final PackageInfo packageInfo =
-                                PackageParser.generatePackageInfo(pkg, ai, flags);
-                        mAllPackagesCache.add(packageInfo);
-                        if (ai.isActive) {
-                            if (activePackagesSet.contains(packageInfo.packageName)) {
-                                throw new IllegalStateException(
-                                        "Two active packages have the same name: "
-                                                + packageInfo.packageName);
-                            }
-                            activePackagesSet.add(packageInfo.packageName);
-                        }
-                        if (ai.isFactory) {
-                            if (factoryPackagesSet.contains(packageInfo.packageName)) {
-                                throw new IllegalStateException(
-                                        "Two factory packages have the same name: "
-                                                + packageInfo.packageName);
-                            }
-                            factoryPackagesSet.add(packageInfo.packageName);
-                        }
+            for (ApexInfo ai : allPkgs) {
+                File apexFile = new File(ai.modulePath);
+                parallelPackageParser.submit(apexFile, flags);
+                parsingApexInfo.put(apexFile, ai);
+            }
+
+            HashSet<String> activePackagesSet = new HashSet<>();
+            HashSet<String> factoryPackagesSet = new HashSet<>();
+            // Process results one by one
+            for (int i = 0; i < parsingApexInfo.size(); i++) {
+                ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take();
+                Throwable throwable = parseResult.throwable;
+                ApexInfo ai = parsingApexInfo.get(parseResult.scanFile);
+
+                if (throwable == null) {
+                    final PackageInfo packageInfo = PackageInfoWithoutStateUtils.generate(
+                            parseResult.parsedPackage, ai, flags);
+                    if (packageInfo == null) {
+                        throw new IllegalStateException("Unable to generate package info: "
+                                + ai.modulePath);
                     }
-                } catch (RemoteException re) {
-                    Slog.e(TAG, "Unable to retrieve packages from apexservice: " + re.toString());
-                    throw new RuntimeException(re);
+                    mAllPackagesCache.add(packageInfo);
+                    mPackageNameToApexModuleName.put(packageInfo.packageName, ai.moduleName);
+                    if (ai.isActive) {
+                        if (activePackagesSet.contains(packageInfo.packageName)) {
+                            throw new IllegalStateException(
+                                    "Two active packages have the same name: "
+                                            + packageInfo.packageName);
+                        }
+                        activePackagesSet.add(packageInfo.packageName);
+                    }
+                    if (ai.isFactory) {
+                        if (factoryPackagesSet.contains(packageInfo.packageName)) {
+                            throw new IllegalStateException(
+                                    "Two factory packages have the same name: "
+                                            + packageInfo.packageName);
+                        }
+                        factoryPackagesSet.add(packageInfo.packageName);
+                    }
+                } else if (throwable instanceof PackageParser.PackageParserException) {
+                    throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable);
+                } else {
+                    throw new IllegalStateException("Unexpected exception occurred while parsing "
+                            + ai.modulePath, throwable);
                 }
             }
         }
 
         @Override
-        @Nullable PackageInfo getPackageInfo(String packageName, @PackageInfoFlags int flags) {
-            populateAllPackagesCacheIfNeeded();
+        @Nullable
+        public PackageInfo getPackageInfo(String packageName,
+                @PackageInfoFlags int flags) {
+            Preconditions.checkState(mAllPackagesCache != null,
+                    "APEX packages have not been scanned");
             boolean matchActive = (flags & MATCH_ACTIVE_PACKAGE) != 0;
             boolean matchFactory = (flags & MATCH_FACTORY_PACKAGE) != 0;
             for (PackageInfo packageInfo: mAllPackagesCache) {
@@ -525,7 +536,8 @@
 
         @Override
         List<PackageInfo> getActivePackages() {
-            populateAllPackagesCacheIfNeeded();
+            Preconditions.checkState(mAllPackagesCache != null,
+                    "APEX packages have not been scanned");
             return mAllPackagesCache
                     .stream()
                     .filter(item -> isActive(item))
@@ -534,7 +546,8 @@
 
         @Override
         List<PackageInfo> getFactoryPackages() {
-            populateAllPackagesCacheIfNeeded();
+            Preconditions.checkState(mAllPackagesCache != null,
+                    "APEX packages have not been scanned");
             return mAllPackagesCache
                     .stream()
                     .filter(item -> isFactory(item))
@@ -543,7 +556,8 @@
 
         @Override
         List<PackageInfo> getInactivePackages() {
-            populateAllPackagesCacheIfNeeded();
+            Preconditions.checkState(mAllPackagesCache != null,
+                    "APEX packages have not been scanned");
             return mAllPackagesCache
                     .stream()
                     .filter(item -> !isActive(item))
@@ -553,7 +567,8 @@
         @Override
         boolean isApexPackage(String packageName) {
             if (!isApexSupported()) return false;
-            populateAllPackagesCacheIfNeeded();
+            Preconditions.checkState(mAllPackagesCache != null,
+                    "APEX packages have not been scanned");
             for (PackageInfo packageInfo : mAllPackagesCache) {
                 if (packageInfo.packageName.equals(packageName)) {
                     return true;
@@ -563,6 +578,36 @@
         }
 
         @Override
+        @Nullable
+        public String getActiveApexPackageNameContainingPackage(
+                @NonNull AndroidPackage containedPackage) {
+            Preconditions.checkState(mPackageNameToApexModuleName != null,
+                    "APEX packages have not been scanned");
+
+            Objects.requireNonNull(containedPackage);
+
+            synchronized (mLock) {
+                int numApksInApex = mApksInApex.size();
+                for (int apkInApexNum = 0; apkInApexNum < numApksInApex; apkInApexNum++) {
+                    if (mApksInApex.valueAt(apkInApexNum).contains(
+                            containedPackage.getPackageName())) {
+                        String apexModuleName = mApksInApex.keyAt(apkInApexNum);
+
+                        int numApexPkgs = mPackageNameToApexModuleName.size();
+                        for (int apexPkgNum = 0; apexPkgNum < numApexPkgs; apexPkgNum++) {
+                            if (mPackageNameToApexModuleName.valueAt(apexPkgNum).equals(
+                                    apexModuleName)) {
+                                return mPackageNameToApexModuleName.keyAt(apexPkgNum);
+                            }
+                        }
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        @Override
         @Nullable ApexSessionInfo getStagedSessionInfo(int sessionId) {
             try {
                 ApexSessionInfo apexSessionInfo = mApexService.getStagedSessionInfo(sessionId);
@@ -684,8 +729,9 @@
 
         @Override
         List<String> getApksInApex(String apexPackageName) {
-            populatePackageNameToApexModuleNameIfNeeded();
             synchronized (mLock) {
+                Preconditions.checkState(mPackageNameToApexModuleName != null,
+                        "APEX packages have not been scanned");
                 String moduleName = mPackageNameToApexModuleName.get(apexPackageName);
                 if (moduleName == null) {
                     return Collections.emptyList();
@@ -697,17 +743,19 @@
         @Override
         @Nullable
         public String getApexModuleNameForPackageName(String apexPackageName) {
-            populatePackageNameToApexModuleNameIfNeeded();
             synchronized (mLock) {
+                Preconditions.checkState(mPackageNameToApexModuleName != null,
+                        "APEX packages have not been scanned");
                 return mPackageNameToApexModuleName.get(apexPackageName);
             }
         }
 
         @Override
         public long snapshotCeData(int userId, int rollbackId, String apexPackageName) {
-            populatePackageNameToApexModuleNameIfNeeded();
             String apexModuleName;
             synchronized (mLock) {
+                Preconditions.checkState(mPackageNameToApexModuleName != null,
+                        "APEX packages have not been scanned");
                 apexModuleName = mPackageNameToApexModuleName.get(apexPackageName);
             }
             if (apexModuleName == null) {
@@ -724,9 +772,10 @@
 
         @Override
         public boolean restoreCeData(int userId, int rollbackId, String apexPackageName) {
-            populatePackageNameToApexModuleNameIfNeeded();
             String apexModuleName;
             synchronized (mLock) {
+                Preconditions.checkState(mPackageNameToApexModuleName != null,
+                        "APEX packages have not been scanned");
                 apexModuleName = mPackageNameToApexModuleName.get(apexPackageName);
             }
             if (apexModuleName == null) {
@@ -797,15 +846,7 @@
         void dump(PrintWriter pw, @Nullable String packageName) {
             final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ", 120);
             try {
-                populateAllPackagesCacheIfNeeded();
                 ipw.println();
-                ipw.println("Active APEX packages:");
-                dumpFromPackagesCache(getActivePackages(), packageName, ipw);
-                ipw.println("Inactive APEX packages:");
-                dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
-                ipw.println("Factory APEX packages:");
-                dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
-                ipw.increaseIndent();
                 ipw.println("APEX session state:");
                 ipw.increaseIndent();
                 final ApexSessionInfo[] sessions = mApexService.getSessions();
@@ -834,6 +875,17 @@
                     ipw.decreaseIndent();
                 }
                 ipw.decreaseIndent();
+                ipw.println();
+                if (mAllPackagesCache == null) {
+                    ipw.println("APEX packages have not been scanned");
+                    return;
+                }
+                ipw.println("Active APEX packages:");
+                dumpFromPackagesCache(getActivePackages(), packageName, ipw);
+                ipw.println("Inactive APEX packages:");
+                dumpFromPackagesCache(getInactivePackages(), packageName, ipw);
+                ipw.println("Factory APEX packages:");
+                dumpFromPackagesCache(getFactoryPackages(), packageName, ipw);
             } catch (RemoteException e) {
                 ipw.println("Couldn't communicate with apexd.");
             }
@@ -879,12 +931,13 @@
         }
 
         @Override
-        void systemReady(Context context) {
+        void scanApexPackagesTraced(@NonNull PackageParser2 packageParser,
+                @NonNull ExecutorService executorService) {
             // No-op
         }
 
         @Override
-        PackageInfo getPackageInfo(String packageName, int flags) {
+        public PackageInfo getPackageInfo(String packageName, int flags) {
             return null;
         }
 
@@ -909,6 +962,15 @@
         }
 
         @Override
+        @Nullable
+        public String getActiveApexPackageNameContainingPackage(
+                @NonNull AndroidPackage containedPackage) {
+            Objects.requireNonNull(containedPackage);
+
+            return null;
+        }
+
+        @Override
         ApexSessionInfo getStagedSessionInfo(int sessionId) {
             throw new UnsupportedOperationException();
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 58a9d9c..34363c8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -2900,6 +2900,9 @@
                     mMetrics, mCacheDir, mPackageParserCallback);
 
             ExecutorService executorService = ParallelPackageParser.makeExecutorService();
+            // Prepare apex package info before scanning APKs, these information are needed when
+            // scanning apk in apex.
+            mApexManager.scanApexPackagesTraced(packageParser, executorService);
             // Collect vendor/product/system_ext overlay packages. (Do this before scanning
             // any apps.)
             // For security and version matching reason, only consider overlay packages if they
@@ -20696,7 +20699,6 @@
         storage.registerListener(mStorageListener);
 
         mInstallerService.systemReady();
-        mApexManager.systemReady(mContext);
         mPackageDexOptimizer.systemReady();
 
         mInjector.getStorageManagerInternal().addExternalStoragePolicy(
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 04c965e..765ecb9 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -42,6 +42,7 @@
 import static android.permission.PermissionManager.KILL_APP_REASON_GIDS_CHANGED;
 import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
 
+import static com.android.server.pm.ApexManager.MATCH_ACTIVE_PACKAGE;
 import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
 import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
 import static com.android.server.pm.PackageManagerService.DEBUG_PERMISSIONS;
@@ -130,6 +131,7 @@
 import com.android.server.ServiceThread;
 import com.android.server.SystemConfig;
 import com.android.server.Watchdog;
+import com.android.server.pm.ApexManager;
 import com.android.server.pm.PackageManagerServiceUtils;
 import com.android.server.pm.PackageSetting;
 import com.android.server.pm.SharedUserSetting;
@@ -3317,8 +3319,16 @@
         if (!privappPermissionsDisable && privilegedPermission && pkg.isPrivileged()
                 && !platformPackage && platformPermission) {
             if (!hasPrivappWhitelistEntry(perm, pkg)) {
-                // Only report violations for apps on system image
-                if (!mSystemReady && !pkgSetting.getPkgState().isUpdatedSystemApp()) {
+                ApexManager apexMgr = ApexManager.getInstance();
+                String apexContainingPkg = apexMgr.getActiveApexPackageNameContainingPackage(pkg);
+
+                // Only enforce whitelist this on boot
+                if (!mSystemReady
+                        // Updated system apps do not need to be whitelisted
+                        && !pkgSetting.getPkgState().isUpdatedSystemApp()
+                        // Apps that are in updated apexs' do not need to be whitelisted
+                        && (apexContainingPkg == null || apexMgr.isFactory(
+                        apexMgr.getPackageInfo(apexContainingPkg, MATCH_ACTIVE_PACKAGE)))) {
                     // it's only a reportable violation if the permission isn't explicitly denied
                     ArraySet<String> deniedPermissions = null;
                     if (pkg.isVendor()) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
index 40ada2a..db1bbab 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ApexManagerTest.java
@@ -43,6 +43,7 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.frameworks.servicestests.R;
+import com.android.server.pm.parsing.PackageParser2;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -63,6 +64,7 @@
     private static final int[] TEST_CHILD_SESSION_ID = {8888, 7777};
     private ApexManager mApexManager;
     private Context mContext;
+    private PackageParser2 mPackageParser2;
 
     private IApexService mApexService = mock(IApexService.class);
 
@@ -70,11 +72,14 @@
     public void setUp() throws RemoteException {
         mContext = InstrumentationRegistry.getInstrumentation().getContext();
         mApexManager = new ApexManager.ApexManagerImpl(mApexService);
+        mPackageParser2 = new PackageParser2(null, false, null, null, null);
     }
 
     @Test
     public void testGetPackageInfo_setFlagsMatchActivePackage() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
         final PackageInfo activePkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
                 ApexManager.MATCH_ACTIVE_PACKAGE);
 
@@ -90,6 +95,8 @@
     @Test
     public void testGetPackageInfo_setFlagsMatchFactoryPackage() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
         PackageInfo factoryPkgPi = mApexManager.getPackageInfo(TEST_APEX_PKG,
                 ApexManager.MATCH_FACTORY_PACKAGE);
 
@@ -105,6 +112,8 @@
     @Test
     public void testGetPackageInfo_setFlagsNone() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getPackageInfo(TEST_APEX_PKG, 0)).isNull();
     }
@@ -112,6 +121,8 @@
     @Test
     public void testGetActivePackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getActivePackages()).isNotEmpty();
     }
@@ -119,6 +130,8 @@
     @Test
     public void testGetActivePackages_noneActivePackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getActivePackages()).isEmpty();
     }
@@ -126,6 +139,8 @@
     @Test
     public void testGetFactoryPackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getFactoryPackages()).isNotEmpty();
     }
@@ -133,6 +148,8 @@
     @Test
     public void testGetFactoryPackages_noneFactoryPackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getFactoryPackages()).isEmpty();
     }
@@ -140,6 +157,8 @@
     @Test
     public void testGetInactivePackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getInactivePackages()).isNotEmpty();
     }
@@ -147,6 +166,8 @@
     @Test
     public void testGetInactivePackages_noneInactivePackages() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(true, false));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.getInactivePackages()).isEmpty();
     }
@@ -154,6 +175,8 @@
     @Test
     public void testIsApexPackage() throws RemoteException {
         when(mApexService.getAllPackages()).thenReturn(createApexInfo(false, true));
+        mApexManager.scanApexPackagesTraced(mPackageParser2,
+                ParallelPackageParser.makeExecutorService());
 
         assertThat(mApexManager.isApexPackage(TEST_APEX_PKG)).isTrue();
     }