diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index c237222d91349..7a131e5680a81 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -55,6 +55,7 @@ public class Environment { private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT"; private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT"; private static final String ENV_SYSTEM_EXT_ROOT = "SYSTEM_EXT_ROOT"; + private static final String ENV_APEX_ROOT = "APEX_ROOT"; /** {@hide} */ public static final String DIR_ANDROID = "Android"; @@ -78,7 +79,9 @@ public class Environment { private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor"); private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product"); private static final File DIR_SYSTEM_EXT_ROOT = getDirectory(ENV_SYSTEM_EXT_ROOT, - "/system_ext"); + "/system_ext"); + private static final File DIR_APEX_ROOT = getDirectory(ENV_APEX_ROOT, + "/apex"); @UnsupportedAppUsage private static UserEnvironment sCurrentUser; @@ -245,6 +248,16 @@ public class Environment { return DIR_SYSTEM_EXT_ROOT; } + /** + * Return root directory of the apex mount point, where all the apex modules are made available + * to the rest of the system. + * + * @hide + */ + public static @NonNull File getApexDirectory() { + return DIR_APEX_ROOT; + } + /** * Return the system directory for a user. This is for use by system * services to store files relating to the user. This directory will be diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index fd44cbb460652..12e8069ecae5f 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -32,6 +32,7 @@ import android.content.pm.PackageInfo; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; import android.content.pm.PackageParser; +import android.os.Environment; import android.os.RemoteException; import android.os.ServiceManager; import android.sysprop.ApexProperties; @@ -47,6 +48,7 @@ import java.io.PrintWriter; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.List; @@ -64,9 +66,9 @@ abstract class ApexManager { static final int MATCH_FACTORY_PACKAGE = 1 << 1; /** - * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerNoOp} depending - * on whenever this device supports APEX, i.e. {@link ApexProperties#updatable()} evaluates to - * {@code true}. + * Returns an instance of either {@link ApexManagerImpl} or {@link ApexManagerFlattenedApex} + * depending on whether this device supports APEX, i.e. {@link ApexProperties#updatable()} + * evaluates to {@code true}. */ static ApexManager create(Context systemContext) { if (ApexProperties.updatable().orElse(false)) { @@ -77,10 +79,28 @@ abstract class ApexManager { throw new IllegalStateException("Required service apexservice not available"); } } else { - return new ApexManagerNoOp(); + return new ApexManagerFlattenedApex(); } } + /** + * Minimal information about APEX mount points and the original APEX package they refer to. + */ + static class ActiveApexInfo { + public final File apexDirectory; + public final File preinstalledApexPath; + + private ActiveApexInfo(File apexDirectory, File preinstalledApexPath) { + this.apexDirectory = apexDirectory; + this.preinstalledApexPath = preinstalledApexPath; + } + } + + /** + * Returns {@link ActiveApexInfo} records relative to all active APEX packages. + */ + abstract List getActiveApexInfos(); + abstract void systemReady(); /** @@ -258,6 +278,22 @@ abstract class ApexManager { return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0; } + @Override + List getActiveApexInfos() { + try { + return Arrays.stream(mApexService.getActivePackages()) + .map(apexInfo -> new ActiveApexInfo( + new File( + Environment.getApexDirectory() + File.separator + + apexInfo.moduleName), + new File(apexInfo.modulePath))).collect( + Collectors.toList()); + } catch (RemoteException e) { + Slog.e(TAG, "Unable to retrieve packages from apexservice", e); + } + return Collections.emptyList(); + } + @Override void systemReady() { mContext.registerReceiver(new BroadcastReceiver() { @@ -549,7 +585,40 @@ abstract class ApexManager { * An implementation of {@link ApexManager} that should be used in case device does not support * updating APEX packages. */ - private static final class ApexManagerNoOp extends ApexManager { + private static final class ApexManagerFlattenedApex extends ApexManager { + + @Override + List getActiveApexInfos() { + // There is no apexd running in case of flattened apex + // We look up the /apex directory and identify the active APEX modules from there. + // As "preinstalled" path, we just report /system since in the case of flattened APEX + // the /apex directory is just a symlink to /system/apex. + List result = new ArrayList<>(); + File apexDir = Environment.getApexDirectory(); + // In flattened configuration, init special-case the art directory and bind-mounts + // com.android.art.{release|debug} to com.android.art. At the time of writing, these + // directories are copied from the kArtApexDirNames variable in + // system/core/init/mount_namespace.cpp. + String[] skipDirs = {"com.android.art.release", "com.android.art.debug"}; + if (apexDir.isDirectory()) { + File[] files = apexDir.listFiles(); + // listFiles might be null if system server doesn't have permission to read + // a directory. + if (files != null) { + for (File file : files) { + if (file.isDirectory() && !file.getName().contains("@")) { + for (String skipDir : skipDirs) { + if (file.getName().equals(skipDir)) { + continue; + } + } + result.add(new ActiveApexInfo(file, Environment.getRootDirectory())); + } + } + } + } + return result; + } @Override void systemReady() { diff --git a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java index 1d3d24c270412..259200b92597b 100644 --- a/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java +++ b/services/core/java/com/android/server/pm/PackageAbiHelperImpl.java @@ -67,6 +67,15 @@ final class PackageAbiHelperImpl implements PackageAbiHelper { codeRoot = Environment.getSystemExtDirectory(); } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) { codeRoot = Environment.getOdmDirectory(); + } else if (FileUtils.contains(Environment.getApexDirectory(), codePath)) { + String fullPath = codePath.getAbsolutePath(); + String[] parts = fullPath.split(File.separator); + if (parts.length > 2) { + codeRoot = new File(parts[1] + File.separator + parts[2]); + } else { + Slog.w(PackageManagerService.TAG, "Can't canonicalize code path " + codePath); + codeRoot = Environment.getApexDirectory(); + } } else { // Unrecognized code path; take its top real segment as the apk root: // e.g. /something/app/blah.apk => /something diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 9198b8de45600..c5a04dd635f1c 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -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; @@ -374,6 +375,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Collectors; /** * Keep track of all those APKs everywhere. @@ -588,16 +590,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 +749,31 @@ 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 SYSTEM_PARTITIONS = Collections.unmodifiableList( + Arrays.asList( + new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */, + false /* hasOverlays */), + new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR, + true /* hasOverlays */), + new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM, + true /* hasOverlays */), + new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM, + true /* hasOverlays */), + new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT, + true /* hasOverlays */), + new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT, + true /* hasOverlays */))); + + private final List mDirsToScanAsSystem; + + /** + * 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,9 +2426,70 @@ 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 static boolean shouldScanPrivApps(@ScanFlags int scanFlags) { + if ((scanFlags & SCAN_AS_OEM) != 0) { + return false; + } + if (scanFlags == 0) { // /system partition + return true; + } + if ((scanFlags + & (SCAN_AS_VENDOR | SCAN_AS_ODM | SCAN_AS_PRODUCT | SCAN_AS_SYSTEM_EXT)) != 0) { + return true; + } + return false; + } + + private SystemPartition(File folder, int scanFlag, boolean hasOverlays) { + this.folder = folder; + this.scanFlag = scanFlag; + this.appFolder = toCanonical(new File(folder, "app")); + this.privAppFolder = shouldScanPrivApps(scanFlag) + ? toCanonical(new File(folder, "priv-app")) + : null; + this.overlayFolder = hasOverlays ? toCanonical(new File(folder, "overlay")) : null; + } + + 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); + boolean factoryTest, boolean onlyCore) { + LockGuard.installLock(mPackages, LockGuard.INDEX_PACKAGES); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "create package manager"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_START, SystemClock.uptimeMillis()); @@ -2505,7 +2582,18 @@ public class PackageManagerService extends IPackageManager.Stub mProtectedPackages = new ProtectedPackages(mContext); - mApexManager = ApexManager.create(context); + mApexManager = ApexManager.create(mContext); + + mDirsToScanAsSystem = new ArrayList<>(); + mDirsToScanAsSystem.addAll(SYSTEM_PARTITIONS); + mDirsToScanAsSystem.addAll(mApexManager.getActiveApexInfos().stream() + .map(ai -> resolveApexToSystemPartition(ai)) + .filter(Objects::nonNull).collect(Collectors.toList())); + Slog.d(TAG, + "Directories scanned as system partitions: [" + mDirsToScanAsSystem.stream().map( + d -> (d.folder.getAbsolutePath() + ":" + d.scanFlag)) + .collect(Collectors.joining(",")) + "]"); + // CHECKSTYLE:OFF IndentationCheck synchronized (mInstallLock) { // writer @@ -2640,215 +2728,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 = mDirsToScanAsSystem.size() - 1; i >= 0; i--) { + final SystemPartition partition = mDirsToScanAsSystem.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 + for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) { + final SystemPartition partition = mDirsToScanAsSystem.get(i); + if (partition.privAppFolder != null) { + scanDirTracedLI(partition.privAppFolder, systemParseFlags, + systemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0); + } + scanDirTracedLI(partition.appFolder, systemParseFlags, + systemScanFlags | partition.scanFlag, 0); } - 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 - } - 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(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 possiblyDeletedUpdatedSystemApps = new ArrayList<>(); @@ -3016,89 +2924,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 = mDirsToScanAsSystem.size(); i1 < size; i1++) { + SystemPartition partition = mDirsToScanAsSystem.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 { @@ -18559,70 +18404,17 @@ 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); + private static @Nullable SystemPartition resolveApexToSystemPartition( + ApexManager.ActiveApexInfo apexInfo) { + for (int i = 0, size = SYSTEM_PARTITIONS.size(); i < size; i++) { + SystemPartition sp = SYSTEM_PARTITIONS.get(i); + if (apexInfo.preinstalledApexPath.getAbsolutePath().startsWith( + sp.folder.getAbsolutePath())) { + return new SystemPartition(apexInfo.apexDirectory, sp.scanFlag, + false /* hasOverlays */); + } } - 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; - } - - 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; + return null; } /* @@ -18734,23 +18526,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)) { - 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; - } - if (locationIsOdm(codePathString)) { - scanFlags |= SCAN_AS_ODM; + for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) { + SystemPartition partition = mDirsToScanAsSystem.get(i); + if (partition.containsPath(codePathString)) { + scanFlags |= partition.scanFlag; + if (partition.containsPrivPath(codePathString)) { + scanFlags |= SCAN_AS_PRIVILEGED; + } + break; + } } final File codePath = new File(codePathString); @@ -22564,9 +22348,9 @@ public class PackageManagerService extends IPackageManager.Stub mSettings.writeKernelMappingLPr(ps); } - final UserManager um = mContext.getSystemService(UserManager.class); + final UserManagerService um = sUserManager; UserManagerInternal umInternal = getUserManagerInternal(); - for (UserInfo user : um.getUsers()) { + for (UserInfo user : um.getUsers(false /* excludeDying */)) { final int flags; if (umInternal.isUserUnlockingOrUnlocked(user.id)) { flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE; diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 4ecfbfee6e654..d1e4537b9235a 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -3506,7 +3506,7 @@ public final class Settings { int pkgFlags = 0; int pkgPrivateFlags = 0; pkgFlags |= ApplicationInfo.FLAG_SYSTEM; - if (PackageManagerService.locationIsPrivileged(codePathStr)) { + if (codePathStr.contains("/priv-app/")) { pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED; } PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr), diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java index fc7cfec9dc875..0a310d1936756 100644 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java +++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerServiceTest.java @@ -118,17 +118,20 @@ public class PackageManagerServiceTest { String[] partitions = { "system", "vendor", "odm", "oem", "product", "system_ext" }; String[] appdir = { "app", "priv-app" }; for (int i = 0; i < partitions.length; i++) { + final PackageManagerService.SystemPartition systemPartition = + PackageManagerService.SYSTEM_PARTITIONS.get(i); for (int j = 0; j < appdir.length; j++) { String canonical = new File("/" + partitions[i]).getCanonicalPath(); String path = String.format("%s/%s/A.apk", canonical, appdir[j]); - Assert.assertEquals(j == 1 && i != 3, - PackageManagerService.locationIsPrivileged(path)); + Assert.assertEquals(j == 1 && i != 3, systemPartition.containsPrivPath(path)); - Assert.assertEquals(i == 1 || i == 2, PackageManagerService.locationIsVendor(path)); - Assert.assertEquals(i == 3, PackageManagerService.locationIsOem(path)); - Assert.assertEquals(i == 4, PackageManagerService.locationIsProduct(path)); - Assert.assertEquals(i == 5, PackageManagerService.locationIsSystemExt(path)); + final int scanFlag = systemPartition.scanFlag; + Assert.assertEquals(i == 1, scanFlag == PackageManagerService.SCAN_AS_VENDOR); + Assert.assertEquals(i == 2, scanFlag == PackageManagerService.SCAN_AS_ODM); + Assert.assertEquals(i == 3, scanFlag == PackageManagerService.SCAN_AS_OEM); + Assert.assertEquals(i == 4, scanFlag == PackageManagerService.SCAN_AS_PRODUCT); + Assert.assertEquals(i == 5, scanFlag == PackageManagerService.SCAN_AS_SYSTEM_EXT); } } }