Merge changes from topic "aosp-apk-in-apex"
* changes: DO NOT MERGE: Fixes NPE when preparing app data during init Support privileged apps installed in APEX. Support non-privileged APKs in APEX. Refactors initial directory scan to be dryer
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<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 {
|
||||
@@ -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<String> 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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user