Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ecccf009 authored by Patrick Baumann's avatar Patrick Baumann Committed by Bill Lin
Browse files

Refactors initial directory scan to be dryer

This change collapses a bunch of manual calls to scanDir with a map and
a loop. This makes things a little more readable and easier to update
going forward.

Bug: NA
Test: boots without issue.
Merged-In: I81fb7a9474894d0bceecb6b0ef7a64d047a40c14
Change-Id: I81fb7a9474894d0bceecb6b0ef7a64d047a40c14
parent 18fa446f
Loading
Loading
Loading
Loading
+123 −371
Original line number Diff line number Diff line
@@ -91,6 +91,7 @@ import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static com.android.internal.annotations.VisibleForTesting.Visibility;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
@@ -588,16 +589,6 @@ public class PackageManagerService extends IPackageManager.Stub
    private static final String PACKAGE_SCHEME = "package";
    private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
    private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
    private static final String SYSTEM_EXT_OVERLAY_DIR = "/system_ext/overlay";
    private static final String ODM_OVERLAY_DIR = "/odm/overlay";
    private static final String OEM_OVERLAY_DIR = "/oem/overlay";
    /** Canonical intent used to identify what counts as a "web browser" app */
    private static final Intent sBrowserIntent;
    static {
@@ -757,7 +748,29 @@ public class PackageManagerService extends IPackageManager.Stub
    private final Injector mInjector;
    /**
     * Unit tests will instantiate and / or extend to mock dependencies / behaviors.
     * The list of all system partitions that may contain packages in ascending order of
     * specificity (the more generic, the earlier in the list a partition appears).
     */
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static final List<SystemPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
            Arrays.asList(
                    new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */,
                            true /* hasPriv */, false /* hasOverlays */),
                    new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR,
                            true /* hasPriv */, true /* hasOverlays */),
                    new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM,
                            true /* hasPriv */, true /* hasOverlays */),
                    new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM,
                            false /* hasPriv */, true /* hasOverlays */),
                    new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT,
                            true /* hasPriv */, true /* hasOverlays */),
                    new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
                            true /* hasPriv */, true /* hasOverlays */)));
    /**
     * Unit tests will instantiate, extend and/or mock to mock dependencies / behaviors.
     *
     * NOTE: All getters should return the same instance for every call.
     */
    @VisibleForTesting
    static class Injector {
@@ -2410,6 +2423,51 @@ public class PackageManagerService extends IPackageManager.Stub
        }
    }
    @VisibleForTesting(visibility = Visibility.PRIVATE)
    static class SystemPartition {
        public final File folder;
        public final int scanFlag;
        public final File appFolder;
        @Nullable
        public final File privAppFolder;
        @Nullable
        public final File overlayFolder;
        private SystemPartition(File folder, int scanFlag, boolean hasPrivApps,
                boolean hasOverlays) {
            this.folder = folder;
            this.scanFlag = scanFlag;
            this.appFolder = toCanonical(new File(folder, "app"));
            this.privAppFolder = hasPrivApps ? toCanonical(new File(folder, "priv-app")) : null;
            this.overlayFolder = hasOverlays ? toCanonical(new File(folder, "overlay")) : null;
        }
        public boolean containsPrivApp(File scanFile) {
            return FileUtils.contains(privAppFolder, scanFile);
        }
        public boolean containsApp(File scanFile) {
            return FileUtils.contains(appFolder, scanFile);
        }
        public boolean containsPath(String path) {
            return path.startsWith(folder.getPath() + "/");
        }
        public boolean containsPrivPath(String path) {
            return privAppFolder != null && path.startsWith(privAppFolder.getPath() + "/");
        }
        private static File toCanonical(File dir) {
            try {
                return dir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
                return dir;
            }
        }
    }
    public PackageManagerService(Context context, Installer installer,
        boolean factoryTest, boolean onlyCore) {
            LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES);
@@ -2640,215 +2698,35 @@ public class PackageManagerService extends IPackageManager.Stub
            // any apps.)
            // For security and version matching reason, only consider overlay packages if they
            // reside in the right directory.
            scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
            scanDirTracedLI(new File(PRODUCT_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT,
                    0);
            scanDirTracedLI(new File(SYSTEM_EXT_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_SYSTEM_EXT,
                    0);
            scanDirTracedLI(new File(ODM_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_ODM,
                    0);
            scanDirTracedLI(new File(OEM_OVERLAY_DIR),
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_OEM,
                    0);
            final int systemParseFlags = mDefParseFlags | PackageParser.PARSE_IS_SYSTEM_DIR;
            final int systemScanFlags = scanFlags | SCAN_AS_SYSTEM;
            for (int i = SYSTEM_PARTITIONS.size() - 1; i >= 0; i--) {
                final SystemPartition partition = SYSTEM_PARTITIONS.get(i);
                if (partition.overlayFolder == null) {
                    continue;
                }
                scanDirTracedLI(partition.overlayFolder, systemParseFlags,
                        systemScanFlags | partition.scanFlag, 0);
            }
            mParallelPackageParserCallback.findStaticOverlayPackages();
            // Find base frameworks (resource packages without code).
            scanDirTracedLI(frameworkDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_NO_DEX
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED,
                    0);
            scanDirTracedLI(frameworkDir, systemParseFlags,
                    systemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0);
            if (!mPackages.containsKey("android")) {
                throw new IllegalStateException(
                        "Failed to load frameworks package; check log for warnings");
            }
            // Collect privileged system packages.
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            scanDirTracedLI(privilegedAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRIVILEGED,
                    0);
            // Collect ordinary system packages.
            final File systemAppDir = new File(Environment.getRootDirectory(), "app");
            scanDirTracedLI(systemAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM,
                    0);
            // Collect privileged vendor packages.
            File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
            try {
                privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedVendorAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR
                    | SCAN_AS_PRIVILEGED,
                    0);
            // Collect ordinary vendor packages.
            File vendorAppDir = new File(Environment.getVendorDirectory(), "app");
            try {
                vendorAppDir = vendorAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(vendorAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
            // Collect privileged odm packages. /odm is another vendor partition
            // other than /vendor.
            File privilegedOdmAppDir = new File(Environment.getOdmDirectory(),
                        "priv-app");
            try {
                privilegedOdmAppDir = privilegedOdmAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedOdmAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR
                    | SCAN_AS_PRIVILEGED,
                    0);
            // Collect ordinary odm packages. /odm is another vendor partition
            // other than /vendor.
            File odmAppDir = new File(Environment.getOdmDirectory(), "app");
            try {
                odmAppDir = odmAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(odmAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_VENDOR,
                    0);
            // Collect all OEM packages.
            final File oemAppDir = new File(Environment.getOemDirectory(), "app");
            scanDirTracedLI(oemAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_OEM,
                    0);
            // Collected privileged /product packages.
            File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
            try {
                privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(privilegedProductAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT
                    | SCAN_AS_PRIVILEGED,
                    0);
            // Collect ordinary /product packages.
            File productAppDir = new File(Environment.getProductDirectory(), "app");
            try {
                productAppDir = productAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
                final SystemPartition partition = SYSTEM_PARTITIONS.get(i);
                if (partition.privAppFolder != null) {
                    scanDirTracedLI(partition.privAppFolder, systemParseFlags,
                            systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0);
                }
            scanDirTracedLI(productAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_PRODUCT,
                    0);
            // Collected privileged /system_ext packages.
            File privilegedSystemExtAppDir =
                    new File(Environment.getSystemExtDirectory(), "priv-app");
            try {
                privilegedSystemExtAppDir =
                        privilegedSystemExtAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
                scanDirTracedLI(partition.appFolder, systemParseFlags,
                        systemScanFlags | partition.scanFlag, 0);
            }
            scanDirTracedLI(privilegedSystemExtAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_SYSTEM_EXT
                    | SCAN_AS_PRIVILEGED,
                    0);
            // Collect ordinary /system_ext packages.
            File systemExtAppDir = new File(Environment.getSystemExtDirectory(), "app");
            try {
                systemExtAppDir = systemExtAppDir.getCanonicalFile();
            } catch (IOException e) {
                // failed to look up canonical path, continue with original one
            }
            scanDirTracedLI(systemExtAppDir,
                    mDefParseFlags
                    | PackageParser.PARSE_IS_SYSTEM_DIR,
                    scanFlags
                    | SCAN_AS_SYSTEM
                    | SCAN_AS_SYSTEM_EXT,
                    0);
            // Prune any system packages that no longer exist.
            final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
@@ -3016,89 +2894,26 @@ public class PackageManagerService extends IPackageManager.Stub
                        logCriticalInfo(Log.WARN, "Expected better " + packageName
                                + " but never showed up; reverting to system");
                        final @ParseFlags int reparseFlags;
                        final @ScanFlags int rescanFlags;
                        if (FileUtils.contains(privilegedAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_PRIVILEGED;
                        } else if (FileUtils.contains(systemAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM;
                        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)
                                || FileUtils.contains(privilegedOdmAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_VENDOR
                                    | SCAN_AS_PRIVILEGED;
                        } else if (FileUtils.contains(vendorAppDir, scanFile)
                                || FileUtils.contains(odmAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_VENDOR;
                        } else if (FileUtils.contains(oemAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_OEM;
                        } else if (FileUtils.contains(privilegedProductAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_PRODUCT
                                    | SCAN_AS_PRIVILEGED;
                        } else if (FileUtils.contains(productAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_PRODUCT;
                        } else if (FileUtils.contains(privilegedSystemExtAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_SYSTEM_EXT
                                    | SCAN_AS_PRIVILEGED;
                        } else if (FileUtils.contains(systemExtAppDir, scanFile)) {
                            reparseFlags =
                                    mDefParseFlags |
                                    PackageParser.PARSE_IS_SYSTEM_DIR;
                            rescanFlags =
                                    scanFlags
                                    | SCAN_AS_SYSTEM
                                    | SCAN_AS_SYSTEM_EXT;
                        } else {
                        @ParseFlags int reparseFlags = 0;
                        @ScanFlags int rescanFlags = 0;
                        for (int i1 = 0, size = SYSTEM_PARTITIONS.size(); i1 < size; i1++) {
                            SystemPartition partition = SYSTEM_PARTITIONS.get(i1);
                            if (partition.containsPrivApp(scanFile)) {
                                reparseFlags = systemParseFlags;
                                rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED
                                        | partition.scanFlag;
                                break;
                            }
                            if (partition.containsApp(scanFile)) {
                                reparseFlags = systemParseFlags;
                                rescanFlags = systemScanFlags | partition.scanFlag;
                                break;
                            }
                        }
                        if (rescanFlags == 0) {
                            Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                            continue;
                        }
                        mSettings.enableSystemPackageLPw(packageName);
                        try {
@@ -18560,70 +18375,15 @@ public class PackageManagerService extends IPackageManager.Stub
    }
    static boolean locationIsPrivileged(String path) {
        try {
            final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
            final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
            final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
            final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
            final File privilegedSystemExtAppDir =
                    new File(Environment.getSystemExtDirectory(), "priv-app");
            return path.startsWith(privilegedAppDir.getCanonicalPath() + "/")
                    || path.startsWith(privilegedVendorAppDir.getCanonicalPath() + "/")
                    || path.startsWith(privilegedOdmAppDir.getCanonicalPath() + "/")
                    || path.startsWith(privilegedProductAppDir.getCanonicalPath() + "/")
                    || path.startsWith(privilegedSystemExtAppDir.getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
    }
    static boolean locationIsOem(String path) {
        try {
            return path.startsWith(Environment.getOemDirectory().getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
    }
    static boolean locationIsVendor(String path) {
        try {
            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath() + "/")
                    || path.startsWith(Environment.getOdmDirectory().getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
    }
    static boolean locationIsProduct(String path) {
        try {
            return path.startsWith(Environment.getProductDirectory().getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
        for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
            SystemPartition partition = SYSTEM_PARTITIONS.get(i);
            if (partition.containsPrivPath(path)) {
                return true;
            }
    static boolean locationIsSystemExt(String path) {
        try {
            return path.startsWith(
              Environment.getSystemExtDirectory().getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
    }
    static boolean locationIsOdm(String path) {
        try {
            return path.startsWith(Environment.getOdmDirectory().getCanonicalPath() + "/");
        } catch (IOException e) {
            Slog.e(TAG, "Unable to access code path " + path);
        }
        return false;
    }
    /*
     * Tries to delete system package.
@@ -18730,23 +18490,15 @@ public class PackageManagerService extends IPackageManager.Stub
                | PackageParser.PARSE_MUST_BE_APK
                | PackageParser.PARSE_IS_SYSTEM_DIR;
        @ScanFlags int scanFlags = SCAN_AS_SYSTEM;
        if (locationIsPrivileged(codePathString)) {
        for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) {
            SystemPartition partition = SYSTEM_PARTITIONS.get(i);
            if (partition.containsPath(codePathString)) {
                scanFlags |= partition.scanFlag;
                if (partition.containsPrivPath(codePathString)) {
                    scanFlags |= SCAN_AS_PRIVILEGED;
                }
        if (locationIsOem(codePathString)) {
            scanFlags |= SCAN_AS_OEM;
        }
        if (locationIsVendor(codePathString)) {
            scanFlags |= SCAN_AS_VENDOR;
        }
        if (locationIsProduct(codePathString)) {
            scanFlags |= SCAN_AS_PRODUCT;
        }
        if (locationIsSystemExt(codePathString)) {
            scanFlags |= SCAN_AS_SYSTEM_EXT;
                break;
            }
        if (locationIsOdm(codePathString)) {
            scanFlags |= SCAN_AS_ODM;
        }
        final File codePath = new File(codePathString);
+9 −6

File changed.

Preview size limit exceeded, changes collapsed.