Merge "Apply static RRO when parsing Android manifest of a target package" into oc-dev

am: dc326a883e

Change-Id: I7803a75b0c0a863e5491b3faa3a03c03f46036e8
This commit is contained in:
Jaekyun Seok
2017-04-28 09:55:01 +00:00
committed by android-build-merger
2 changed files with 152 additions and 6 deletions

View File

@@ -547,6 +547,8 @@ public class PackageParser {
*/ */
public interface Callback { public interface Callback {
boolean hasFeature(String feature); boolean hasFeature(String feature);
String[] getOverlayPaths(String targetPackageName, String targetPath);
String[] getOverlayApks(String targetPackageName);
} }
/** /**
@@ -563,6 +565,14 @@ public class PackageParser {
@Override public boolean hasFeature(String feature) { @Override public boolean hasFeature(String feature) {
return mPm.hasSystemFeature(feature); return mPm.hasSystemFeature(feature);
} }
@Override public String[] getOverlayPaths(String targetPackageName, String targetPath) {
return null;
}
@Override public String[] getOverlayApks(String targetPackageName) {
return null;
}
} }
/** /**
@@ -1054,7 +1064,19 @@ public class PackageParser {
try { try {
final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath()); final byte[] bytes = IoUtils.readFileAsByteArray(cacheFile.getAbsolutePath());
return fromCacheEntry(bytes); 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;
} catch (Exception e) { } catch (Exception e) {
Slog.w(TAG, "Error reading package cache: ", e); Slog.w(TAG, "Error reading package cache: ", e);
@@ -1238,7 +1260,7 @@ public class PackageParser {
parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
final String[] outError = new String[1]; final String[] outError = new String[1];
final Package pkg = parseBaseApk(res, parser, flags, outError); final Package pkg = parseBaseApk(apkPath, res, parser, flags, outError);
if (pkg == null) { if (pkg == null) {
throw new PackageParserException(mParseError, throw new PackageParserException(mParseError,
apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]);
@@ -1938,6 +1960,7 @@ public class PackageParser {
* need to consider whether they should be supported by split APKs and child * need to consider whether they should be supported by split APKs and child
* packages. * packages.
* *
* @param apkPath The package apk file path
* @param res The resources from which to resolve values * @param res The resources from which to resolve values
* @param parser The manifest parser * @param parser The manifest parser
* @param flags Flags how to parse * @param flags Flags how to parse
@@ -1947,7 +1970,7 @@ public class PackageParser {
* @throws XmlPullParserException * @throws XmlPullParserException
* @throws IOException * @throws IOException
*/ */
private Package parseBaseApk(Resources res, XmlResourceParser parser, int flags, private Package parseBaseApk(String apkPath, Resources res, XmlResourceParser parser, int flags,
String[] outError) throws XmlPullParserException, IOException { String[] outError) throws XmlPullParserException, IOException {
final String splitName; final String splitName;
final String pkgName; final String pkgName;
@@ -1967,6 +1990,15 @@ public class PackageParser {
return null; 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); final Package pkg = new Package(pkgName);
TypedArray sa = res.obtainAttributes(parser, TypedArray sa = res.obtainAttributes(parser,

View File

@@ -739,11 +739,122 @@ public class PackageManagerService extends IPackageManager.Stub
@GuardedBy("mPackages") @GuardedBy("mPackages")
final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>(); final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>();
final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() { class PackageParserCallback implements PackageParser.Callback {
@Override public boolean hasFeature(String feature) { @Override public final boolean hasFeature(String feature) {
return PackageManagerService.this.hasSystemFeature(feature, 0); return PackageManagerService.this.hasSystemFeature(feature, 0);
} }
final List<PackageParser.Package> getStaticOverlayPackagesLocked(
Collection<PackageParser.Package> allPackages, String targetPackageName) {
List<PackageParser.Package> overlayPackages = null;
for (PackageParser.Package p : allPackages) {
if (targetPackageName.equals(p.mOverlayTarget) && p.mIsStaticOverlay) {
if (overlayPackages == null) {
overlayPackages = new ArrayList<PackageParser.Package>();
}
overlayPackages.add(p);
}
}
if (overlayPackages != null) {
Comparator<PackageParser.Package> cmp = new Comparator<PackageParser.Package>() {
public int compare(PackageParser.Package p1, PackageParser.Package p2) {
return p1.mOverlayPriority - p2.mOverlayPriority;
}
}; };
Collections.sort(overlayPackages, cmp);
}
return overlayPackages;
}
final String[] getStaticOverlayPathsLocked(Collection<PackageParser.Package> allPackages,
String targetPackageName, String targetPath) {
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 =
getStaticOverlayPackagesLocked(allPackages, targetPackageName);
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<String>();
}
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<String>();
}
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) {
synchronized (mPackages) {
return getStaticOverlayPathsLocked(
mPackages.values(), targetPackageName, 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.mIsStaticOverlay) {
if (mOverlayPackages == null) {
mOverlayPackages = new ArrayList<PackageParser.Package>();
}
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.
// Moreover holding mPackages on each parsing thread causes dead-lock.
return mOverlayPackages == null ? null :
getStaticOverlayPathsLocked(mOverlayPackages, targetPackageName, targetPath);
}
}
final PackageParser.Callback mPackageParserCallback = new PackageParserCallback();
final ParallelPackageParserCallback mParallelPackageParserCallback =
new ParallelPackageParserCallback();
public static final class SharedLibraryEntry { public static final class SharedLibraryEntry {
public final String path; public final String path;
@@ -2453,6 +2564,8 @@ public class PackageManagerService extends IPackageManager.Stub
| PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_IS_SYSTEM_DIR
| PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0);
mParallelPackageParserCallback.findStaticOverlayPackages();
// Find base frameworks (resource packages without code). // Find base frameworks (resource packages without code).
scanDirTracedLI(frameworkDir, mDefParseFlags scanDirTracedLI(frameworkDir, mDefParseFlags
| PackageParser.PARSE_IS_SYSTEM | PackageParser.PARSE_IS_SYSTEM
@@ -7856,7 +7969,8 @@ public class PackageManagerService extends IPackageManager.Stub
+ " flags=0x" + Integer.toHexString(parseFlags)); + " flags=0x" + Integer.toHexString(parseFlags));
} }
ParallelPackageParser parallelPackageParser = new ParallelPackageParser( ParallelPackageParser parallelPackageParser = new ParallelPackageParser(
mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback); mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir,
mParallelPackageParserCallback);
// Submit files for parsing in parallel // Submit files for parsing in parallel
int fileCount = 0; int fileCount = 0;