Support privileged apps installed in APEX. am: 787471af48

am: 3fad35fa15

Change-Id: Idc501a4c77d6d3f13e7b416d98815d9b944c9202
This commit is contained in:
Dario Freni
2019-12-03 08:44:41 -08:00
committed by android-build-merger
6 changed files with 265 additions and 387 deletions

View File

@@ -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

View File

@@ -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<ActiveApexInfo> getActiveApexInfos();
abstract void systemReady();
/**
@@ -258,6 +278,22 @@ abstract class ApexManager {
return (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
@Override
List<ActiveApexInfo> 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<ActiveApexInfo> 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<ActiveApexInfo> 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() {

View File

@@ -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

View File

@@ -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;
@@ -376,6 +377,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.
@@ -590,16 +592,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 {
@@ -759,7 +751,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<SystemPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList(
Arrays.asList(
new SystemPartition(Environment.getRootDirectory(), 0 /* scanFlag */,
false /* hasOverlays */),
new SystemPartition(Environment.getVendorDirectory(), SCAN_AS_VENDOR,
true /* hasOverlays */),
new SystemPartition(Environment.getOdmDirectory(), SCAN_AS_ODM,
true /* hasOverlays */),
new SystemPartition(Environment.getOemDirectory(), SCAN_AS_OEM,
true /* hasOverlays */),
new SystemPartition(Environment.getProductDirectory(), SCAN_AS_PRODUCT,
true /* hasOverlays */),
new SystemPartition(Environment.getSystemExtDirectory(), SCAN_AS_SYSTEM_EXT,
true /* hasOverlays */)));
private final List<SystemPartition> 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 {
@@ -2426,9 +2442,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());
@@ -2521,7 +2598,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
@@ -2656,215 +2744,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<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
@@ -3032,89 +2940,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 {
@@ -18587,70 +18432,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;
}
/*
@@ -18762,23 +18554,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);

View File

@@ -3510,7 +3510,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),

View File

@@ -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);
}
}
}