Loading core/java/android/content/pm/PackageParser.java +35 −3 Original line number Diff line number Diff line Loading @@ -547,6 +547,8 @@ public class PackageParser { */ public interface Callback { boolean hasFeature(String feature); String[] getOverlayPaths(String targetPackageName, String targetPath); String[] getOverlayApks(String targetPackageName); } /** Loading @@ -563,6 +565,14 @@ 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; } } /** Loading Loading @@ -1054,7 +1064,19 @@ public class PackageParser { try { 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) { Slog.w(TAG, "Error reading package cache: ", e); Loading Loading @@ -1238,7 +1260,7 @@ public class PackageParser { parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); 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) { throw new PackageParserException(mParseError, apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); Loading Loading @@ -1938,6 +1960,7 @@ 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 Loading @@ -1947,7 +1970,7 @@ public class PackageParser { * @throws XmlPullParserException * @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 { final String splitName; final String pkgName; Loading @@ -1967,6 +1990,15 @@ 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, Loading services/core/java/com/android/server/pm/PackageManagerService.java +117 −3 Original line number Diff line number Diff line Loading @@ -739,11 +739,122 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>(); final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() { @Override public boolean hasFeature(String feature) { class PackageParserCallback implements PackageParser.Callback { @Override public final boolean hasFeature(String feature) { 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 final String path; Loading Loading @@ -2453,6 +2564,8 @@ public class PackageManagerService extends IPackageManager.Stub | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); mParallelPackageParserCallback.findStaticOverlayPackages(); // Find base frameworks (resource packages without code). scanDirTracedLI(frameworkDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM Loading Loading @@ -7856,7 +7969,8 @@ public class PackageManagerService extends IPackageManager.Stub + " flags=0x" + Integer.toHexString(parseFlags)); } ParallelPackageParser parallelPackageParser = new ParallelPackageParser( mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback); mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mParallelPackageParserCallback); // Submit files for parsing in parallel int fileCount = 0; Loading
core/java/android/content/pm/PackageParser.java +35 −3 Original line number Diff line number Diff line Loading @@ -547,6 +547,8 @@ public class PackageParser { */ public interface Callback { boolean hasFeature(String feature); String[] getOverlayPaths(String targetPackageName, String targetPath); String[] getOverlayApks(String targetPackageName); } /** Loading @@ -563,6 +565,14 @@ 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; } } /** Loading Loading @@ -1054,7 +1064,19 @@ public class PackageParser { try { 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) { Slog.w(TAG, "Error reading package cache: ", e); Loading Loading @@ -1238,7 +1260,7 @@ public class PackageParser { parser = assets.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME); 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) { throw new PackageParserException(mParseError, apkPath + " (at " + parser.getPositionDescription() + "): " + outError[0]); Loading Loading @@ -1938,6 +1960,7 @@ 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 Loading @@ -1947,7 +1970,7 @@ public class PackageParser { * @throws XmlPullParserException * @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 { final String splitName; final String pkgName; Loading @@ -1967,6 +1990,15 @@ 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, Loading
services/core/java/com/android/server/pm/PackageManagerService.java +117 −3 Original line number Diff line number Diff line Loading @@ -739,11 +739,122 @@ public class PackageManagerService extends IPackageManager.Stub @GuardedBy("mPackages") final SparseArray<Map<String, Integer>> mChangedPackagesSequenceNumbers = new SparseArray<>(); final PackageParser.Callback mPackageParserCallback = new PackageParser.Callback() { @Override public boolean hasFeature(String feature) { class PackageParserCallback implements PackageParser.Callback { @Override public final boolean hasFeature(String feature) { 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 final String path; Loading Loading @@ -2453,6 +2564,8 @@ public class PackageManagerService extends IPackageManager.Stub | PackageParser.PARSE_IS_SYSTEM_DIR | PackageParser.PARSE_TRUSTED_OVERLAY, scanFlags | SCAN_TRUSTED_OVERLAY, 0); mParallelPackageParserCallback.findStaticOverlayPackages(); // Find base frameworks (resource packages without code). scanDirTracedLI(frameworkDir, mDefParseFlags | PackageParser.PARSE_IS_SYSTEM Loading Loading @@ -7856,7 +7969,8 @@ public class PackageManagerService extends IPackageManager.Stub + " flags=0x" + Integer.toHexString(parseFlags)); } ParallelPackageParser parallelPackageParser = new ParallelPackageParser( mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mPackageParserCallback); mSeparateProcesses, mOnlyCore, mMetrics, mCacheDir, mParallelPackageParserCallback); // Submit files for parsing in parallel int fileCount = 0;