Remove overlay logic from package manager and parser

Consolidate all knowledge about overlays to the overlay manager (except
static RROs that target "android": these are handled from native code in
order to be loaded as part of Zygote boot).

This removes the ability to overlay AndroidManifest.xml. There are some
use-cases where overlaying a manifest makes sense [e.g. changing an
app's label or icon or what components should be enabled by default] but
the opposite is also true [e.g. permissions]. Support for manifests can
be introduced again gradually with these goals in mind:

  - should not happen during parsing [which represents the immutable
    truth as read from disk]

  - should happen during scanning [which applies mutable settings to a
    parsed package]

  - be limited in what can be modified

Bug: 78808368
Test: builds, boots
Change-Id: I12c16fce65b1e68876f0c9acd7e2a61405e64435
This commit is contained in:
Mårten Kongstad
2018-12-06 13:40:12 +01:00
committed by Winson
parent 3841ec1593
commit 588784dc25
2 changed files with 4 additions and 154 deletions

View File

@@ -591,8 +591,6 @@ public class PackageParser {
*/
public interface Callback {
boolean hasFeature(String feature);
String[] getOverlayPaths(String targetPackageName, String targetPath);
String[] getOverlayApks(String targetPackageName);
}
/**
@@ -609,14 +607,6 @@ public class PackageParser {
@Override public boolean hasFeature(String feature) {
return mPm.hasSystemFeature(feature);
}
@Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
return null;
}
@Override public String[] getOverlayApks(String targetPackageName) {
return null;
}
}
/**
@@ -1168,19 +1158,7 @@ public class PackageParser {
}
final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
Package p = fromCacheEntry(bytes);
if (mCallback != null) {
String[] overlayApks = mCallback.getOverlayApks(p.packageName);
if (overlayApks != null && overlayApks.length > 0) {
for (String overlayApk : overlayApks) {
// If a static RRO is updated, return null.
if (!isCacheUpToDate(new File(overlayApk), cacheFile)) {
return null;
}
}
}
}
return p;
return fromCacheEntry(bytes);
} catch (Throwable e) {
Slog.w(TAG, "Error reading package cache: ", e);
@@ -1354,7 +1332,7 @@ public class PackageParser {
final Resources res = new Resources(assets, mMetrics, null);
final String[] outError = new String[1];
final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
final Package pkg = parseBaseApk(res, parser, flags, outError);
if (pkg == null) {
throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
@@ -1911,7 +1889,6 @@ public class PackageParser {
* need to consider whether they should be supported by split APKs and child
* packages.
*
* @param apkPath The package apk file path
* @param res The resources from which to resolve values
* @param parser The manifest parser
* @param flags Flags how to parse
@@ -1921,8 +1898,7 @@ public class PackageParser {
* @throws XmlPullParserException
* @throws IOException
*/
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException {
final String splitName;
final String pkgName;
@@ -1942,15 +1918,6 @@ public class PackageParser {
return null;
}
if (mCallback != null) {
String[] overlayPaths = mCallback.getOverlayPaths(pkgName, apkPath);
if (overlayPaths != null && overlayPaths.length > 0) {
for (String overlayPath : overlayPaths) {
res.getAssets().addOverlayPath(overlayPath);
}
}
}
final Package pkg = new Package(pkgName);
TypedArray sa = res.obtainAttributes(parser,

View File

@@ -753,124 +753,9 @@ public class PackageManagerService extends IPackageManager.Stub
@Override public final boolean hasFeature(String feature) {
return PackageManagerService.this.hasSystemFeature(feature, 0);
}
final List<PackageParser.Package> getStaticOverlayPackages(
Collection<PackageParser.Package> allPackages, String targetPackageName) {
if ("android".equals(targetPackageName)) {
// Static RROs targeting to "android", ie framework-res.apk, are already applied by
// native AssetManager.
return null;
}
List<PackageParser.Package> overlayPackages = null;
for (PackageParser.Package p : allPackages) {
if (targetPackageName.equals(p.mOverlayTarget) && p.mOverlayIsStatic) {
if (overlayPackages == null) {
overlayPackages = new ArrayList<>();
}
overlayPackages.add(p);
}
}
if (overlayPackages != null) {
Comparator<PackageParser.Package> cmp =
Comparator.comparingInt(p -> p.mOverlayPriority);
overlayPackages.sort(cmp);
}
return overlayPackages;
}
final String[] getStaticOverlayPaths(List<PackageParser.Package> overlayPackages,
String targetPath) {
if (overlayPackages == null || overlayPackages.isEmpty()) {
return null;
}
List<String> overlayPathList = null;
for (PackageParser.Package overlayPackage : overlayPackages) {
if (targetPath == null) {
if (overlayPathList == null) {
overlayPathList = new ArrayList<>();
}
overlayPathList.add(overlayPackage.baseCodePath);
continue;
}
try {
// Creates idmaps for system to parse correctly the Android manifest of the
// target package.
//
// OverlayManagerService will update each of them with a correct gid from its
// target package app id.
mInstaller.idmap(targetPath, overlayPackage.baseCodePath,
UserHandle.getSharedAppGid(
UserHandle.getUserGid(UserHandle.USER_SYSTEM)));
if (overlayPathList == null) {
overlayPathList = new ArrayList<>();
}
overlayPathList.add(overlayPackage.baseCodePath);
} catch (InstallerException e) {
Slog.e(TAG, "Failed to generate idmap for " + targetPath + " and " +
overlayPackage.baseCodePath);
}
}
return overlayPathList == null ? null : overlayPathList.toArray(new String[0]);
}
String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
List<PackageParser.Package> overlayPackages;
synchronized (mInstallLock) {
synchronized (mPackages) {
overlayPackages = getStaticOverlayPackages(
mPackages.values(), targetPackageName);
}
// It is safe to keep overlayPackages without holding mPackages because static overlay
// packages can't be uninstalled or disabled.
return getStaticOverlayPaths(overlayPackages, targetPath);
}
}
@Override public final String[] getOverlayApks(String targetPackageName) {
return getStaticOverlayPaths(targetPackageName, null);
}
@Override public final String[] getOverlayPaths(String targetPackageName,
String targetPath) {
return getStaticOverlayPaths(targetPackageName, targetPath);
}
}
class ParallelPackageParserCallback extends PackageParserCallback {
List<PackageParser.Package> mOverlayPackages = null;
void findStaticOverlayPackages() {
synchronized (mPackages) {
for (PackageParser.Package p : mPackages.values()) {
if (p.mOverlayIsStatic) {
if (mOverlayPackages == null) {
mOverlayPackages = new ArrayList<>();
}
mOverlayPackages.add(p);
}
}
}
}
@Override
synchronized String[] getStaticOverlayPaths(String targetPackageName, String targetPath) {
// We can trust mOverlayPackages without holding mPackages because package uninstall
// can't happen while running parallel parsing.
// And we can call mInstaller inside getStaticOverlayPaths without holding mInstallLock
// because mInstallLock is held before running parallel parsing.
// Moreover holding mPackages or mInstallLock on each parsing thread causes dead-lock.
return mOverlayPackages == null ? null :
getStaticOverlayPaths(
getStaticOverlayPackages(mOverlayPackages, targetPackageName),
targetPath);
}
}
final PackageParser.Callback mPackageParserCallback = new PackageParserCallback();
final ParallelPackageParserCallback mParallelPackageParserCallback =
new ParallelPackageParserCallback();
// Currently known shared libraries.
final ArrayMap<String, LongSparseArray<SharedLibraryInfo>> mSharedLibraries = new ArrayMap<>();
@@ -2534,8 +2419,6 @@ public class PackageManagerService extends IPackageManager.Stub
| SCAN_AS_ODM,
0);
mParallelPackageParserCallback.findStaticOverlayPackages();
// Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir,
mDefParseFlags
@@ -8571,7 +8454,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
try (ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback)) {
mPackageParserCallback)) {
// Submit files for parsing in parallel
int fileCount = 0;
for (File file : files) {