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:
@@ -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,
|
||||||
|
|||||||
@@ -739,12 +739,123 @@ 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;
|
||||||
public final String apk;
|
public final String apk;
|
||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user